summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCasey Marshall <csm@gnu.org>2006-01-26 02:25:07 +0000
committerCasey Marshall <csm@gnu.org>2006-01-26 02:25:07 +0000
commitbd5a522ce73b442dd07099c264bf251e6d8d6a63 (patch)
treeb1cdc8f04689d9ea082589d3a7e61fef847ac1fa
parentbf20436907439f2c47dc22eea41b3d3d5808aa74 (diff)
downloadclasspath-bd5a522ce73b442dd07099c264bf251e6d8d6a63.tar.gz
2006-01-25 Casey Marshall <csm@gnu.org>
Merging GNU Crypto and Jessie. * NEWS: mention the merge in the 0.21 notes. * gnu/classpath/debug/Component.java (SSL_APPLICATION): removed. (SSL_RECORD_LAYER): new constants. * gnu/java/security/provider/Gnu.java (<init>): add new algorithms to provider. * resource/java/security/classpath.security: add new providers. * gnu/javax/crypto/assembly/Assembly.java, gnu/javax/crypto/assembly/Cascade.java, gnu/javax/crypto/assembly/CascadeStage.java, gnu/javax/crypto/assembly/CascadeTransformer.java, gnu/javax/crypto/assembly/DeflateTransformer.java, gnu/javax/crypto/assembly/Direction.java, gnu/javax/crypto/assembly/LoopbackTransformer.java, gnu/javax/crypto/assembly/ModeStage.java, gnu/javax/crypto/assembly/Operation.java, gnu/javax/crypto/assembly/PaddingTransformer.java, gnu/javax/crypto/assembly/Stage.java, gnu/javax/crypto/assembly/Transformer.java, gnu/javax/crypto/assembly/TransformerException.java, gnu/javax/crypto/cipher/Anubis.java, gnu/javax/crypto/cipher/BaseCipher.java, gnu/javax/crypto/cipher/Blowfish.java, gnu/javax/crypto/cipher/Cast5.java, gnu/javax/crypto/cipher/CipherFactory.java, gnu/javax/crypto/cipher/DES.java, gnu/javax/crypto/cipher/IBlockCipher.java, gnu/javax/crypto/cipher/IBlockCipherSpi.java, gnu/javax/crypto/cipher/Khazad.java, gnu/javax/crypto/cipher/NullCipher.java, gnu/javax/crypto/cipher/Rijndael.java, gnu/javax/crypto/cipher/Serpent.java, gnu/javax/crypto/cipher/Square.java, gnu/javax/crypto/cipher/TripleDES.java, gnu/javax/crypto/cipher/Twofish.java, gnu/javax/crypto/cipher/WeakKeyException.java, gnu/javax/crypto/jce/GnuCrypto.java, gnu/javax/crypto/jce/GnuSasl.java, gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java, gnu/javax/crypto/jce/cipher/AESSpi.java, gnu/javax/crypto/jce/cipher/ARCFourSpi.java, gnu/javax/crypto/jce/cipher/AnubisSpi.java, gnu/javax/crypto/jce/cipher/BlowfishSpi.java, gnu/javax/crypto/jce/cipher/Cast5Spi.java, gnu/javax/crypto/jce/cipher/CipherAdapter.java, gnu/javax/crypto/jce/cipher/DESSpi.java, gnu/javax/crypto/jce/cipher/KhazadSpi.java, gnu/javax/crypto/jce/cipher/NullCipherSpi.java, gnu/javax/crypto/jce/cipher/PBES2.java, gnu/javax/crypto/jce/cipher/RijndaelSpi.java, gnu/javax/crypto/jce/cipher/SerpentSpi.java, gnu/javax/crypto/jce/cipher/SquareSpi.java, gnu/javax/crypto/jce/cipher/TripleDESSpi.java, gnu/javax/crypto/jce/cipher/TwofishSpi.java, gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java, gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java, gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java, gnu/javax/crypto/jce/keyring/GnuKeyring.java, gnu/javax/crypto/jce/mac/HMacHavalSpi.java, gnu/javax/crypto/jce/mac/HMacMD2Spi.java, gnu/javax/crypto/jce/mac/HMacMD4Spi.java, gnu/javax/crypto/jce/mac/HMacMD5Spi.java, gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java, gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java, gnu/javax/crypto/jce/mac/HMacSHA160Spi.java, gnu/javax/crypto/jce/mac/HMacSHA256Spi.java, gnu/javax/crypto/jce/mac/HMacSHA384Spi.java, gnu/javax/crypto/jce/mac/HMacSHA512Spi.java, gnu/javax/crypto/jce/mac/HMacTigerSpi.java, gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java, gnu/javax/crypto/jce/mac/MacAdapter.java, gnu/javax/crypto/jce/mac/OMacAnubisImpl.java, gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java, gnu/javax/crypto/jce/mac/OMacCast5Impl.java, gnu/javax/crypto/jce/mac/OMacDESImpl.java, gnu/javax/crypto/jce/mac/OMacImpl.java, gnu/javax/crypto/jce/mac/OMacKhazadImpl.java, gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java, gnu/javax/crypto/jce/mac/OMacSerpentImpl.java, gnu/javax/crypto/jce/mac/OMacSquareImpl.java, gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java, gnu/javax/crypto/jce/mac/OMacTwofishImpl.java, gnu/javax/crypto/jce/mac/TMMH16Spi.java, gnu/javax/crypto/jce/mac/UHash32Spi.java, gnu/javax/crypto/jce/mac/UMac32Spi.java, gnu/javax/crypto/jce/params/BlockCipherParameters.java, gnu/javax/crypto/jce/params/DEREncodingException.java, gnu/javax/crypto/jce/params/DERReader.java, gnu/javax/crypto/jce/params/DERWriter.java, gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java, gnu/javax/crypto/jce/prng/CSPRNGSpi.java, gnu/javax/crypto/jce/prng/FortunaImpl.java, gnu/javax/crypto/jce/prng/ICMRandomSpi.java, gnu/javax/crypto/jce/prng/UMacRandomSpi.java, gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java, gnu/javax/crypto/jce/spec/TMMHParameterSpec.java, gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java, gnu/javax/crypto/key/BaseKeyAgreementParty.java, gnu/javax/crypto/key/GnuSecretKey.java, gnu/javax/crypto/key/IKeyAgreementParty.java, gnu/javax/crypto/key/IncomingMessage.java, gnu/javax/crypto/key/KeyAgreementException.java, gnu/javax/crypto/key/KeyAgreementFactory.java, gnu/javax/crypto/key/OutgoingMessage.java, gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java, gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java, gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java, gnu/javax/crypto/key/dh/DiffieHellmanSender.java, gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java, gnu/javax/crypto/key/dh/ElGamalReceiver.java, gnu/javax/crypto/key/dh/ElGamalSender.java, gnu/javax/crypto/key/dh/GnuDHKey.java, gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java, gnu/javax/crypto/key/dh/GnuDHPrivateKey.java, gnu/javax/crypto/key/dh/GnuDHPublicKey.java, gnu/javax/crypto/key/dh/RFC2631.java, gnu/javax/crypto/key/srp6/SRP6Host.java, gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java, gnu/javax/crypto/key/srp6/SRP6SaslClient.java, gnu/javax/crypto/key/srp6/SRP6SaslServer.java, gnu/javax/crypto/key/srp6/SRP6TLSClient.java, gnu/javax/crypto/key/srp6/SRP6TLSServer.java, gnu/javax/crypto/key/srp6/SRP6User.java, gnu/javax/crypto/key/srp6/SRPAlgorithm.java, gnu/javax/crypto/key/srp6/SRPKey.java, gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java, gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java, gnu/javax/crypto/key/srp6/SRPPrivateKey.java, gnu/javax/crypto/key/srp6/SRPPublicKey.java, gnu/javax/crypto/keyring/AuthenticatedEntry.java, gnu/javax/crypto/keyring/BaseKeyring.java, gnu/javax/crypto/keyring/BinaryDataEntry.java, gnu/javax/crypto/keyring/CertPathEntry.java, gnu/javax/crypto/keyring/CertificateEntry.java, gnu/javax/crypto/keyring/CompressedEntry.java, gnu/javax/crypto/keyring/EncryptedEntry.java, gnu/javax/crypto/keyring/Entry.java, gnu/javax/crypto/keyring/EnvelopeEntry.java, gnu/javax/crypto/keyring/GnuPrivateKeyring.java, gnu/javax/crypto/keyring/GnuPublicKeyring.java, gnu/javax/crypto/keyring/IKeyring.java, gnu/javax/crypto/keyring/IPrivateKeyring.java, gnu/javax/crypto/keyring/IPublicKeyring.java, gnu/javax/crypto/keyring/MalformedKeyringException.java, gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java, gnu/javax/crypto/keyring/MeteredInputStream.java, gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java, gnu/javax/crypto/keyring/PasswordEncryptedEntry.java, gnu/javax/crypto/keyring/PasswordProtectedEntry.java, gnu/javax/crypto/keyring/PrimitiveEntry.java, gnu/javax/crypto/keyring/PrivateKeyEntry.java, gnu/javax/crypto/keyring/Properties.java, gnu/javax/crypto/keyring/PublicKeyEntry.java, gnu/javax/crypto/mac/BaseMac.java, gnu/javax/crypto/mac/HMac.java, gnu/javax/crypto/mac/HMacFactory.java, gnu/javax/crypto/mac/IMac.java, gnu/javax/crypto/mac/MacFactory.java, gnu/javax/crypto/mac/MacInputStream.java, gnu/javax/crypto/mac/MacOutputStream.java, gnu/javax/crypto/mac/OMAC.java, gnu/javax/crypto/mac/TMMH16.java, gnu/javax/crypto/mac/UHash32.java, gnu/javax/crypto/mac/UMac32.java, gnu/javax/crypto/mode/BaseMode.java, gnu/javax/crypto/mode/CBC.java, gnu/javax/crypto/mode/CFB.java, gnu/javax/crypto/mode/CTR.java, gnu/javax/crypto/mode/EAX.java, gnu/javax/crypto/mode/ECB.java, gnu/javax/crypto/mode/IAuthenticatedMode.java, gnu/javax/crypto/mode/ICM.java, gnu/javax/crypto/mode/IMode.java, gnu/javax/crypto/mode/ModeFactory.java, gnu/javax/crypto/mode/OFB.java, gnu/javax/crypto/pad/BasePad.java, gnu/javax/crypto/pad/IPad.java, gnu/javax/crypto/pad/PKCS1_V1_5.java, gnu/javax/crypto/pad/PKCS7.java, gnu/javax/crypto/pad/PadFactory.java, gnu/javax/crypto/pad/SSL3.java, gnu/javax/crypto/pad/TBC.java, gnu/javax/crypto/pad/TLS1.java, gnu/javax/crypto/pad/WrongPaddingException.java, gnu/javax/crypto/prng/ARCFour.java, gnu/javax/crypto/prng/CSPRNG.java, gnu/javax/crypto/prng/Fortuna.java, gnu/javax/crypto/prng/ICMGenerator.java, gnu/javax/crypto/prng/IPBE.java, gnu/javax/crypto/prng/PBKDF2.java, gnu/javax/crypto/prng/PRNGFactory.java, gnu/javax/crypto/prng/UMacGenerator.java, gnu/javax/crypto/sasl/AuthInfo.java, gnu/javax/crypto/sasl/AuthInfoProviderFactory.java, gnu/javax/crypto/sasl/ClientFactory.java, gnu/javax/crypto/sasl/ClientMechanism.java, gnu/javax/crypto/sasl/ConfidentialityException.java, gnu/javax/crypto/sasl/IAuthInfoProvider.java, gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java, gnu/javax/crypto/sasl/IllegalMechanismStateException.java, gnu/javax/crypto/sasl/InputBuffer.java, gnu/javax/crypto/sasl/IntegrityException.java, gnu/javax/crypto/sasl/NoSuchMechanismException.java, gnu/javax/crypto/sasl/NoSuchUserException.java, gnu/javax/crypto/sasl/OutputBuffer.java, gnu/javax/crypto/sasl/SaslEncodingException.java, gnu/javax/crypto/sasl/SaslInputStream.java, gnu/javax/crypto/sasl/SaslOutputStream.java, gnu/javax/crypto/sasl/SaslUtil.java, gnu/javax/crypto/sasl/ServerFactory.java, gnu/javax/crypto/sasl/ServerMechanism.java, gnu/javax/crypto/sasl/UserAlreadyExistsException.java, gnu/javax/crypto/sasl/anonymous/AnonymousClient.java, gnu/javax/crypto/sasl/anonymous/AnonymousServer.java, gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java, gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java, gnu/javax/crypto/sasl/crammd5/CramMD5Client.java, gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java, gnu/javax/crypto/sasl/crammd5/CramMD5Server.java, gnu/javax/crypto/sasl/crammd5/CramMD5Util.java, gnu/javax/crypto/sasl/crammd5/PasswordFile.java, gnu/javax/crypto/sasl/plain/PasswordFile.java, gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java, gnu/javax/crypto/sasl/plain/PlainClient.java, gnu/javax/crypto/sasl/plain/PlainRegistry.java, gnu/javax/crypto/sasl/plain/PlainServer.java, gnu/javax/crypto/sasl/srp/CALG.java, gnu/javax/crypto/sasl/srp/ClientStore.java, gnu/javax/crypto/sasl/srp/IALG.java, gnu/javax/crypto/sasl/srp/KDF.java, gnu/javax/crypto/sasl/srp/PasswordFile.java, gnu/javax/crypto/sasl/srp/SRP.java, gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java, gnu/javax/crypto/sasl/srp/SRPClient.java, gnu/javax/crypto/sasl/srp/SRPRegistry.java, gnu/javax/crypto/sasl/srp/SRPServer.java, gnu/javax/crypto/sasl/srp/SecurityContext.java, gnu/javax/crypto/sasl/srp/ServerStore.java, gnu/javax/crypto/sasl/srp/StoreEntry.java, gnu/javax/net/ssl/Base64.java, gnu/javax/net/ssl/EntropySource.java, gnu/javax/net/ssl/NullManagerParameters.java, gnu/javax/net/ssl/PrivateCredentials.java, gnu/javax/net/ssl/SRPManagerParameters.java, gnu/javax/net/ssl/SRPTrustManager.java, gnu/javax/net/ssl/StaticTrustAnchors.java, gnu/javax/net/ssl/provider/Alert.java, gnu/javax/net/ssl/provider/AlertException.java, gnu/javax/net/ssl/provider/Certificate.java, gnu/javax/net/ssl/provider/CertificateRequest.java, gnu/javax/net/ssl/provider/CertificateType.java, gnu/javax/net/ssl/provider/CertificateVerify.java, gnu/javax/net/ssl/provider/CipherSuite.java, gnu/javax/net/ssl/provider/ClientHello.java, gnu/javax/net/ssl/provider/ClientKeyExchange.java, gnu/javax/net/ssl/provider/CompressionMethod.java, gnu/javax/net/ssl/provider/Constructed.java, gnu/javax/net/ssl/provider/ContentType.java, gnu/javax/net/ssl/provider/Context.java, gnu/javax/net/ssl/provider/DiffieHellman.java, gnu/javax/net/ssl/provider/DigestInputStream.java, gnu/javax/net/ssl/provider/DigestOutputStream.java, gnu/javax/net/ssl/provider/Enumerated.java, gnu/javax/net/ssl/provider/Extension.java, gnu/javax/net/ssl/provider/Extensions.java, gnu/javax/net/ssl/provider/Finished.java, gnu/javax/net/ssl/provider/GNUSecurityParameters.java, gnu/javax/net/ssl/provider/Handshake.java, gnu/javax/net/ssl/provider/JCESecurityParameters.java, gnu/javax/net/ssl/provider/JDBCSessionContext.java, gnu/javax/net/ssl/provider/Jessie.java, gnu/javax/net/ssl/provider/JessieDHPrivateKey.java, gnu/javax/net/ssl/provider/JessieDHPublicKey.java, gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java, gnu/javax/net/ssl/provider/JessieRSAPublicKey.java, gnu/javax/net/ssl/provider/KeyPool.java, gnu/javax/net/ssl/provider/MacException.java, gnu/javax/net/ssl/provider/OverflowException.java, gnu/javax/net/ssl/provider/PRNG.java, gnu/javax/net/ssl/provider/ProtocolVersion.java, gnu/javax/net/ssl/provider/Random.java, gnu/javax/net/ssl/provider/RecordInput.java, gnu/javax/net/ssl/provider/RecordInputStream.java, gnu/javax/net/ssl/provider/RecordOutputStream.java, gnu/javax/net/ssl/provider/RecordingInputStream.java, gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java, gnu/javax/net/ssl/provider/SSLHMac.java, gnu/javax/net/ssl/provider/SSLRSASignature.java, gnu/javax/net/ssl/provider/SSLRandom.java, gnu/javax/net/ssl/provider/SSLServerSocket.java, gnu/javax/net/ssl/provider/SSLServerSocketFactory.java, gnu/javax/net/ssl/provider/SSLSocket.java, gnu/javax/net/ssl/provider/SSLSocketFactory.java, gnu/javax/net/ssl/provider/SSLSocketInputStream.java, gnu/javax/net/ssl/provider/SSLSocketOutputStream.java, gnu/javax/net/ssl/provider/SecurityParameters.java, gnu/javax/net/ssl/provider/ServerHello.java, gnu/javax/net/ssl/provider/ServerKeyExchange.java, gnu/javax/net/ssl/provider/Session.java, gnu/javax/net/ssl/provider/SessionContext.java, gnu/javax/net/ssl/provider/Signature.java, gnu/javax/net/ssl/provider/SynchronizedRandom.java, gnu/javax/net/ssl/provider/TLSHMac.java, gnu/javax/net/ssl/provider/TLSRandom.java, gnu/javax/net/ssl/provider/Util.java, gnu/javax/net/ssl/provider/X509KeyManagerFactory.java, gnu/javax/net/ssl/provider/X509TrustManagerFactory.java, gnu/javax/net/ssl/provider/XMLSessionContext.java, gnu/javax/security/auth/Password.java, gnu/javax/security/auth/callback/AWTCallbackHandler.java, gnu/javax/security/auth/callback/AbstractCallbackHandler.java, gnu/javax/security/auth/callback/ConsoleCallbackHandler.java, gnu/javax/security/auth/callback/DefaultCallbackHandler.java, gnu/javax/security/auth/callback/GnuCallbacks.java, gnu/javax/security/auth/callback/SwingCallbackHandler.java, gnu/java/security/Registry.java, gnu/java/security/Properties.java, gnu/java/security/hash/BaseHash.java, gnu/java/security/hash/HashFactory.java, gnu/java/security/hash/Haval.java, gnu/java/security/hash/IMessageDigest.java, gnu/java/security/hash/MD2.java, gnu/java/security/hash/MD4.java, gnu/java/security/hash/MD5.java, gnu/java/security/hash/RipeMD128.java, gnu/java/security/hash/RipeMD160.java, gnu/java/security/hash/Sha160.java, gnu/java/security/hash/Sha256.java, gnu/java/security/hash/Sha384.java, gnu/java/security/hash/Sha512.java, gnu/java/security/hash/Tiger.java, gnu/java/security/hash/Whirlpool.java, gnu/java/security/jce/hash/HavalSpi.java, gnu/java/security/jce/hash/MD2Spi.java, gnu/java/security/jce/hash/MD4Spi.java, gnu/java/security/jce/hash/MD5Spi.java, gnu/java/security/jce/hash/MessageDigestAdapter.java, gnu/java/security/jce/hash/RipeMD128Spi.java, gnu/java/security/jce/hash/RipeMD160Spi.java, gnu/java/security/jce/hash/Sha160Spi.java, gnu/java/security/jce/hash/Sha256Spi.java, gnu/java/security/jce/hash/Sha384Spi.java, gnu/java/security/jce/hash/Sha512Spi.java, gnu/java/security/jce/hash/TigerSpi.java, gnu/java/security/jce/hash/WhirlpoolSpi.java, gnu/java/security/jce/prng/HavalRandomSpi.java, gnu/java/security/jce/prng/MD2RandomSpi.java, gnu/java/security/jce/prng/MD4RandomSpi.java, gnu/java/security/jce/prng/MD5RandomSpi.java, gnu/java/security/jce/prng/RipeMD128RandomSpi.java, gnu/java/security/jce/prng/RipeMD160RandomSpi.java, gnu/java/security/jce/prng/SecureRandomAdapter.java, gnu/java/security/jce/prng/Sha160RandomSpi.java, gnu/java/security/jce/prng/Sha256RandomSpi.java, gnu/java/security/jce/prng/Sha384RandomSpi.java, gnu/java/security/jce/prng/Sha512RandomSpi.java, gnu/java/security/jce/prng/TigerRandomSpi.java, gnu/java/security/jce/prng/WhirlpoolRandomSpi.java, gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java, gnu/java/security/jce/sig/DSSRawSignatureSpi.java, gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java, gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java, gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java, gnu/java/security/jce/sig/SignatureAdapter.java, gnu/java/security/key/IKeyPairCodec.java, gnu/java/security/key/IKeyPairGenerator.java, gnu/java/security/key/KeyPairCodecFactory.java, gnu/java/security/key/KeyPairGeneratorFactory.java, gnu/java/security/key/dss/DSSKey.java, gnu/java/security/key/dss/DSSKeyPairGenerator.java, gnu/java/security/key/dss/DSSKeyPairRawCodec.java, gnu/java/security/key/dss/DSSPrivateKey.java, gnu/java/security/key/dss/DSSPublicKey.java, gnu/java/security/key/dss/FIPS186.java, gnu/java/security/key/rsa/GnuRSAKey.java, gnu/java/security/key/rsa/GnuRSAPrivateKey.java, gnu/java/security/key/rsa/GnuRSAPublicKey.java, gnu/java/security/key/rsa/RSAKeyPairGenerator.java, gnu/java/security/key/rsa/RSAKeyPairRawCodec.java, gnu/java/security/prng/BasePRNG.java, gnu/java/security/prng/EntropySource.java, gnu/java/security/prng/IRandom.java, gnu/java/security/prng/LimitReachedException.java, gnu/java/security/prng/MDGenerator.java, gnu/java/security/prng/PRNGFactory.java, gnu/java/security/prng/RandomEvent.java, gnu/java/security/prng/RandomEventListener.java, gnu/java/security/sig/BaseSignature.java, gnu/java/security/sig/ISignature.java, gnu/java/security/sig/ISignatureCodec.java, gnu/java/security/sig/SignatureFactory.java, gnu/java/security/sig/dss/DSSSignature.java, gnu/java/security/sig/dss/DSSSignatureRawCodec.java, gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java, gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java, gnu/java/security/sig/rsa/EMSA_PSS.java, gnu/java/security/sig/rsa/RSA.java, gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java, gnu/java/security/sig/rsa/RSAPSSSignature.java, gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java, gnu/java/security/util/Base64.java, gnu/java/security/util/ExpirableObject.java, gnu/java/security/util/Prime2.java, gnu/java/security/util/Sequence.java, gnu/java/security/util/SimpleList.java, gnu/java/security/util/Util.java, resource/gnu/javax/security/auth/callback/MessagesBundle.properties: new files imported from GNU Crypto and Jessie.
-rw-r--r--ChangeLog431
-rw-r--r--NEWS9
-rw-r--r--gnu/classpath/debug/Component.java4
-rw-r--r--gnu/java/security/Properties.java374
-rw-r--r--gnu/java/security/Registry.java429
-rw-r--r--gnu/java/security/hash/BaseHash.java206
-rw-r--r--gnu/java/security/hash/HashFactory.java178
-rw-r--r--gnu/java/security/hash/Haval.java759
-rw-r--r--gnu/java/security/hash/IMessageDigest.java135
-rw-r--r--gnu/java/security/hash/MD2.java301
-rw-r--r--gnu/java/security/hash/MD4.java328
-rw-r--r--gnu/java/security/hash/MD5.java365
-rw-r--r--gnu/java/security/hash/RipeMD128.java291
-rw-r--r--gnu/java/security/hash/RipeMD160.java328
-rw-r--r--gnu/java/security/hash/Sha160.java308
-rw-r--r--gnu/java/security/hash/Sha256.java278
-rw-r--r--gnu/java/security/hash/Sha384.java322
-rw-r--r--gnu/java/security/hash/Sha512.java322
-rw-r--r--gnu/java/security/hash/Tiger.java943
-rw-r--r--gnu/java/security/hash/Whirlpool.java626
-rw-r--r--gnu/java/security/jce/hash/HavalSpi.java68
-rw-r--r--gnu/java/security/jce/hash/MD2Spi.java69
-rw-r--r--gnu/java/security/jce/hash/MD4Spi.java69
-rw-r--r--gnu/java/security/jce/hash/MD5Spi.java68
-rw-r--r--gnu/java/security/jce/hash/MessageDigestAdapter.java147
-rw-r--r--gnu/java/security/jce/hash/RipeMD128Spi.java68
-rw-r--r--gnu/java/security/jce/hash/RipeMD160Spi.java68
-rw-r--r--gnu/java/security/jce/hash/Sha160Spi.java68
-rw-r--r--gnu/java/security/jce/hash/Sha256Spi.java68
-rw-r--r--gnu/java/security/jce/hash/Sha384Spi.java68
-rw-r--r--gnu/java/security/jce/hash/Sha512Spi.java68
-rw-r--r--gnu/java/security/jce/hash/TigerSpi.java69
-rw-r--r--gnu/java/security/jce/hash/WhirlpoolSpi.java68
-rw-r--r--gnu/java/security/jce/prng/HavalRandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/MD2RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/MD4RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/MD5RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/RipeMD128RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/RipeMD160RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/SecureRandomAdapter.java126
-rw-r--r--gnu/java/security/jce/prng/Sha160RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/Sha256RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/Sha384RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/Sha512RandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/TigerRandomSpi.java66
-rw-r--r--gnu/java/security/jce/prng/WhirlpoolRandomSpi.java66
-rw-r--r--gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java113
-rw-r--r--gnu/java/security/jce/sig/DSSRawSignatureSpi.java70
-rw-r--r--gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java109
-rw-r--r--gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java111
-rw-r--r--gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java69
-rw-r--r--gnu/java/security/jce/sig/SignatureAdapter.java258
-rw-r--r--gnu/java/security/key/IKeyPairCodec.java121
-rw-r--r--gnu/java/security/key/IKeyPairGenerator.java82
-rw-r--r--gnu/java/security/key/KeyPairCodecFactory.java263
-rw-r--r--gnu/java/security/key/KeyPairGeneratorFactory.java148
-rw-r--r--gnu/java/security/key/dss/DSSKey.java173
-rw-r--r--gnu/java/security/key/dss/DSSKeyPairGenerator.java360
-rw-r--r--gnu/java/security/key/dss/DSSKeyPairRawCodec.java383
-rw-r--r--gnu/java/security/key/dss/DSSPrivateKey.java179
-rw-r--r--gnu/java/security/key/dss/DSSPublicKey.java179
-rw-r--r--gnu/java/security/key/dss/FIPS186.java286
-rw-r--r--gnu/java/security/key/rsa/GnuRSAKey.java171
-rw-r--r--gnu/java/security/key/rsa/GnuRSAPrivateKey.java255
-rw-r--r--gnu/java/security/key/rsa/GnuRSAPublicKey.java179
-rw-r--r--gnu/java/security/key/rsa/RSAKeyPairGenerator.java236
-rw-r--r--gnu/java/security/key/rsa/RSAKeyPairRawCodec.java332
-rw-r--r--gnu/java/security/prng/BasePRNG.java195
-rw-r--r--gnu/java/security/prng/EntropySource.java62
-rw-r--r--gnu/java/security/prng/IRandom.java180
-rw-r--r--gnu/java/security/prng/LimitReachedException.java69
-rw-r--r--gnu/java/security/prng/MDGenerator.java124
-rw-r--r--gnu/java/security/prng/PRNGFactory.java109
-rw-r--r--gnu/java/security/prng/RandomEvent.java82
-rw-r--r--gnu/java/security/prng/RandomEventListener.java50
-rw-r--r--gnu/java/security/provider/Gnu.java111
-rw-r--r--gnu/java/security/sig/BaseSignature.java247
-rw-r--r--gnu/java/security/sig/ISignature.java169
-rw-r--r--gnu/java/security/sig/ISignatureCodec.java68
-rw-r--r--gnu/java/security/sig/SignatureFactory.java122
-rw-r--r--gnu/java/security/sig/dss/DSSSignature.java347
-rw-r--r--gnu/java/security/sig/dss/DSSSignatureRawCodec.java191
-rw-r--r--gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java305
-rw-r--r--gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java299
-rw-r--r--gnu/java/security/sig/rsa/EMSA_PSS.java432
-rw-r--r--gnu/java/security/sig/rsa/RSA.java355
-rw-r--r--gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java242
-rw-r--r--gnu/java/security/sig/rsa/RSAPSSSignature.java343
-rw-r--r--gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java159
-rw-r--r--gnu/java/security/util/Base64.java396
-rw-r--r--gnu/java/security/util/ExpirableObject.java172
-rw-r--r--gnu/java/security/util/Prime2.java632
-rw-r--r--gnu/java/security/util/Sequence.java149
-rw-r--r--gnu/java/security/util/SimpleList.java171
-rw-r--r--gnu/java/security/util/Util.java692
-rw-r--r--gnu/javax/crypto/assembly/Assembly.java298
-rw-r--r--gnu/javax/crypto/assembly/Cascade.java405
-rw-r--r--gnu/javax/crypto/assembly/CascadeStage.java109
-rw-r--r--gnu/javax/crypto/assembly/CascadeTransformer.java139
-rw-r--r--gnu/javax/crypto/assembly/DeflateTransformer.java233
-rw-r--r--gnu/javax/crypto/assembly/Direction.java92
-rw-r--r--gnu/javax/crypto/assembly/LoopbackTransformer.java116
-rw-r--r--gnu/javax/crypto/assembly/ModeStage.java129
-rw-r--r--gnu/javax/crypto/assembly/Operation.java89
-rw-r--r--gnu/javax/crypto/assembly/PaddingTransformer.java178
-rw-r--r--gnu/javax/crypto/assembly/Stage.java218
-rw-r--r--gnu/javax/crypto/assembly/Transformer.java460
-rw-r--r--gnu/javax/crypto/assembly/TransformerException.java158
-rw-r--r--gnu/javax/crypto/cipher/Anubis.java583
-rw-r--r--gnu/javax/crypto/cipher/BaseCipher.java304
-rw-r--r--gnu/javax/crypto/cipher/Blowfish.java749
-rw-r--r--gnu/javax/crypto/cipher/Cast5.java1391
-rw-r--r--gnu/javax/crypto/cipher/CipherFactory.java169
-rw-r--r--gnu/javax/crypto/cipher/DES.java894
-rw-r--r--gnu/javax/crypto/cipher/IBlockCipher.java205
-rw-r--r--gnu/javax/crypto/cipher/IBlockCipherSpi.java128
-rw-r--r--gnu/javax/crypto/cipher/Khazad.java521
-rw-r--r--gnu/javax/crypto/cipher/NullCipher.java129
-rw-r--r--gnu/javax/crypto/cipher/Rijndael.java859
-rw-r--r--gnu/javax/crypto/cipher/Serpent.java1830
-rw-r--r--gnu/javax/crypto/cipher/Square.java520
-rw-r--r--gnu/javax/crypto/cipher/TripleDES.java196
-rw-r--r--gnu/javax/crypto/cipher/Twofish.java909
-rw-r--r--gnu/javax/crypto/cipher/WeakKeyException.java71
-rw-r--r--gnu/javax/crypto/jce/GnuCrypto.java569
-rw-r--r--gnu/javax/crypto/jce/GnuSasl.java114
-rw-r--r--gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java229
-rw-r--r--gnu/javax/crypto/jce/cipher/AESSpi.java104
-rw-r--r--gnu/javax/crypto/jce/cipher/ARCFourSpi.java208
-rw-r--r--gnu/javax/crypto/jce/cipher/AnubisSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/BlowfishSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/Cast5Spi.java68
-rw-r--r--gnu/javax/crypto/jce/cipher/CipherAdapter.java507
-rw-r--r--gnu/javax/crypto/jce/cipher/DESSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/KhazadSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/NullCipherSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/PBES2.java1352
-rw-r--r--gnu/javax/crypto/jce/cipher/RijndaelSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/SerpentSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/SquareSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/TripleDESSpi.java59
-rw-r--r--gnu/javax/crypto/jce/cipher/TwofishSpi.java59
-rw-r--r--gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java53
-rw-r--r--gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java53
-rw-r--r--gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java53
-rw-r--r--gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java53
-rw-r--r--gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java53
-rw-r--r--gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java53
-rw-r--r--gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java73
-rw-r--r--gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java80
-rw-r--r--gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java80
-rw-r--r--gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java87
-rw-r--r--gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java120
-rw-r--r--gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java52
-rw-r--r--gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java52
-rw-r--r--gnu/javax/crypto/jce/keyring/GnuKeyring.java413
-rw-r--r--gnu/javax/crypto/jce/mac/HMacHavalSpi.java67
-rw-r--r--gnu/javax/crypto/jce/mac/HMacMD2Spi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/HMacMD4Spi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/HMacMD5Spi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/HMacSHA160Spi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/HMacSHA256Spi.java67
-rw-r--r--gnu/javax/crypto/jce/mac/HMacSHA384Spi.java67
-rw-r--r--gnu/javax/crypto/jce/mac/HMacSHA512Spi.java67
-rw-r--r--gnu/javax/crypto/jce/mac/HMacTigerSpi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/MacAdapter.java142
-rw-r--r--gnu/javax/crypto/jce/mac/OMacAnubisImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacCast5Impl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacDESImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacImpl.java137
-rw-r--r--gnu/javax/crypto/jce/mac/OMacKhazadImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacSerpentImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacSquareImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/OMacTwofishImpl.java53
-rw-r--r--gnu/javax/crypto/jce/mac/TMMH16Spi.java91
-rw-r--r--gnu/javax/crypto/jce/mac/UHash32Spi.java59
-rw-r--r--gnu/javax/crypto/jce/mac/UMac32Spi.java91
-rw-r--r--gnu/javax/crypto/jce/params/BlockCipherParameters.java209
-rw-r--r--gnu/javax/crypto/jce/params/DEREncodingException.java53
-rw-r--r--gnu/javax/crypto/jce/params/DERReader.java160
-rw-r--r--gnu/javax/crypto/jce/params/DERWriter.java154
-rw-r--r--gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java120
-rw-r--r--gnu/javax/crypto/jce/prng/CSPRNGSpi.java114
-rw-r--r--gnu/javax/crypto/jce/prng/FortunaImpl.java85
-rw-r--r--gnu/javax/crypto/jce/prng/ICMRandomSpi.java260
-rw-r--r--gnu/javax/crypto/jce/prng/UMacRandomSpi.java207
-rw-r--r--gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java139
-rw-r--r--gnu/javax/crypto/jce/spec/TMMHParameterSpec.java129
-rw-r--r--gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java82
-rw-r--r--gnu/javax/crypto/key/BaseKeyAgreementParty.java198
-rw-r--r--gnu/javax/crypto/key/GnuSecretKey.java149
-rw-r--r--gnu/javax/crypto/key/IKeyAgreementParty.java105
-rw-r--r--gnu/javax/crypto/key/IncomingMessage.java293
-rw-r--r--gnu/javax/crypto/key/KeyAgreementException.java187
-rw-r--r--gnu/javax/crypto/key/KeyAgreementFactory.java181
-rw-r--r--gnu/javax/crypto/key/OutgoingMessage.java212
-rw-r--r--gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java370
-rw-r--r--gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java134
-rw-r--r--gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java147
-rw-r--r--gnu/javax/crypto/key/dh/DiffieHellmanSender.java156
-rw-r--r--gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java130
-rw-r--r--gnu/javax/crypto/key/dh/ElGamalReceiver.java121
-rw-r--r--gnu/javax/crypto/key/dh/ElGamalSender.java134
-rw-r--r--gnu/javax/crypto/key/dh/GnuDHKey.java163
-rw-r--r--gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java254
-rw-r--r--gnu/javax/crypto/key/dh/GnuDHPrivateKey.java155
-rw-r--r--gnu/javax/crypto/key/dh/GnuDHPublicKey.java155
-rw-r--r--gnu/javax/crypto/key/dh/RFC2631.java245
-rw-r--r--gnu/javax/crypto/key/srp6/SRP6Host.java213
-rw-r--r--gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java172
-rw-r--r--gnu/javax/crypto/key/srp6/SRP6SaslClient.java101
-rw-r--r--gnu/javax/crypto/key/srp6/SRP6SaslServer.java101
-rw-r--r--gnu/javax/crypto/key/srp6/SRP6TLSClient.java191
-rw-r--r--gnu/javax/crypto/key/srp6/SRP6TLSServer.java220
-rw-r--r--gnu/javax/crypto/key/srp6/SRP6User.java203
-rw-r--r--gnu/javax/crypto/key/srp6/SRPAlgorithm.java175
-rw-r--r--gnu/javax/crypto/key/srp6/SRPKey.java170
-rw-r--r--gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java341
-rw-r--r--gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java380
-rw-r--r--gnu/javax/crypto/key/srp6/SRPPrivateKey.java250
-rw-r--r--gnu/javax/crypto/key/srp6/SRPPublicKey.java194
-rw-r--r--gnu/javax/crypto/keyring/AuthenticatedEntry.java222
-rw-r--r--gnu/javax/crypto/keyring/BaseKeyring.java198
-rw-r--r--gnu/javax/crypto/keyring/BinaryDataEntry.java128
-rw-r--r--gnu/javax/crypto/keyring/CertPathEntry.java133
-rw-r--r--gnu/javax/crypto/keyring/CertificateEntry.java150
-rw-r--r--gnu/javax/crypto/keyring/CompressedEntry.java113
-rw-r--r--gnu/javax/crypto/keyring/EncryptedEntry.java235
-rw-r--r--gnu/javax/crypto/keyring/Entry.java178
-rw-r--r--gnu/javax/crypto/keyring/EnvelopeEntry.java398
-rw-r--r--gnu/javax/crypto/keyring/GnuPrivateKeyring.java328
-rw-r--r--gnu/javax/crypto/keyring/GnuPublicKeyring.java146
-rw-r--r--gnu/javax/crypto/keyring/IKeyring.java164
-rw-r--r--gnu/javax/crypto/keyring/IPrivateKeyring.java142
-rw-r--r--gnu/javax/crypto/keyring/IPublicKeyring.java81
-rw-r--r--gnu/javax/crypto/keyring/MalformedKeyringException.java58
-rw-r--r--gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java148
-rw-r--r--gnu/javax/crypto/keyring/MeteredInputStream.java137
-rw-r--r--gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java285
-rw-r--r--gnu/javax/crypto/keyring/PasswordEncryptedEntry.java301
-rw-r--r--gnu/javax/crypto/keyring/PasswordProtectedEntry.java66
-rw-r--r--gnu/javax/crypto/keyring/PrimitiveEntry.java129
-rw-r--r--gnu/javax/crypto/keyring/PrivateKeyEntry.java221
-rw-r--r--gnu/javax/crypto/keyring/Properties.java227
-rw-r--r--gnu/javax/crypto/keyring/PublicKeyEntry.java192
-rw-r--r--gnu/javax/crypto/mac/BaseMac.java144
-rw-r--r--gnu/javax/crypto/mac/HMac.java313
-rw-r--r--gnu/javax/crypto/mac/HMacFactory.java128
-rw-r--r--gnu/javax/crypto/mac/IMac.java197
-rw-r--r--gnu/javax/crypto/mac/MacFactory.java164
-rw-r--r--gnu/javax/crypto/mac/MacInputStream.java138
-rw-r--r--gnu/javax/crypto/mac/MacOutputStream.java140
-rw-r--r--gnu/javax/crypto/mac/OMAC.java402
-rw-r--r--gnu/javax/crypto/mac/TMMH16.java378
-rw-r--r--gnu/javax/crypto/mac/UHash32.java957
-rw-r--r--gnu/javax/crypto/mac/UMac32.java491
-rw-r--r--gnu/javax/crypto/mode/BaseMode.java352
-rw-r--r--gnu/javax/crypto/mode/CBC.java143
-rw-r--r--gnu/javax/crypto/mode/CFB.java175
-rw-r--r--gnu/javax/crypto/mode/CTR.java221
-rw-r--r--gnu/javax/crypto/mode/EAX.java352
-rw-r--r--gnu/javax/crypto/mode/ECB.java137
-rw-r--r--gnu/javax/crypto/mode/IAuthenticatedMode.java60
-rw-r--r--gnu/javax/crypto/mode/ICM.java228
-rw-r--r--gnu/javax/crypto/mode/IMode.java145
-rw-r--r--gnu/javax/crypto/mode/ModeFactory.java192
-rw-r--r--gnu/javax/crypto/mode/OFB.java194
-rw-r--r--gnu/javax/crypto/pad/BasePad.java153
-rw-r--r--gnu/javax/crypto/pad/IPad.java110
-rw-r--r--gnu/javax/crypto/pad/PKCS1_V1_5.java184
-rw-r--r--gnu/javax/crypto/pad/PKCS7.java149
-rw-r--r--gnu/javax/crypto/pad/PadFactory.java136
-rw-r--r--gnu/javax/crypto/pad/SSL3.java98
-rw-r--r--gnu/javax/crypto/pad/TBC.java156
-rw-r--r--gnu/javax/crypto/pad/TLS1.java105
-rw-r--r--gnu/javax/crypto/pad/WrongPaddingException.java63
-rw-r--r--gnu/javax/crypto/prng/ARCFour.java161
-rw-r--r--gnu/javax/crypto/prng/CSPRNG.java1268
-rw-r--r--gnu/javax/crypto/prng/Fortuna.java366
-rw-r--r--gnu/javax/crypto/prng/ICMGenerator.java379
-rw-r--r--gnu/javax/crypto/prng/IPBE.java69
-rw-r--r--gnu/javax/crypto/prng/PBKDF2.java216
-rw-r--r--gnu/javax/crypto/prng/PRNGFactory.java143
-rw-r--r--gnu/javax/crypto/prng/UMacGenerator.java228
-rw-r--r--gnu/javax/crypto/sasl/AuthInfo.java143
-rw-r--r--gnu/javax/crypto/sasl/AuthInfoProviderFactory.java89
-rw-r--r--gnu/javax/crypto/sasl/ClientFactory.java210
-rw-r--r--gnu/javax/crypto/sasl/ClientMechanism.java365
-rw-r--r--gnu/javax/crypto/sasl/ConfidentialityException.java84
-rw-r--r--gnu/javax/crypto/sasl/IAuthInfoProvider.java117
-rw-r--r--gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java62
-rw-r--r--gnu/javax/crypto/sasl/IllegalMechanismStateException.java86
-rw-r--r--gnu/javax/crypto/sasl/InputBuffer.java339
-rw-r--r--gnu/javax/crypto/sasl/IntegrityException.java83
-rw-r--r--gnu/javax/crypto/sasl/NoSuchMechanismException.java62
-rw-r--r--gnu/javax/crypto/sasl/NoSuchUserException.java67
-rw-r--r--gnu/javax/crypto/sasl/OutputBuffer.java225
-rw-r--r--gnu/javax/crypto/sasl/SaslEncodingException.java66
-rw-r--r--gnu/javax/crypto/sasl/SaslInputStream.java459
-rw-r--r--gnu/javax/crypto/sasl/SaslOutputStream.java218
-rw-r--r--gnu/javax/crypto/sasl/SaslUtil.java89
-rw-r--r--gnu/javax/crypto/sasl/ServerFactory.java194
-rw-r--r--gnu/javax/crypto/sasl/ServerMechanism.java371
-rw-r--r--gnu/javax/crypto/sasl/UserAlreadyExistsException.java70
-rw-r--r--gnu/javax/crypto/sasl/anonymous/AnonymousClient.java120
-rw-r--r--gnu/javax/crypto/sasl/anonymous/AnonymousServer.java107
-rw-r--r--gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java109
-rw-r--r--gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java200
-rw-r--r--gnu/javax/crypto/sasl/crammd5/CramMD5Client.java201
-rw-r--r--gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java66
-rw-r--r--gnu/javax/crypto/sasl/crammd5/CramMD5Server.java185
-rw-r--r--gnu/javax/crypto/sasl/crammd5/CramMD5Util.java137
-rw-r--r--gnu/javax/crypto/sasl/crammd5/PasswordFile.java301
-rw-r--r--gnu/javax/crypto/sasl/plain/PasswordFile.java309
-rw-r--r--gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java206
-rw-r--r--gnu/javax/crypto/sasl/plain/PlainClient.java193
-rw-r--r--gnu/javax/crypto/sasl/plain/PlainRegistry.java67
-rw-r--r--gnu/javax/crypto/sasl/plain/PlainServer.java196
-rw-r--r--gnu/javax/crypto/sasl/srp/CALG.java292
-rw-r--r--gnu/javax/crypto/sasl/srp/ClientStore.java173
-rw-r--r--gnu/javax/crypto/sasl/srp/IALG.java159
-rw-r--r--gnu/javax/crypto/sasl/srp/KDF.java157
-rw-r--r--gnu/javax/crypto/sasl/srp/PasswordFile.java699
-rw-r--r--gnu/javax/crypto/sasl/srp/SRP.java285
-rw-r--r--gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java218
-rw-r--r--gnu/javax/crypto/sasl/srp/SRPClient.java1199
-rw-r--r--gnu/javax/crypto/sasl/srp/SRPRegistry.java219
-rw-r--r--gnu/javax/crypto/sasl/srp/SRPServer.java1147
-rw-r--r--gnu/javax/crypto/sasl/srp/SecurityContext.java164
-rw-r--r--gnu/javax/crypto/sasl/srp/ServerStore.java196
-rw-r--r--gnu/javax/crypto/sasl/srp/StoreEntry.java89
-rw-r--r--gnu/javax/net/ssl/Base64.java311
-rw-r--r--gnu/javax/net/ssl/EntropySource.java62
-rw-r--r--gnu/javax/net/ssl/NullManagerParameters.java56
-rw-r--r--gnu/javax/net/ssl/PrivateCredentials.java360
-rw-r--r--gnu/javax/net/ssl/SRPManagerParameters.java81
-rw-r--r--gnu/javax/net/ssl/SRPTrustManager.java99
-rw-r--r--gnu/javax/net/ssl/StaticTrustAnchors.java1942
-rw-r--r--gnu/javax/net/ssl/provider/Alert.java474
-rw-r--r--gnu/javax/net/ssl/provider/AlertException.java76
-rw-r--r--gnu/javax/net/ssl/provider/Certificate.java194
-rw-r--r--gnu/javax/net/ssl/provider/CertificateRequest.java285
-rw-r--r--gnu/javax/net/ssl/provider/CertificateType.java104
-rw-r--r--gnu/javax/net/ssl/provider/CertificateVerify.java95
-rw-r--r--gnu/javax/net/ssl/provider/CipherSuite.java754
-rw-r--r--gnu/javax/net/ssl/provider/ClientHello.java253
-rw-r--r--gnu/javax/net/ssl/provider/ClientKeyExchange.java181
-rw-r--r--gnu/javax/net/ssl/provider/CompressionMethod.java104
-rw-r--r--gnu/javax/net/ssl/provider/Constructed.java57
-rw-r--r--gnu/javax/net/ssl/provider/ContentType.java135
-rw-r--r--gnu/javax/net/ssl/provider/Context.java334
-rw-r--r--gnu/javax/net/ssl/provider/DiffieHellman.java285
-rw-r--r--gnu/javax/net/ssl/provider/DigestInputStream.java103
-rw-r--r--gnu/javax/net/ssl/provider/DigestOutputStream.java107
-rw-r--r--gnu/javax/net/ssl/provider/Enumerated.java79
-rw-r--r--gnu/javax/net/ssl/provider/Extension.java214
-rw-r--r--gnu/javax/net/ssl/provider/Extensions.java159
-rw-r--r--gnu/javax/net/ssl/provider/Finished.java143
-rw-r--r--gnu/javax/net/ssl/provider/GNUSecurityParameters.java490
-rw-r--r--gnu/javax/net/ssl/provider/Handshake.java440
-rw-r--r--gnu/javax/net/ssl/provider/JCESecurityParameters.java307
-rw-r--r--gnu/javax/net/ssl/provider/JDBCSessionContext.java356
-rw-r--r--gnu/javax/net/ssl/provider/Jessie.java91
-rw-r--r--gnu/javax/net/ssl/provider/JessieDHPrivateKey.java99
-rw-r--r--gnu/javax/net/ssl/provider/JessieDHPublicKey.java99
-rw-r--r--gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java98
-rw-r--r--gnu/javax/net/ssl/provider/JessieRSAPublicKey.java98
-rw-r--r--gnu/javax/net/ssl/provider/KeyPool.java119
-rw-r--r--gnu/javax/net/ssl/provider/MacException.java53
-rw-r--r--gnu/javax/net/ssl/provider/OverflowException.java57
-rw-r--r--gnu/javax/net/ssl/provider/PRNG.java41
-rw-r--r--gnu/javax/net/ssl/provider/ProtocolVersion.java180
-rw-r--r--gnu/javax/net/ssl/provider/Random.java124
-rw-r--r--gnu/javax/net/ssl/provider/RecordInput.java232
-rw-r--r--gnu/javax/net/ssl/provider/RecordInputStream.java106
-rw-r--r--gnu/javax/net/ssl/provider/RecordOutputStream.java189
-rw-r--r--gnu/javax/net/ssl/provider/RecordingInputStream.java131
-rw-r--r--gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java225
-rw-r--r--gnu/javax/net/ssl/provider/SSLHMac.java158
-rw-r--r--gnu/javax/net/ssl/provider/SSLRSASignature.java235
-rw-r--r--gnu/javax/net/ssl/provider/SSLRandom.java165
-rw-r--r--gnu/javax/net/ssl/provider/SSLServerSocket.java283
-rw-r--r--gnu/javax/net/ssl/provider/SSLServerSocketFactory.java136
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocket.java3530
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocketFactory.java133
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocketInputStream.java181
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocketOutputStream.java115
-rw-r--r--gnu/javax/net/ssl/provider/SecurityParameters.java178
-rw-r--r--gnu/javax/net/ssl/provider/ServerHello.java216
-rw-r--r--gnu/javax/net/ssl/provider/ServerKeyExchange.java286
-rw-r--r--gnu/javax/net/ssl/provider/Session.java381
-rw-r--r--gnu/javax/net/ssl/provider/SessionContext.java250
-rw-r--r--gnu/javax/net/ssl/provider/Signature.java158
-rw-r--r--gnu/javax/net/ssl/provider/SynchronizedRandom.java104
-rw-r--r--gnu/javax/net/ssl/provider/TLSHMac.java138
-rw-r--r--gnu/javax/net/ssl/provider/TLSRandom.java252
-rw-r--r--gnu/javax/net/ssl/provider/Util.java422
-rw-r--r--gnu/javax/net/ssl/provider/X509KeyManagerFactory.java359
-rw-r--r--gnu/javax/net/ssl/provider/X509TrustManagerFactory.java298
-rw-r--r--gnu/javax/net/ssl/provider/XMLSessionContext.java619
-rw-r--r--gnu/javax/security/auth/Password.java285
-rw-r--r--gnu/javax/security/auth/callback/AWTCallbackHandler.java452
-rw-r--r--gnu/javax/security/auth/callback/AbstractCallbackHandler.java258
-rw-r--r--gnu/javax/security/auth/callback/ConsoleCallbackHandler.java289
-rw-r--r--gnu/javax/security/auth/callback/DefaultCallbackHandler.java109
-rw-r--r--gnu/javax/security/auth/callback/GnuCallbacks.java64
-rw-r--r--gnu/javax/security/auth/callback/SwingCallbackHandler.java587
-rw-r--r--resource/gnu/javax/security/auth/callback/MessagesBundle.properties52
-rw-r--r--resource/java/security/classpath.security3
424 files changed, 92710 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 3348bb6e5..b32d0e662 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,434 @@
+2006-01-25 Casey Marshall <csm@gnu.org>
+
+ Merging GNU Crypto and Jessie.
+
+ * NEWS: mention the merge in the 0.21 notes.
+ * gnu/classpath/debug/Component.java (SSL_APPLICATION): removed.
+ (SSL_RECORD_LAYER): new constants.
+ * gnu/java/security/provider/Gnu.java (<init>): add new algorithms
+ to provider.
+ * resource/java/security/classpath.security: add new providers.
+ * gnu/javax/crypto/assembly/Assembly.java,
+ gnu/javax/crypto/assembly/Cascade.java,
+ gnu/javax/crypto/assembly/CascadeStage.java,
+ gnu/javax/crypto/assembly/CascadeTransformer.java,
+ gnu/javax/crypto/assembly/DeflateTransformer.java,
+ gnu/javax/crypto/assembly/Direction.java,
+ gnu/javax/crypto/assembly/LoopbackTransformer.java,
+ gnu/javax/crypto/assembly/ModeStage.java,
+ gnu/javax/crypto/assembly/Operation.java,
+ gnu/javax/crypto/assembly/PaddingTransformer.java,
+ gnu/javax/crypto/assembly/Stage.java,
+ gnu/javax/crypto/assembly/Transformer.java,
+ gnu/javax/crypto/assembly/TransformerException.java,
+ gnu/javax/crypto/cipher/Anubis.java,
+ gnu/javax/crypto/cipher/BaseCipher.java,
+ gnu/javax/crypto/cipher/Blowfish.java,
+ gnu/javax/crypto/cipher/Cast5.java,
+ gnu/javax/crypto/cipher/CipherFactory.java,
+ gnu/javax/crypto/cipher/DES.java,
+ gnu/javax/crypto/cipher/IBlockCipher.java,
+ gnu/javax/crypto/cipher/IBlockCipherSpi.java,
+ gnu/javax/crypto/cipher/Khazad.java,
+ gnu/javax/crypto/cipher/NullCipher.java,
+ gnu/javax/crypto/cipher/Rijndael.java,
+ gnu/javax/crypto/cipher/Serpent.java,
+ gnu/javax/crypto/cipher/Square.java,
+ gnu/javax/crypto/cipher/TripleDES.java,
+ gnu/javax/crypto/cipher/Twofish.java,
+ gnu/javax/crypto/cipher/WeakKeyException.java,
+ gnu/javax/crypto/jce/GnuCrypto.java,
+ gnu/javax/crypto/jce/GnuSasl.java,
+ gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java,
+ gnu/javax/crypto/jce/cipher/AESSpi.java,
+ gnu/javax/crypto/jce/cipher/ARCFourSpi.java,
+ gnu/javax/crypto/jce/cipher/AnubisSpi.java,
+ gnu/javax/crypto/jce/cipher/BlowfishSpi.java,
+ gnu/javax/crypto/jce/cipher/Cast5Spi.java,
+ gnu/javax/crypto/jce/cipher/CipherAdapter.java,
+ gnu/javax/crypto/jce/cipher/DESSpi.java,
+ gnu/javax/crypto/jce/cipher/KhazadSpi.java,
+ gnu/javax/crypto/jce/cipher/NullCipherSpi.java,
+ gnu/javax/crypto/jce/cipher/PBES2.java,
+ gnu/javax/crypto/jce/cipher/RijndaelSpi.java,
+ gnu/javax/crypto/jce/cipher/SerpentSpi.java,
+ gnu/javax/crypto/jce/cipher/SquareSpi.java,
+ gnu/javax/crypto/jce/cipher/TripleDESSpi.java,
+ gnu/javax/crypto/jce/cipher/TwofishSpi.java,
+ gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java,
+ gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java,
+ gnu/javax/crypto/jce/keyring/GnuKeyring.java,
+ gnu/javax/crypto/jce/mac/HMacHavalSpi.java,
+ gnu/javax/crypto/jce/mac/HMacMD2Spi.java,
+ gnu/javax/crypto/jce/mac/HMacMD4Spi.java,
+ gnu/javax/crypto/jce/mac/HMacMD5Spi.java,
+ gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java,
+ gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java,
+ gnu/javax/crypto/jce/mac/HMacSHA160Spi.java,
+ gnu/javax/crypto/jce/mac/HMacSHA256Spi.java,
+ gnu/javax/crypto/jce/mac/HMacSHA384Spi.java,
+ gnu/javax/crypto/jce/mac/HMacSHA512Spi.java,
+ gnu/javax/crypto/jce/mac/HMacTigerSpi.java,
+ gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java,
+ gnu/javax/crypto/jce/mac/MacAdapter.java,
+ gnu/javax/crypto/jce/mac/OMacAnubisImpl.java,
+ gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java,
+ gnu/javax/crypto/jce/mac/OMacCast5Impl.java,
+ gnu/javax/crypto/jce/mac/OMacDESImpl.java,
+ gnu/javax/crypto/jce/mac/OMacImpl.java,
+ gnu/javax/crypto/jce/mac/OMacKhazadImpl.java,
+ gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java,
+ gnu/javax/crypto/jce/mac/OMacSerpentImpl.java,
+ gnu/javax/crypto/jce/mac/OMacSquareImpl.java,
+ gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java,
+ gnu/javax/crypto/jce/mac/OMacTwofishImpl.java,
+ gnu/javax/crypto/jce/mac/TMMH16Spi.java,
+ gnu/javax/crypto/jce/mac/UHash32Spi.java,
+ gnu/javax/crypto/jce/mac/UMac32Spi.java,
+ gnu/javax/crypto/jce/params/BlockCipherParameters.java,
+ gnu/javax/crypto/jce/params/DEREncodingException.java,
+ gnu/javax/crypto/jce/params/DERReader.java,
+ gnu/javax/crypto/jce/params/DERWriter.java,
+ gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java,
+ gnu/javax/crypto/jce/prng/CSPRNGSpi.java,
+ gnu/javax/crypto/jce/prng/FortunaImpl.java,
+ gnu/javax/crypto/jce/prng/ICMRandomSpi.java,
+ gnu/javax/crypto/jce/prng/UMacRandomSpi.java,
+ gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java,
+ gnu/javax/crypto/jce/spec/TMMHParameterSpec.java,
+ gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java,
+ gnu/javax/crypto/key/BaseKeyAgreementParty.java,
+ gnu/javax/crypto/key/GnuSecretKey.java,
+ gnu/javax/crypto/key/IKeyAgreementParty.java,
+ gnu/javax/crypto/key/IncomingMessage.java,
+ gnu/javax/crypto/key/KeyAgreementException.java,
+ gnu/javax/crypto/key/KeyAgreementFactory.java,
+ gnu/javax/crypto/key/OutgoingMessage.java,
+ gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java,
+ gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java,
+ gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java,
+ gnu/javax/crypto/key/dh/DiffieHellmanSender.java,
+ gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java,
+ gnu/javax/crypto/key/dh/ElGamalReceiver.java,
+ gnu/javax/crypto/key/dh/ElGamalSender.java,
+ gnu/javax/crypto/key/dh/GnuDHKey.java,
+ gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java,
+ gnu/javax/crypto/key/dh/GnuDHPrivateKey.java,
+ gnu/javax/crypto/key/dh/GnuDHPublicKey.java,
+ gnu/javax/crypto/key/dh/RFC2631.java,
+ gnu/javax/crypto/key/srp6/SRP6Host.java,
+ gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java,
+ gnu/javax/crypto/key/srp6/SRP6SaslClient.java,
+ gnu/javax/crypto/key/srp6/SRP6SaslServer.java,
+ gnu/javax/crypto/key/srp6/SRP6TLSClient.java,
+ gnu/javax/crypto/key/srp6/SRP6TLSServer.java,
+ gnu/javax/crypto/key/srp6/SRP6User.java,
+ gnu/javax/crypto/key/srp6/SRPAlgorithm.java,
+ gnu/javax/crypto/key/srp6/SRPKey.java,
+ gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java,
+ gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java,
+ gnu/javax/crypto/key/srp6/SRPPrivateKey.java,
+ gnu/javax/crypto/key/srp6/SRPPublicKey.java,
+ gnu/javax/crypto/keyring/AuthenticatedEntry.java,
+ gnu/javax/crypto/keyring/BaseKeyring.java,
+ gnu/javax/crypto/keyring/BinaryDataEntry.java,
+ gnu/javax/crypto/keyring/CertPathEntry.java,
+ gnu/javax/crypto/keyring/CertificateEntry.java,
+ gnu/javax/crypto/keyring/CompressedEntry.java,
+ gnu/javax/crypto/keyring/EncryptedEntry.java,
+ gnu/javax/crypto/keyring/Entry.java,
+ gnu/javax/crypto/keyring/EnvelopeEntry.java,
+ gnu/javax/crypto/keyring/GnuPrivateKeyring.java,
+ gnu/javax/crypto/keyring/GnuPublicKeyring.java,
+ gnu/javax/crypto/keyring/IKeyring.java,
+ gnu/javax/crypto/keyring/IPrivateKeyring.java,
+ gnu/javax/crypto/keyring/IPublicKeyring.java,
+ gnu/javax/crypto/keyring/MalformedKeyringException.java,
+ gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java,
+ gnu/javax/crypto/keyring/MeteredInputStream.java,
+ gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java,
+ gnu/javax/crypto/keyring/PasswordEncryptedEntry.java,
+ gnu/javax/crypto/keyring/PasswordProtectedEntry.java,
+ gnu/javax/crypto/keyring/PrimitiveEntry.java,
+ gnu/javax/crypto/keyring/PrivateKeyEntry.java,
+ gnu/javax/crypto/keyring/Properties.java,
+ gnu/javax/crypto/keyring/PublicKeyEntry.java,
+ gnu/javax/crypto/mac/BaseMac.java,
+ gnu/javax/crypto/mac/HMac.java,
+ gnu/javax/crypto/mac/HMacFactory.java,
+ gnu/javax/crypto/mac/IMac.java,
+ gnu/javax/crypto/mac/MacFactory.java,
+ gnu/javax/crypto/mac/MacInputStream.java,
+ gnu/javax/crypto/mac/MacOutputStream.java,
+ gnu/javax/crypto/mac/OMAC.java,
+ gnu/javax/crypto/mac/TMMH16.java,
+ gnu/javax/crypto/mac/UHash32.java,
+ gnu/javax/crypto/mac/UMac32.java,
+ gnu/javax/crypto/mode/BaseMode.java,
+ gnu/javax/crypto/mode/CBC.java,
+ gnu/javax/crypto/mode/CFB.java,
+ gnu/javax/crypto/mode/CTR.java,
+ gnu/javax/crypto/mode/EAX.java,
+ gnu/javax/crypto/mode/ECB.java,
+ gnu/javax/crypto/mode/IAuthenticatedMode.java,
+ gnu/javax/crypto/mode/ICM.java,
+ gnu/javax/crypto/mode/IMode.java,
+ gnu/javax/crypto/mode/ModeFactory.java,
+ gnu/javax/crypto/mode/OFB.java,
+ gnu/javax/crypto/pad/BasePad.java,
+ gnu/javax/crypto/pad/IPad.java,
+ gnu/javax/crypto/pad/PKCS1_V1_5.java,
+ gnu/javax/crypto/pad/PKCS7.java,
+ gnu/javax/crypto/pad/PadFactory.java,
+ gnu/javax/crypto/pad/SSL3.java,
+ gnu/javax/crypto/pad/TBC.java,
+ gnu/javax/crypto/pad/TLS1.java,
+ gnu/javax/crypto/pad/WrongPaddingException.java,
+ gnu/javax/crypto/prng/ARCFour.java,
+ gnu/javax/crypto/prng/CSPRNG.java,
+ gnu/javax/crypto/prng/Fortuna.java,
+ gnu/javax/crypto/prng/ICMGenerator.java,
+ gnu/javax/crypto/prng/IPBE.java,
+ gnu/javax/crypto/prng/PBKDF2.java,
+ gnu/javax/crypto/prng/PRNGFactory.java,
+ gnu/javax/crypto/prng/UMacGenerator.java,
+ gnu/javax/crypto/sasl/AuthInfo.java,
+ gnu/javax/crypto/sasl/AuthInfoProviderFactory.java,
+ gnu/javax/crypto/sasl/ClientFactory.java,
+ gnu/javax/crypto/sasl/ClientMechanism.java,
+ gnu/javax/crypto/sasl/ConfidentialityException.java,
+ gnu/javax/crypto/sasl/IAuthInfoProvider.java,
+ gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java,
+ gnu/javax/crypto/sasl/IllegalMechanismStateException.java,
+ gnu/javax/crypto/sasl/InputBuffer.java,
+ gnu/javax/crypto/sasl/IntegrityException.java,
+ gnu/javax/crypto/sasl/NoSuchMechanismException.java,
+ gnu/javax/crypto/sasl/NoSuchUserException.java,
+ gnu/javax/crypto/sasl/OutputBuffer.java,
+ gnu/javax/crypto/sasl/SaslEncodingException.java,
+ gnu/javax/crypto/sasl/SaslInputStream.java,
+ gnu/javax/crypto/sasl/SaslOutputStream.java,
+ gnu/javax/crypto/sasl/SaslUtil.java,
+ gnu/javax/crypto/sasl/ServerFactory.java,
+ gnu/javax/crypto/sasl/ServerMechanism.java,
+ gnu/javax/crypto/sasl/UserAlreadyExistsException.java,
+ gnu/javax/crypto/sasl/anonymous/AnonymousClient.java,
+ gnu/javax/crypto/sasl/anonymous/AnonymousServer.java,
+ gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java,
+ gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java,
+ gnu/javax/crypto/sasl/crammd5/CramMD5Client.java,
+ gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java,
+ gnu/javax/crypto/sasl/crammd5/CramMD5Server.java,
+ gnu/javax/crypto/sasl/crammd5/CramMD5Util.java,
+ gnu/javax/crypto/sasl/crammd5/PasswordFile.java,
+ gnu/javax/crypto/sasl/plain/PasswordFile.java,
+ gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java,
+ gnu/javax/crypto/sasl/plain/PlainClient.java,
+ gnu/javax/crypto/sasl/plain/PlainRegistry.java,
+ gnu/javax/crypto/sasl/plain/PlainServer.java,
+ gnu/javax/crypto/sasl/srp/CALG.java,
+ gnu/javax/crypto/sasl/srp/ClientStore.java,
+ gnu/javax/crypto/sasl/srp/IALG.java,
+ gnu/javax/crypto/sasl/srp/KDF.java,
+ gnu/javax/crypto/sasl/srp/PasswordFile.java,
+ gnu/javax/crypto/sasl/srp/SRP.java,
+ gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java,
+ gnu/javax/crypto/sasl/srp/SRPClient.java,
+ gnu/javax/crypto/sasl/srp/SRPRegistry.java,
+ gnu/javax/crypto/sasl/srp/SRPServer.java,
+ gnu/javax/crypto/sasl/srp/SecurityContext.java,
+ gnu/javax/crypto/sasl/srp/ServerStore.java,
+ gnu/javax/crypto/sasl/srp/StoreEntry.java,
+ gnu/javax/net/ssl/Base64.java,
+ gnu/javax/net/ssl/EntropySource.java,
+ gnu/javax/net/ssl/NullManagerParameters.java,
+ gnu/javax/net/ssl/PrivateCredentials.java,
+ gnu/javax/net/ssl/SRPManagerParameters.java,
+ gnu/javax/net/ssl/SRPTrustManager.java,
+ gnu/javax/net/ssl/StaticTrustAnchors.java,
+ gnu/javax/net/ssl/provider/Alert.java,
+ gnu/javax/net/ssl/provider/AlertException.java,
+ gnu/javax/net/ssl/provider/Certificate.java,
+ gnu/javax/net/ssl/provider/CertificateRequest.java,
+ gnu/javax/net/ssl/provider/CertificateType.java,
+ gnu/javax/net/ssl/provider/CertificateVerify.java,
+ gnu/javax/net/ssl/provider/CipherSuite.java,
+ gnu/javax/net/ssl/provider/ClientHello.java,
+ gnu/javax/net/ssl/provider/ClientKeyExchange.java,
+ gnu/javax/net/ssl/provider/CompressionMethod.java,
+ gnu/javax/net/ssl/provider/Constructed.java,
+ gnu/javax/net/ssl/provider/ContentType.java,
+ gnu/javax/net/ssl/provider/Context.java,
+ gnu/javax/net/ssl/provider/DiffieHellman.java,
+ gnu/javax/net/ssl/provider/DigestInputStream.java,
+ gnu/javax/net/ssl/provider/DigestOutputStream.java,
+ gnu/javax/net/ssl/provider/Enumerated.java,
+ gnu/javax/net/ssl/provider/Extension.java,
+ gnu/javax/net/ssl/provider/Extensions.java,
+ gnu/javax/net/ssl/provider/Finished.java,
+ gnu/javax/net/ssl/provider/GNUSecurityParameters.java,
+ gnu/javax/net/ssl/provider/Handshake.java,
+ gnu/javax/net/ssl/provider/JCESecurityParameters.java,
+ gnu/javax/net/ssl/provider/JDBCSessionContext.java,
+ gnu/javax/net/ssl/provider/Jessie.java,
+ gnu/javax/net/ssl/provider/JessieDHPrivateKey.java,
+ gnu/javax/net/ssl/provider/JessieDHPublicKey.java,
+ gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java,
+ gnu/javax/net/ssl/provider/JessieRSAPublicKey.java,
+ gnu/javax/net/ssl/provider/KeyPool.java,
+ gnu/javax/net/ssl/provider/MacException.java,
+ gnu/javax/net/ssl/provider/OverflowException.java,
+ gnu/javax/net/ssl/provider/PRNG.java,
+ gnu/javax/net/ssl/provider/ProtocolVersion.java,
+ gnu/javax/net/ssl/provider/Random.java,
+ gnu/javax/net/ssl/provider/RecordInput.java,
+ gnu/javax/net/ssl/provider/RecordInputStream.java,
+ gnu/javax/net/ssl/provider/RecordOutputStream.java,
+ gnu/javax/net/ssl/provider/RecordingInputStream.java,
+ gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java,
+ gnu/javax/net/ssl/provider/SSLHMac.java,
+ gnu/javax/net/ssl/provider/SSLRSASignature.java,
+ gnu/javax/net/ssl/provider/SSLRandom.java,
+ gnu/javax/net/ssl/provider/SSLServerSocket.java,
+ gnu/javax/net/ssl/provider/SSLServerSocketFactory.java,
+ gnu/javax/net/ssl/provider/SSLSocket.java,
+ gnu/javax/net/ssl/provider/SSLSocketFactory.java,
+ gnu/javax/net/ssl/provider/SSLSocketInputStream.java,
+ gnu/javax/net/ssl/provider/SSLSocketOutputStream.java,
+ gnu/javax/net/ssl/provider/SecurityParameters.java,
+ gnu/javax/net/ssl/provider/ServerHello.java,
+ gnu/javax/net/ssl/provider/ServerKeyExchange.java,
+ gnu/javax/net/ssl/provider/Session.java,
+ gnu/javax/net/ssl/provider/SessionContext.java,
+ gnu/javax/net/ssl/provider/Signature.java,
+ gnu/javax/net/ssl/provider/SynchronizedRandom.java,
+ gnu/javax/net/ssl/provider/TLSHMac.java,
+ gnu/javax/net/ssl/provider/TLSRandom.java,
+ gnu/javax/net/ssl/provider/Util.java,
+ gnu/javax/net/ssl/provider/X509KeyManagerFactory.java,
+ gnu/javax/net/ssl/provider/X509TrustManagerFactory.java,
+ gnu/javax/net/ssl/provider/XMLSessionContext.java,
+ gnu/javax/security/auth/Password.java,
+ gnu/javax/security/auth/callback/AWTCallbackHandler.java,
+ gnu/javax/security/auth/callback/AbstractCallbackHandler.java,
+ gnu/javax/security/auth/callback/ConsoleCallbackHandler.java,
+ gnu/javax/security/auth/callback/DefaultCallbackHandler.java,
+ gnu/javax/security/auth/callback/GnuCallbacks.java,
+ gnu/javax/security/auth/callback/SwingCallbackHandler.java,
+ gnu/java/security/Registry.java,
+ gnu/java/security/Properties.java,
+ gnu/java/security/hash/BaseHash.java,
+ gnu/java/security/hash/HashFactory.java,
+ gnu/java/security/hash/Haval.java,
+ gnu/java/security/hash/IMessageDigest.java,
+ gnu/java/security/hash/MD2.java,
+ gnu/java/security/hash/MD4.java,
+ gnu/java/security/hash/MD5.java,
+ gnu/java/security/hash/RipeMD128.java,
+ gnu/java/security/hash/RipeMD160.java,
+ gnu/java/security/hash/Sha160.java,
+ gnu/java/security/hash/Sha256.java,
+ gnu/java/security/hash/Sha384.java,
+ gnu/java/security/hash/Sha512.java,
+ gnu/java/security/hash/Tiger.java,
+ gnu/java/security/hash/Whirlpool.java,
+ gnu/java/security/jce/hash/HavalSpi.java,
+ gnu/java/security/jce/hash/MD2Spi.java,
+ gnu/java/security/jce/hash/MD4Spi.java,
+ gnu/java/security/jce/hash/MD5Spi.java,
+ gnu/java/security/jce/hash/MessageDigestAdapter.java,
+ gnu/java/security/jce/hash/RipeMD128Spi.java,
+ gnu/java/security/jce/hash/RipeMD160Spi.java,
+ gnu/java/security/jce/hash/Sha160Spi.java,
+ gnu/java/security/jce/hash/Sha256Spi.java,
+ gnu/java/security/jce/hash/Sha384Spi.java,
+ gnu/java/security/jce/hash/Sha512Spi.java,
+ gnu/java/security/jce/hash/TigerSpi.java,
+ gnu/java/security/jce/hash/WhirlpoolSpi.java,
+ gnu/java/security/jce/prng/HavalRandomSpi.java,
+ gnu/java/security/jce/prng/MD2RandomSpi.java,
+ gnu/java/security/jce/prng/MD4RandomSpi.java,
+ gnu/java/security/jce/prng/MD5RandomSpi.java,
+ gnu/java/security/jce/prng/RipeMD128RandomSpi.java,
+ gnu/java/security/jce/prng/RipeMD160RandomSpi.java,
+ gnu/java/security/jce/prng/SecureRandomAdapter.java,
+ gnu/java/security/jce/prng/Sha160RandomSpi.java,
+ gnu/java/security/jce/prng/Sha256RandomSpi.java,
+ gnu/java/security/jce/prng/Sha384RandomSpi.java,
+ gnu/java/security/jce/prng/Sha512RandomSpi.java,
+ gnu/java/security/jce/prng/TigerRandomSpi.java,
+ gnu/java/security/jce/prng/WhirlpoolRandomSpi.java,
+ gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java,
+ gnu/java/security/jce/sig/DSSRawSignatureSpi.java,
+ gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java,
+ gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java,
+ gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java,
+ gnu/java/security/jce/sig/SignatureAdapter.java,
+ gnu/java/security/key/IKeyPairCodec.java,
+ gnu/java/security/key/IKeyPairGenerator.java,
+ gnu/java/security/key/KeyPairCodecFactory.java,
+ gnu/java/security/key/KeyPairGeneratorFactory.java,
+ gnu/java/security/key/dss/DSSKey.java,
+ gnu/java/security/key/dss/DSSKeyPairGenerator.java,
+ gnu/java/security/key/dss/DSSKeyPairRawCodec.java,
+ gnu/java/security/key/dss/DSSPrivateKey.java,
+ gnu/java/security/key/dss/DSSPublicKey.java,
+ gnu/java/security/key/dss/FIPS186.java,
+ gnu/java/security/key/rsa/GnuRSAKey.java,
+ gnu/java/security/key/rsa/GnuRSAPrivateKey.java,
+ gnu/java/security/key/rsa/GnuRSAPublicKey.java,
+ gnu/java/security/key/rsa/RSAKeyPairGenerator.java,
+ gnu/java/security/key/rsa/RSAKeyPairRawCodec.java,
+ gnu/java/security/prng/BasePRNG.java,
+ gnu/java/security/prng/EntropySource.java,
+ gnu/java/security/prng/IRandom.java,
+ gnu/java/security/prng/LimitReachedException.java,
+ gnu/java/security/prng/MDGenerator.java,
+ gnu/java/security/prng/PRNGFactory.java,
+ gnu/java/security/prng/RandomEvent.java,
+ gnu/java/security/prng/RandomEventListener.java,
+ gnu/java/security/sig/BaseSignature.java,
+ gnu/java/security/sig/ISignature.java,
+ gnu/java/security/sig/ISignatureCodec.java,
+ gnu/java/security/sig/SignatureFactory.java,
+ gnu/java/security/sig/dss/DSSSignature.java,
+ gnu/java/security/sig/dss/DSSSignatureRawCodec.java,
+ gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java,
+ gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java,
+ gnu/java/security/sig/rsa/EMSA_PSS.java,
+ gnu/java/security/sig/rsa/RSA.java,
+ gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java,
+ gnu/java/security/sig/rsa/RSAPSSSignature.java,
+ gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java,
+ gnu/java/security/util/Base64.java,
+ gnu/java/security/util/ExpirableObject.java,
+ gnu/java/security/util/Prime2.java,
+ gnu/java/security/util/Sequence.java,
+ gnu/java/security/util/SimpleList.java,
+ gnu/java/security/util/Util.java,
+ resource/gnu/javax/security/auth/callback/MessagesBundle.properties:
+ new files imported from GNU Crypto and Jessie.
+
2006-01-25 Tom Tromey <tromey@redhat.com>
* gnu/java/net/protocol/http/ChunkedInputStream.java (read):
diff --git a/NEWS b/NEWS
index bbf1fdc11..484f48cf5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+New in release 0.21 (to be released)
+
+* GNU Crypto and Jessie have been merged into Classpath; this will
+ provide Classpath with a wide array of cryptographic algorithms
+ (ciphers, message digests, etc.) and implementations of SSL version
+ 3 and TLS version 1. These roughly complement the public
+ `java.security.' `javax.crypto,' and `javax.net.ssl' packages, and
+ are service providers implementing the underlying algorithms.
+
New in release 0.20 (Jan 13, 2006)
* New StAX pull parser and SAX-over-StAX driver. Lots of DOM, SAX/StAX,
diff --git a/gnu/classpath/debug/Component.java b/gnu/classpath/debug/Component.java
index 242419ce4..af030ed27 100644
--- a/gnu/classpath/debug/Component.java
+++ b/gnu/classpath/debug/Component.java
@@ -89,9 +89,9 @@ public final class Component extends Level
public static final Component SSL_HANDSHAKE = new Component ("SSL HANDSHAKE", 0);
/**
- * Traces the application messages during SSL communications.
+ * Traces record layer messages during SSL communications.
*/
- public static final Component SSL_APPLICATION = new Component ("SSL APPLICATION", 1);
+ public static final Component SSL_RECORD_LAYER = new Component ("SSL RECORD LAYER", 1);
/**
* Trace details about the SSL key exchange.
diff --git a/gnu/java/security/Properties.java b/gnu/java/security/Properties.java
new file mode 100644
index 000000000..813888c20
--- /dev/null
+++ b/gnu/java/security/Properties.java
@@ -0,0 +1,374 @@
+/* Properties.java -- run-time configuration properties.
+ Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.PropertyPermission;
+
+/**
+ * <p>A global object containing build-specific properties that affect the
+ * behaviour of the generated binaries from this library.</p>
+ */
+public final class Properties
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "Properties";
+
+ private static final boolean DEBUG = false;
+
+ // private static final int debuglevel = 9;
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(final String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String VERSION = "gnu.crypto.version";
+
+ public static final String PROPERTIES_FILE = "gnu.crypto.properties.file";
+
+ public static final String REPRODUCIBLE_PRNG = "gnu.crypto.with.reproducible.prng";
+
+ public static final String CHECK_WEAK_KEYS = "gnu.crypto.with.check.for.weak.keys";
+
+ public static final String DO_RSA_BLINDING = "gnu.crypto.with.rsa.blinding";
+
+ private static final String TRUE = Boolean.TRUE.toString();
+
+ private static final String FALSE = Boolean.FALSE.toString();
+
+ private static final HashMap props = new HashMap();
+
+ private static Properties singleton = null;
+
+ private boolean reproducible = false;
+
+ private boolean checkForWeakKeys = true;
+
+ private boolean doRSABlinding = true;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private Properties()
+ {
+ super();
+ init();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the string representation of the library global configuration
+ * property with the designated <code>key</code>.</p>
+ *
+ * @param key the case-insensitive, non-null and non-empty name of a
+ * configuration property.
+ * @return the string representation of the designated property, or
+ * <code>null</code> if such property is not yet set, or <code>key</code> is
+ * empty.
+ */
+ public static final synchronized String getProperty(String key)
+ {
+ if (key == null)
+ return null;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(key, "read"));
+ key = key.trim().toLowerCase();
+ if ("".equals(key))
+ return null;
+ return (String) props.get(key);
+ }
+
+ /**
+ * <p>Sets the value of a designated library global configuration property,
+ * to a string representation of what should be a legal value.</p>
+ *
+ * @param key the case-insensitive, non-null and non-empty name of a
+ * configuration property.
+ * @param value the non-null, non-empty string representation of a legal
+ * value of the configuration property named by <code>key</code>.
+ */
+ public static final synchronized void setProperty(String key, String value)
+ {
+ if (key == null || value == null)
+ return;
+ key = key.trim().toLowerCase();
+ if ("".equals(key))
+ return;
+ if (key.equals(VERSION))
+ return;
+ value = value.trim();
+ if ("".equals(value))
+ return;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(key, "write"));
+ if (key.equals(REPRODUCIBLE_PRNG)
+ && (value.equalsIgnoreCase(TRUE) || value.equalsIgnoreCase(FALSE)))
+ setReproducible(Boolean.valueOf(value).booleanValue());
+ else if (key.equals(CHECK_WEAK_KEYS)
+ && (value.equalsIgnoreCase(TRUE) || value.equalsIgnoreCase(FALSE)))
+ setCheckForWeakKeys(Boolean.valueOf(value).booleanValue());
+ else if (key.equals(DO_RSA_BLINDING)
+ && (value.equalsIgnoreCase(TRUE) || value.equalsIgnoreCase(FALSE)))
+ setDoRSABlinding(Boolean.valueOf(value).booleanValue());
+ else
+ props.put(key, value);
+ }
+
+ /**
+ * <p>A convenience method that returns, as a boolean, the library global
+ * configuration property indicating if the default Pseudo Random Number
+ * Generator produces, or not, the same bit stream when instantiated.</p>
+ *
+ * @return <code>true</code> if the default PRNG produces the same bit stream
+ * with every VM instance. Returns <code>false</code> if the default PRNG is
+ * seeded with the time of day of its first invocation.
+ */
+ public static final synchronized boolean isReproducible()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(REPRODUCIBLE_PRNG, "read"));
+ return instance().reproducible;
+ }
+
+ /**
+ * <p>A convenience method that returns, as a boolean, the library global
+ * configuration property indicating if the implementations of symmetric
+ * key block ciphers check, or not, for possible/potential weak and semi-weak
+ * keys that may be produced in the course of generating round encryption
+ * and/or decryption keys.</p>
+ *
+ * @return <code>true</code> if the cipher implementations check for weak and
+ * semi-weak keys. Returns <code>false</code> if the cipher implementations
+ * do not check for weak or semi-weak keys.
+ */
+ public static final synchronized boolean checkForWeakKeys()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(CHECK_WEAK_KEYS, "read"));
+ return instance().checkForWeakKeys;
+ }
+
+ /**
+ * <p>A convenience method that returns, as a boolean, the library global
+ * configuration property indicating if RSA decryption (RSADP primitive),
+ * does, or not, blinding against timing attacks.</p>
+ *
+ * @return <code>true</code> if the RSA decryption primitive includes a
+ * blinding operation. Returns <code>false</code> if the RSA decryption
+ * primitive does not include the additional blinding operation.
+ */
+ public static final synchronized boolean doRSABlinding()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(DO_RSA_BLINDING, "read"));
+ return instance().doRSABlinding;
+ }
+
+ /**
+ * <p>A convenience method to set the global property for reproducibility of
+ * the default PRNG bit stream output.</p>
+ *
+ * @param value if <code>true</code> then the default PRNG bit stream output
+ * is the same with every invocation of the VM.
+ */
+ public static final synchronized void setReproducible(final boolean value)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(REPRODUCIBLE_PRNG, "write"));
+ instance().reproducible = value;
+ props.put(REPRODUCIBLE_PRNG, String.valueOf(value));
+ }
+
+ /**
+ * <p>A convenience method to set the global property for checking for weak
+ * and semi-weak cipher keys.</p>
+ *
+ * @param value if <code>true</code> then the cipher implementations will
+ * invoke additional checks for weak and semi-weak key values that may get
+ * generated.
+ */
+ public static final synchronized void setCheckForWeakKeys(final boolean value)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(CHECK_WEAK_KEYS, "write"));
+ instance().checkForWeakKeys = value;
+ props.put(CHECK_WEAK_KEYS, String.valueOf(value));
+ }
+
+ /**
+ * <p>A convenience method to set the global property fo adding a blinding
+ * operation when executing the RSA decryption primitive.</p>
+ *
+ * @param value if <code>true</code> then the code for performing the RSA
+ * decryption primitive will include a blinding operation.
+ */
+ public static final synchronized void setDoRSABlinding(final boolean value)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(DO_RSA_BLINDING, "write"));
+ instance().doRSABlinding = value;
+ props.put(DO_RSA_BLINDING, String.valueOf(value));
+ }
+
+ private static final synchronized Properties instance()
+ {
+ if (singleton == null)
+ singleton = new Properties();
+ return singleton;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+ private void init()
+ {
+ // default values
+ props.put(REPRODUCIBLE_PRNG, (reproducible ? "true" : "false"));
+ props.put(CHECK_WEAK_KEYS, (checkForWeakKeys ? "true" : "false"));
+ props.put(DO_RSA_BLINDING, (doRSABlinding ? "true" : "false"));
+
+ // 1. allow site-wide override by reading a properties file
+ String propFile = null;
+ try
+ {
+ propFile = (String) AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return System.getProperty(PROPERTIES_FILE);
+ }
+ });
+ }
+ catch (SecurityException se)
+ {
+ if (DEBUG)
+ debug("Reading property " + PROPERTIES_FILE
+ + " not allowed. Ignored.");
+ }
+ if (propFile != null)
+ {
+ try
+ {
+ final java.util.Properties temp = new java.util.Properties();
+ final FileInputStream fin = new FileInputStream(propFile);
+ temp.load(fin);
+ temp.list(System.out);
+ props.putAll(temp);
+ }
+ catch (IOException ioe)
+ {
+ if (DEBUG)
+ debug("IO error reading " + propFile + ": " + ioe.getMessage());
+ }
+ catch (SecurityException se)
+ {
+ if (DEBUG)
+ debug("Security error reading " + propFile + ": "
+ + se.getMessage());
+ }
+ }
+
+ // 2. allow vm-specific override by allowing -D options in launcher
+ handleBooleanProperty(REPRODUCIBLE_PRNG);
+ handleBooleanProperty(CHECK_WEAK_KEYS);
+ handleBooleanProperty(DO_RSA_BLINDING);
+
+ // re-sync the 'known' properties
+ reproducible = new Boolean((String) props.get(REPRODUCIBLE_PRNG)).booleanValue();
+ checkForWeakKeys = new Boolean((String) props.get(CHECK_WEAK_KEYS)).booleanValue();
+ doRSABlinding = new Boolean((String) props.get(DO_RSA_BLINDING)).booleanValue();
+
+ // This does not change.
+ props.put(VERSION, Registry.VERSION_STRING);
+ }
+
+ private void handleBooleanProperty(final String name)
+ {
+ String s = null;
+ try
+ {
+ s = System.getProperty(name);
+ }
+ catch (SecurityException x)
+ {
+ if (DEBUG)
+ debug("SecurityManager forbids reading system properties. Ignored");
+ }
+ if (s != null)
+ {
+ s = s.trim().toLowerCase();
+ // we have to test for explicit "true" or "false". anything else may
+ // hide valid value set previously
+ if (s.equals(TRUE) || s.equals(FALSE))
+ {
+ if (DEBUG)
+ debug("Setting " + name + " to '" + s + "'");
+ props.put(name, s);
+ }
+ else
+ {
+ if (DEBUG)
+ debug("Invalid value for -D" + name + ": " + s + ". Ignored");
+ }
+ }
+ }
+}
diff --git a/gnu/java/security/Registry.java b/gnu/java/security/Registry.java
new file mode 100644
index 000000000..eaea2277d
--- /dev/null
+++ b/gnu/java/security/Registry.java
@@ -0,0 +1,429 @@
+/* Registry.java --
+ Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security;
+
+/**
+ * A placeholder for <i>names</i> and <i>literals</i> used throughout this
+ * library.
+ */
+public interface Registry
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** The name of our Providers. */
+ String GNU_CRYPTO = "GNU-CRYPTO";
+
+ String GNU_SASL = "GNU-SASL";
+
+ String GNU_SECURITY = "GNU-SECURITY";
+
+ /** Our version number. */
+ String VERSION_STRING = "2.1.0";
+
+ // Names of properties to use in Maps when initialising primitives .........
+
+ // Symmetric block cipher algorithms and synonyms...........................
+
+ String ANUBIS_CIPHER = "anubis";
+
+ String BLOWFISH_CIPHER = "blowfish";
+
+ String DES_CIPHER = "des";
+
+ String KHAZAD_CIPHER = "khazad";
+
+ String RIJNDAEL_CIPHER = "rijndael";
+
+ String SERPENT_CIPHER = "serpent";
+
+ String SQUARE_CIPHER = "square";
+
+ String TRIPLEDES_CIPHER = "tripledes";
+
+ String TWOFISH_CIPHER = "twofish";
+
+ String CAST5_CIPHER = "cast5";
+
+ String NULL_CIPHER = "null";
+
+ /** AES is synonymous to Rijndael for 128-bit block size only. */
+ String AES_CIPHER = "aes";
+
+ /** TripleDES is also known as DESede. */
+ String DESEDE_CIPHER = "desede";
+
+ /** CAST5 is also known as CAST-128. */
+ String CAST128_CIPHER = "cast128";
+
+ String CAST_128_CIPHER = "cast-128";
+
+ // Message digest algorithms and synonyms...................................
+
+ String WHIRLPOOL_HASH = "whirlpool";
+
+ String RIPEMD128_HASH = "ripemd128";
+
+ String RIPEMD160_HASH = "ripemd160";
+
+ String SHA160_HASH = "sha-160";
+
+ String SHA256_HASH = "sha-256";
+
+ String SHA384_HASH = "sha-384";
+
+ String SHA512_HASH = "sha-512";
+
+ String TIGER_HASH = "tiger";
+
+ String HAVAL_HASH = "haval";
+
+ String MD5_HASH = "md5";
+
+ String MD4_HASH = "md4";
+
+ String MD2_HASH = "md2";
+
+ /** RIPEMD-128 is synonymous to RIPEMD128. */
+ String RIPEMD_128_HASH = "ripemd-128";
+
+ /** RIPEMD-160 is synonymous to RIPEMD160. */
+ String RIPEMD_160_HASH = "ripemd-160";
+
+ /** SHA-1 is synonymous to SHA-160. */
+ String SHA_1_HASH = "sha-1";
+
+ /** SHA1 is synonymous to SHA-160. */
+ String SHA1_HASH = "sha1";
+
+ /** SHA is synonymous to SHA-160. */
+ String SHA_HASH = "sha";
+
+ // Symmetric block cipher modes of operations...............................
+
+ /** Electronic CodeBook mode. */
+ String ECB_MODE = "ecb";
+
+ /** Counter (NIST) mode. */
+ String CTR_MODE = "ctr";
+
+ /** Integer Counter Mode (David McGrew). */
+ String ICM_MODE = "icm";
+
+ /** Output Feedback Mode (NIST). */
+ String OFB_MODE = "ofb";
+
+ /** Cipher block chaining mode (NIST). */
+ String CBC_MODE = "cbc";
+
+ /** Cipher feedback mode (NIST). */
+ String CFB_MODE = "cfb";
+
+ /** Authenticated-Encrypted mode. */
+ String EAX_MODE = "eax";
+
+ // Padding scheme names and synonyms........................................
+
+ /** PKCS#7 padding scheme. */
+ String PKCS7_PAD = "pkcs7";
+
+ /** Trailing Bit Complement padding scheme. */
+ String TBC_PAD = "tbc";
+
+ /** EME-PKCS1-v1_5 padding as described in section 7.2 in RFC-3447. */
+ String EME_PKCS1_V1_5_PAD = "eme-pkcs1-v1.5";
+
+ /** SSLv3 padding scheme. */
+ String SSL3_PAD = "ssl3";
+
+ /** TLSv1 padding scheme. */
+ String TLS1_PAD = "tls1";
+
+ // Pseudo-random number generators..........................................
+
+ /** (Apparently) RC4 keystream PRNG. */
+ String ARCFOUR_PRNG = "arcfour";
+
+ /** We use "rc4" as an alias for "arcfour". */
+ String RC4_PRNG = "rc4";
+
+ /** PRNG based on David McGrew's Integer Counter Mode. */
+ String ICM_PRNG = "icm";
+
+ /** PRNG based on a designated hash function. */
+ String MD_PRNG = "md";
+
+ /** PRNG based on UMAC's Key Derivation Function. */
+ String UMAC_PRNG = "umac-kdf";
+
+ /**
+ * PRNG based on PBKDF2 from PKCS #5 v.2. This is suffixed with the name
+ * of a MAC to be used as a PRF.
+ */
+ String PBKDF2_PRNG_PREFIX = "pbkdf2-";
+
+ /** The continuously-seeded pseudo-random number generator. */
+ String CSPRNG_PRNG = "csprng";
+
+ /** The Fortuna PRNG. */
+ String FORTUNA_PRNG = "fortuna";
+
+ /** The Fortuna generator PRNG. */
+ String FORTUNA_GENERATOR_PRNG = "fortuna-generator";
+
+ // Asymmetric keypair generators............................................
+
+ String DSS_KPG = "dss";
+
+ String RSA_KPG = "rsa";
+
+ String DH_KPG = "dh";
+
+ String SRP_KPG = "srp";
+
+ /** DSA is synonymous to DSS. */
+ String DSA_KPG = "dsa";
+
+ // Signature-with-appendix schemes..........................................
+
+ String DSS_SIG = "dss";
+
+ String RSA_PSS_SIG = "rsa-pss";
+
+ String RSA_PKCS1_V1_5_SIG = "rsa-pkcs1-v1.5";
+
+ /** DSA is synonymous to DSS. */
+ String DSA_SIG = "dsa";
+
+ // Key agreement protocols .................................................
+
+ String DH_KA = "dh";
+
+ String ELGAMAL_KA = "elgamal";
+
+ String SRP6_KA = "srp6";
+
+ String SRP_SASL_KA = "srp-sasl";
+
+ String SRP_TLS_KA = "srp-tls";
+
+ // Keyed-Hash Message Authentication Code ..................................
+
+ /** Name prefix of every HMAC implementation. */
+ String HMAC_NAME_PREFIX = "hmac-";
+
+ // Other MAC algorithms ....................................................
+
+ /** The One-key CBC MAC. */
+ String OMAC_PREFIX = "omac-";
+
+ /** Message Authentication Code using Universal Hashing (Ted Krovetz). */
+ String UHASH32 = "uhash32";
+
+ String UMAC32 = "umac32";
+
+ /** The Truncated Multi-Modular Hash Function -v1 (David McGrew). */
+ String TMMH16 = "tmmh16";
+
+ // String TMMH32 = "tmmh32";
+
+ // Format IDs used to identify how we externalise asymmetric keys ..........
+ String RAW_ENCODING = "gnu.crypto.raw.format";
+
+ int RAW_ENCODING_ID = 1;
+
+ // Magic bytes we generate/expect in externalised asymmetric keys ..........
+ // the four bytes represent G (0x47) for GNU, 1 (0x01) for Raw format,
+ // D (0x44) for DSS, R (0x52) for RSA, H (0x48) for Diffie-Hellman, or S
+ // (0x53) for SRP-6, and finally P (0x50) for Public, p (0x70) for private,
+ // or S (0x53) for signature.
+ byte[] MAGIC_RAW_DSS_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
+ 0x50 };
+
+ byte[] MAGIC_RAW_DSS_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
+ 0x70 };
+
+ byte[] MAGIC_RAW_DSS_SIGNATURE = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
+ 0x53 };
+
+ byte[] MAGIC_RAW_RSA_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x52,
+ 0x50 };
+
+ byte[] MAGIC_RAW_RSA_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x52,
+ 0x70 };
+
+ byte[] MAGIC_RAW_RSA_PSS_SIGNATURE = new byte[] { 0x47, RAW_ENCODING_ID,
+ 0x52, 0x53 };
+
+ byte[] MAGIC_RAW_DH_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x48,
+ 0x50 };
+
+ byte[] MAGIC_RAW_DH_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x48,
+ 0x70 };
+
+ byte[] MAGIC_RAW_SRP_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x53,
+ 0x50 };
+
+ byte[] MAGIC_RAW_SRP_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x53,
+ 0x70 };
+
+ // SASL Property names .....................................................
+
+ String SASL_PREFIX = "gnu.crypto.sasl";
+
+ /** Name of username property. */
+ String SASL_USERNAME = SASL_PREFIX + ".username";
+
+ /** Name of password property. */
+ String SASL_PASSWORD = SASL_PREFIX + ".password";
+
+ /** Name of authentication information provider packages. */
+ String SASL_AUTH_INFO_PROVIDER_PKGS = SASL_PREFIX
+ + ".auth.info.provider.pkgs";
+
+ /** SASL authorization ID. */
+ String SASL_AUTHORISATION_ID = SASL_PREFIX + ".authorisation.ID";
+
+ /** SASL protocol. */
+ String SASL_PROTOCOL = SASL_PREFIX + ".protocol";
+
+ /** SASL Server name. */
+ String SASL_SERVER_NAME = SASL_PREFIX + ".server.name";
+
+ /** SASL Callback handler. */
+ String SASL_CALLBACK_HANDLER = SASL_PREFIX + ".callback.handler";
+
+ /** SASL channel binding. */
+ String SASL_CHANNEL_BINDING = SASL_PREFIX + ".channel.binding";
+
+ // SASL data element size limits ...........................................
+
+ /** The size limit, in bytes, of a SASL OS (Octet Sequence) element. */
+ int SASL_ONE_BYTE_MAX_LIMIT = 255;
+
+ /**
+ * The size limit, in bytes, of both a SASL MPI (Multi-Precision Integer)
+ * element and a SASL Text element.
+ */
+ int SASL_TWO_BYTE_MAX_LIMIT = 65535;
+
+ /** The size limit, in bytes, of a SASL EOS (Extended Octet Sequence) element. */
+ int SASL_FOUR_BYTE_MAX_LIMIT = 2147483383;
+
+ /** The size limit, in bytes, of a SASL Buffer. */
+ int SASL_BUFFER_MAX_LIMIT = 2147483643;
+
+ // Canonical names of SASL mechanisms ......................................
+
+ String SASL_ANONYMOUS_MECHANISM = "ANONYMOUS";
+
+ String SASL_CRAM_MD5_MECHANISM = "CRAM-MD5";
+
+ String SASL_PLAIN_MECHANISM = "PLAIN";
+
+ String SASL_SRP_MECHANISM = "SRP";
+
+ // Canonical names of Integrity Protection algorithms ......................
+
+ String SASL_HMAC_MD5_IALG = "HMACwithMD5";
+
+ String SASL_HMAC_SHA_IALG = "HMACwithSHA";
+
+ // Quality Of Protection string representations ............................
+
+ /** authentication only. */
+ String QOP_AUTH = "auth";
+
+ /** authentication plus integrity protection. */
+ String QOP_AUTH_INT = "auth-int";
+
+ /** authentication plus integrity and confidentiality protection. */
+ String QOP_AUTH_CONF = "auth-conf";
+
+ // SASL mechanism strength string representation ...........................
+
+ String STRENGTH_HIGH = "high";
+
+ String STRENGTH_MEDIUM = "medium";
+
+ String STRENGTH_LOW = "low";
+
+ // SASL Server Authentication requirement ..................................
+
+ /** Server must authenticate to the client. */
+ String SERVER_AUTH_TRUE = "true";
+
+ /** Server does not need to, or cannot, authenticate to the client. */
+ String SERVER_AUTH_FALSE = "false";
+
+ // SASL mechanism reuse capability .........................................
+
+ String REUSE_TRUE = "true";
+
+ String REUSE_FALSE = "false";
+
+ // Keyrings ...............................................................
+
+ byte[] GKR_MAGIC = new byte[] { 0x47, 0x4b, 0x52, 0x01 };
+
+ // Ring usage fields.
+ int GKR_PRIVATE_KEYS = 1 << 0;
+
+ int GKR_PUBLIC_CREDENTIALS = 1 << 1;
+
+ int GKR_CERTIFICATES = 1 << 2;
+
+ // HMac types.
+ int GKR_HMAC_MD5_128 = 0;
+
+ int GKR_HMAC_SHA_160 = 1;
+
+ int GKR_HMAC_MD5_96 = 2;
+
+ int GKR_HMAC_SHA_96 = 3;
+
+ // Cipher types.
+ int GKR_CIPHER_AES_128_OFB = 0;
+
+ int GKR_CIPHER_AES_128_CBC = 1;
+
+ // Methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/hash/BaseHash.java b/gnu/java/security/hash/BaseHash.java
new file mode 100644
index 000000000..720b83539
--- /dev/null
+++ b/gnu/java/security/hash/BaseHash.java
@@ -0,0 +1,206 @@
+/* BaseHash.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+/**
+ * <p>A base abstract class to facilitate hash implementations.</p>
+ */
+public abstract class BaseHash implements IMessageDigest
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of the hash. */
+ protected String name;
+
+ /** The hash (output) size in bytes. */
+ protected int hashSize;
+
+ /** The hash (inner) block size in bytes. */
+ protected int blockSize;
+
+ /** Number of bytes processed so far. */
+ protected long count;
+
+ /** Temporary input buffer. */
+ protected byte[] buffer;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name prefix of this instance.
+ * @param hashSize the block size of the output in bytes.
+ * @param blockSize the block size of the internal transform.
+ */
+ protected BaseHash(String name, int hashSize, int blockSize)
+ {
+ super();
+
+ this.name = name;
+ this.hashSize = hashSize;
+ this.blockSize = blockSize;
+ this.buffer = new byte[blockSize];
+
+ resetContext();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IMessageDigest interface implementation ---------------------------------
+
+ public String name()
+ {
+ return name;
+ }
+
+ public int hashSize()
+ {
+ return hashSize;
+ }
+
+ public int blockSize()
+ {
+ return blockSize;
+ }
+
+ public void update(byte b)
+ {
+ // compute number of bytes still unhashed; ie. present in buffer
+ int i = (int) (count % blockSize);
+ count++;
+ buffer[i] = b;
+ if (i == (blockSize - 1))
+ {
+ transform(buffer, 0);
+ }
+ }
+
+ public void update(byte[] b)
+ {
+ update(b, 0, b.length);
+ }
+
+ public void update(byte[] b, int offset, int len)
+ {
+ int n = (int) (count % blockSize);
+ count += len;
+ int partLen = blockSize - n;
+ int i = 0;
+
+ if (len >= partLen)
+ {
+ System.arraycopy(b, offset, buffer, n, partLen);
+ transform(buffer, 0);
+ for (i = partLen; i + blockSize - 1 < len; i += blockSize)
+ {
+ transform(b, offset + i);
+ }
+ n = 0;
+ }
+
+ if (i < len)
+ {
+ System.arraycopy(b, offset + i, buffer, n, len - i);
+ }
+ }
+
+ public byte[] digest()
+ {
+ byte[] tail = padBuffer(); // pad remaining bytes in buffer
+ update(tail, 0, tail.length); // last transform of a message
+ byte[] result = getResult(); // make a result out of context
+
+ reset(); // reset this instance for future re-use
+
+ return result;
+ }
+
+ public void reset()
+ { // reset this instance for future re-use
+ count = 0L;
+ for (int i = 0; i < blockSize;)
+ {
+ buffer[i++] = 0;
+ }
+
+ resetContext();
+ }
+
+ // methods to be implemented by concrete subclasses ------------------------
+
+ public abstract Object clone();
+
+ public abstract boolean selfTest();
+
+ /**
+ * <p>Returns the byte array to use as padding before completing a hash
+ * operation.</p>
+ *
+ * @return the bytes to pad the remaining bytes in the buffer before
+ * completing a hash operation.
+ */
+ protected abstract byte[] padBuffer();
+
+ /**
+ * <p>Constructs the result from the contents of the current context.</p>
+ *
+ * @return the output of the completed hash operation.
+ */
+ protected abstract byte[] getResult();
+
+ /** Resets the instance for future re-use. */
+ protected abstract void resetContext();
+
+ /**
+ * <p>The block digest transformation per se.</p>
+ *
+ * @param in the <i>blockSize</i> long block, as an array of bytes to digest.
+ * @param offset the index where the data to digest is located within the
+ * input buffer.
+ */
+ protected abstract void transform(byte[] in, int offset);
+}
diff --git a/gnu/java/security/hash/HashFactory.java b/gnu/java/security/hash/HashFactory.java
new file mode 100644
index 000000000..e52092123
--- /dev/null
+++ b/gnu/java/security/hash/HashFactory.java
@@ -0,0 +1,178 @@
+/* HashFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>A <i>Factory</i> to instantiate message digest algorithm instances.</p>
+ */
+public class HashFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce <i>Singleton</i> pattern. */
+ private HashFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Return an instance of a hash algorithm given its name.</p>
+ *
+ * @param name the name of the hash algorithm.
+ * @return an instance of the hash algorithm, or null if none found.
+ * @exception InternalError if the implementation does not pass its self-
+ * test.
+ */
+ public static IMessageDigest getInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ IMessageDigest result = null;
+ if (name.equalsIgnoreCase(Registry.WHIRLPOOL_HASH))
+ {
+ result = new Whirlpool();
+ }
+ else if (name.equalsIgnoreCase(Registry.RIPEMD128_HASH)
+ || name.equalsIgnoreCase(Registry.RIPEMD_128_HASH))
+ {
+ result = new RipeMD128();
+ }
+ else if (name.equalsIgnoreCase(Registry.RIPEMD160_HASH)
+ || name.equalsIgnoreCase(Registry.RIPEMD_160_HASH))
+ {
+ result = new RipeMD160();
+ }
+ else if (name.equalsIgnoreCase(Registry.SHA160_HASH)
+ || name.equalsIgnoreCase(Registry.SHA_1_HASH)
+ || name.equalsIgnoreCase(Registry.SHA1_HASH)
+ || name.equalsIgnoreCase(Registry.SHA_HASH))
+ {
+ result = new Sha160();
+ }
+ else if (name.equalsIgnoreCase(Registry.SHA256_HASH))
+ {
+ result = new Sha256();
+ }
+ else if (name.equalsIgnoreCase(Registry.SHA384_HASH))
+ {
+ result = new Sha384();
+ }
+ else if (name.equalsIgnoreCase(Registry.SHA512_HASH))
+ {
+ result = new Sha512();
+ }
+ else if (name.equalsIgnoreCase(Registry.TIGER_HASH))
+ {
+ result = new Tiger();
+ }
+ else if (name.equalsIgnoreCase(Registry.HAVAL_HASH))
+ {
+ result = new Haval();
+ }
+ else if (name.equalsIgnoreCase(Registry.MD5_HASH))
+ {
+ result = new MD5();
+ }
+ else if (name.equalsIgnoreCase(Registry.MD4_HASH))
+ {
+ result = new MD4();
+ }
+ else if (name.equalsIgnoreCase(Registry.MD2_HASH))
+ {
+ result = new MD2();
+ }
+ else if (name.equalsIgnoreCase(Registry.HAVAL_HASH))
+ {
+ result = new Haval();
+ }
+
+ if (result != null && !result.selfTest())
+ {
+ throw new InternalError(result.name());
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of names of hash algorithms supported by this
+ * <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of hash names (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.WHIRLPOOL_HASH);
+ hs.add(Registry.RIPEMD128_HASH);
+ hs.add(Registry.RIPEMD160_HASH);
+ hs.add(Registry.SHA160_HASH);
+ hs.add(Registry.SHA256_HASH);
+ hs.add(Registry.SHA384_HASH);
+ hs.add(Registry.SHA512_HASH);
+ hs.add(Registry.TIGER_HASH);
+ hs.add(Registry.HAVAL_HASH);
+ hs.add(Registry.MD5_HASH);
+ hs.add(Registry.MD4_HASH);
+ hs.add(Registry.MD2_HASH);
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/hash/Haval.java b/gnu/java/security/hash/Haval.java
new file mode 100644
index 000000000..f9f3282f2
--- /dev/null
+++ b/gnu/java/security/hash/Haval.java
@@ -0,0 +1,759 @@
+/* Haval.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>The <i>HAVAL</i> message-digest algorithm is a variable output length,
+ * with variable number of rounds. By default, this implementation allows
+ * <i>HAVAL</i> to be used as a drop-in replacement for <i>MD5</i>.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>HAVAL - A One-Way Hashing Algorithm with Variable Length of Output<br>
+ * Advances in Cryptology - AUSCRYPT'92, Lecture Notes in Computer Science,<br>
+ * Springer-Verlag, 1993; <br>
+ * Y. Zheng, J. Pieprzyk and J. Seberry.</li>
+ * </ol>
+ */
+public class Haval extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int HAVAL_VERSION = 1;
+
+ public static final int HAVAL_128_BIT = 16;
+
+ public static final int HAVAL_160_BIT = 20;
+
+ public static final int HAVAL_192_BIT = 24;
+
+ public static final int HAVAL_224_BIT = 28;
+
+ public static final int HAVAL_256_BIT = 32;
+
+ public static final int HAVAL_3_ROUND = 3;
+
+ public static final int HAVAL_4_ROUND = 4;
+
+ public static final int HAVAL_5_ROUND = 5;
+
+ private static final int BLOCK_SIZE = 128; // inner block size in bytes
+
+ private static final String DIGEST0 = "C68F39913F901F3DDF44C707357A7D70";
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /**
+ * Number of HAVAL rounds. Allowed values are integers in the range <code>3
+ * .. 5</code>. The default is <code>3</code>.
+ */
+ private int rounds = HAVAL_3_ROUND;
+
+ /** 128-bit interim result. */
+ private int h0, h1, h2, h3, h4, h5, h6, h7;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Calls the constructor with two argument using {@link #HAVAL_128_BIT} as
+ * the value for the output size (i.e. <code>128</code> bits, and
+ * {@link #HAVAL_3_ROUND} for the value of number of rounds.</p>
+ */
+ public Haval()
+ {
+ this(HAVAL_128_BIT, HAVAL_3_ROUND);
+ }
+
+ /**
+ * <p>Calls the constructor with two arguments using the designated output
+ * size, and {@link #HAVAL_3_ROUND} for the value of number of rounds.</p>
+ *
+ * @param size the output size in bytes of this instance.
+ * @throws IllegalArgumentException if the designated output size is invalid.
+ * @see #HAVAL_128_BIT
+ * @see #HAVAL_160_BIT
+ * @see #HAVAL_192_BIT
+ * @see #HAVAL_224_BIT
+ * @see #HAVAL_256_BIT
+ */
+ public Haval(int size)
+ {
+ this(size, HAVAL_3_ROUND);
+ }
+
+ /**
+ * <p>Constructs a <code>Haval</code> instance with the designated output
+ * size (in bytes). Valid output <code>size</code> values are <code>16</code>,
+ * <code>20</code>, <code>24</code>, <code>28</code> and <code>32</code>.
+ * Valid values for <code>rounds</code> are in the range <code>3..5</code>
+ * inclusive.</p>
+ *
+ * @param size the output size in bytes of this instance.
+ * @param rounds the number of rounds to apply when transforming data.
+ * @throws IllegalArgumentException if the designated output size is invalid,
+ * or if the number of rounds is invalid.
+ * @see #HAVAL_128_BIT
+ * @see #HAVAL_160_BIT
+ * @see #HAVAL_192_BIT
+ * @see #HAVAL_224_BIT
+ * @see #HAVAL_256_BIT
+ * @see #HAVAL_3_ROUND
+ * @see #HAVAL_4_ROUND
+ * @see #HAVAL_5_ROUND
+ */
+ public Haval(int size, int rounds)
+ {
+ super(Registry.HAVAL_HASH, size, BLOCK_SIZE);
+
+ if (size != HAVAL_128_BIT && size != HAVAL_160_BIT && size != HAVAL_192_BIT
+ && size != HAVAL_224_BIT && size != HAVAL_256_BIT)
+ {
+ throw new IllegalArgumentException("Invalid HAVAL output size");
+ }
+
+ if (rounds != HAVAL_3_ROUND && rounds != HAVAL_4_ROUND
+ && rounds != HAVAL_5_ROUND)
+ {
+ throw new IllegalArgumentException("Invalid HAVAL number of rounds");
+ }
+
+ this.rounds = rounds;
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Haval(Haval md)
+ {
+ this(md.hashSize, md.rounds);
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.h5 = md.h5;
+ this.h6 = md.h6;
+ this.h7 = md.h7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Haval(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected synchronized void transform(byte[] in, int i)
+ {
+ int X0 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X1 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X2 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X3 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X4 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X5 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X6 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X7 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X8 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X9 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X10 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X11 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X12 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X13 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X14 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X15 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X16 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X17 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X18 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X19 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X20 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X21 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X22 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X23 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X24 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X25 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X26 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X27 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X28 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X29 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X30 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X31 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+
+ int t0 = h0, t1 = h1, t2 = h2, t3 = h3, t4 = h4, t5 = h5, t6 = h6, t7 = h7;
+
+ // Pass 1
+ t7 = FF1(t7, t6, t5, t4, t3, t2, t1, t0, X0);
+ t6 = FF1(t6, t5, t4, t3, t2, t1, t0, t7, X1);
+ t5 = FF1(t5, t4, t3, t2, t1, t0, t7, t6, X2);
+ t4 = FF1(t4, t3, t2, t1, t0, t7, t6, t5, X3);
+ t3 = FF1(t3, t2, t1, t0, t7, t6, t5, t4, X4);
+ t2 = FF1(t2, t1, t0, t7, t6, t5, t4, t3, X5);
+ t1 = FF1(t1, t0, t7, t6, t5, t4, t3, t2, X6);
+ t0 = FF1(t0, t7, t6, t5, t4, t3, t2, t1, X7);
+
+ t7 = FF1(t7, t6, t5, t4, t3, t2, t1, t0, X8);
+ t6 = FF1(t6, t5, t4, t3, t2, t1, t0, t7, X9);
+ t5 = FF1(t5, t4, t3, t2, t1, t0, t7, t6, X10);
+ t4 = FF1(t4, t3, t2, t1, t0, t7, t6, t5, X11);
+ t3 = FF1(t3, t2, t1, t0, t7, t6, t5, t4, X12);
+ t2 = FF1(t2, t1, t0, t7, t6, t5, t4, t3, X13);
+ t1 = FF1(t1, t0, t7, t6, t5, t4, t3, t2, X14);
+ t0 = FF1(t0, t7, t6, t5, t4, t3, t2, t1, X15);
+
+ t7 = FF1(t7, t6, t5, t4, t3, t2, t1, t0, X16);
+ t6 = FF1(t6, t5, t4, t3, t2, t1, t0, t7, X17);
+ t5 = FF1(t5, t4, t3, t2, t1, t0, t7, t6, X18);
+ t4 = FF1(t4, t3, t2, t1, t0, t7, t6, t5, X19);
+ t3 = FF1(t3, t2, t1, t0, t7, t6, t5, t4, X20);
+ t2 = FF1(t2, t1, t0, t7, t6, t5, t4, t3, X21);
+ t1 = FF1(t1, t0, t7, t6, t5, t4, t3, t2, X22);
+ t0 = FF1(t0, t7, t6, t5, t4, t3, t2, t1, X23);
+
+ t7 = FF1(t7, t6, t5, t4, t3, t2, t1, t0, X24);
+ t6 = FF1(t6, t5, t4, t3, t2, t1, t0, t7, X25);
+ t5 = FF1(t5, t4, t3, t2, t1, t0, t7, t6, X26);
+ t4 = FF1(t4, t3, t2, t1, t0, t7, t6, t5, X27);
+ t3 = FF1(t3, t2, t1, t0, t7, t6, t5, t4, X28);
+ t2 = FF1(t2, t1, t0, t7, t6, t5, t4, t3, X29);
+ t1 = FF1(t1, t0, t7, t6, t5, t4, t3, t2, X30);
+ t0 = FF1(t0, t7, t6, t5, t4, t3, t2, t1, X31);
+
+ // Pass 2
+ t7 = FF2(t7, t6, t5, t4, t3, t2, t1, t0, X5, 0x452821E6);
+ t6 = FF2(t6, t5, t4, t3, t2, t1, t0, t7, X14, 0x38D01377);
+ t5 = FF2(t5, t4, t3, t2, t1, t0, t7, t6, X26, 0xBE5466CF);
+ t4 = FF2(t4, t3, t2, t1, t0, t7, t6, t5, X18, 0x34E90C6C);
+ t3 = FF2(t3, t2, t1, t0, t7, t6, t5, t4, X11, 0xC0AC29B7);
+ t2 = FF2(t2, t1, t0, t7, t6, t5, t4, t3, X28, 0xC97C50DD);
+ t1 = FF2(t1, t0, t7, t6, t5, t4, t3, t2, X7, 0x3F84D5B5);
+ t0 = FF2(t0, t7, t6, t5, t4, t3, t2, t1, X16, 0xB5470917);
+
+ t7 = FF2(t7, t6, t5, t4, t3, t2, t1, t0, X0, 0x9216D5D9);
+ t6 = FF2(t6, t5, t4, t3, t2, t1, t0, t7, X23, 0x8979FB1B);
+ t5 = FF2(t5, t4, t3, t2, t1, t0, t7, t6, X20, 0xD1310BA6);
+ t4 = FF2(t4, t3, t2, t1, t0, t7, t6, t5, X22, 0x98DFB5AC);
+ t3 = FF2(t3, t2, t1, t0, t7, t6, t5, t4, X1, 0x2FFD72DB);
+ t2 = FF2(t2, t1, t0, t7, t6, t5, t4, t3, X10, 0xD01ADFB7);
+ t1 = FF2(t1, t0, t7, t6, t5, t4, t3, t2, X4, 0xB8E1AFED);
+ t0 = FF2(t0, t7, t6, t5, t4, t3, t2, t1, X8, 0x6A267E96);
+
+ t7 = FF2(t7, t6, t5, t4, t3, t2, t1, t0, X30, 0xBA7C9045);
+ t6 = FF2(t6, t5, t4, t3, t2, t1, t0, t7, X3, 0xF12C7F99);
+ t5 = FF2(t5, t4, t3, t2, t1, t0, t7, t6, X21, 0x24A19947);
+ t4 = FF2(t4, t3, t2, t1, t0, t7, t6, t5, X9, 0xB3916CF7);
+ t3 = FF2(t3, t2, t1, t0, t7, t6, t5, t4, X17, 0x0801F2E2);
+ t2 = FF2(t2, t1, t0, t7, t6, t5, t4, t3, X24, 0x858EFC16);
+ t1 = FF2(t1, t0, t7, t6, t5, t4, t3, t2, X29, 0x636920D8);
+ t0 = FF2(t0, t7, t6, t5, t4, t3, t2, t1, X6, 0x71574E69);
+
+ t7 = FF2(t7, t6, t5, t4, t3, t2, t1, t0, X19, 0xA458FEA3);
+ t6 = FF2(t6, t5, t4, t3, t2, t1, t0, t7, X12, 0xF4933D7E);
+ t5 = FF2(t5, t4, t3, t2, t1, t0, t7, t6, X15, 0x0D95748F);
+ t4 = FF2(t4, t3, t2, t1, t0, t7, t6, t5, X13, 0x728EB658);
+ t3 = FF2(t3, t2, t1, t0, t7, t6, t5, t4, X2, 0x718BCD58);
+ t2 = FF2(t2, t1, t0, t7, t6, t5, t4, t3, X25, 0x82154AEE);
+ t1 = FF2(t1, t0, t7, t6, t5, t4, t3, t2, X31, 0x7B54A41D);
+ t0 = FF2(t0, t7, t6, t5, t4, t3, t2, t1, X27, 0xC25A59B5);
+
+ // Pass 3
+ t7 = FF3(t7, t6, t5, t4, t3, t2, t1, t0, X19, 0x9C30D539);
+ t6 = FF3(t6, t5, t4, t3, t2, t1, t0, t7, X9, 0x2AF26013);
+ t5 = FF3(t5, t4, t3, t2, t1, t0, t7, t6, X4, 0xC5D1B023);
+ t4 = FF3(t4, t3, t2, t1, t0, t7, t6, t5, X20, 0x286085F0);
+ t3 = FF3(t3, t2, t1, t0, t7, t6, t5, t4, X28, 0xCA417918);
+ t2 = FF3(t2, t1, t0, t7, t6, t5, t4, t3, X17, 0xB8DB38EF);
+ t1 = FF3(t1, t0, t7, t6, t5, t4, t3, t2, X8, 0x8E79DCB0);
+ t0 = FF3(t0, t7, t6, t5, t4, t3, t2, t1, X22, 0x603A180E);
+
+ t7 = FF3(t7, t6, t5, t4, t3, t2, t1, t0, X29, 0x6C9E0E8B);
+ t6 = FF3(t6, t5, t4, t3, t2, t1, t0, t7, X14, 0xB01E8A3E);
+ t5 = FF3(t5, t4, t3, t2, t1, t0, t7, t6, X25, 0xD71577C1);
+ t4 = FF3(t4, t3, t2, t1, t0, t7, t6, t5, X12, 0xBD314B27);
+ t3 = FF3(t3, t2, t1, t0, t7, t6, t5, t4, X24, 0x78AF2FDA);
+ t2 = FF3(t2, t1, t0, t7, t6, t5, t4, t3, X30, 0x55605C60);
+ t1 = FF3(t1, t0, t7, t6, t5, t4, t3, t2, X16, 0xE65525F3);
+ t0 = FF3(t0, t7, t6, t5, t4, t3, t2, t1, X26, 0xAA55AB94);
+
+ t7 = FF3(t7, t6, t5, t4, t3, t2, t1, t0, X31, 0x57489862);
+ t6 = FF3(t6, t5, t4, t3, t2, t1, t0, t7, X15, 0x63E81440);
+ t5 = FF3(t5, t4, t3, t2, t1, t0, t7, t6, X7, 0x55CA396A);
+ t4 = FF3(t4, t3, t2, t1, t0, t7, t6, t5, X3, 0x2AAB10B6);
+ t3 = FF3(t3, t2, t1, t0, t7, t6, t5, t4, X1, 0xB4CC5C34);
+ t2 = FF3(t2, t1, t0, t7, t6, t5, t4, t3, X0, 0x1141E8CE);
+ t1 = FF3(t1, t0, t7, t6, t5, t4, t3, t2, X18, 0xA15486AF);
+ t0 = FF3(t0, t7, t6, t5, t4, t3, t2, t1, X27, 0x7C72E993);
+
+ t7 = FF3(t7, t6, t5, t4, t3, t2, t1, t0, X13, 0xB3EE1411);
+ t6 = FF3(t6, t5, t4, t3, t2, t1, t0, t7, X6, 0x636FBC2A);
+ t5 = FF3(t5, t4, t3, t2, t1, t0, t7, t6, X21, 0x2BA9C55D);
+ t4 = FF3(t4, t3, t2, t1, t0, t7, t6, t5, X10, 0x741831F6);
+ t3 = FF3(t3, t2, t1, t0, t7, t6, t5, t4, X23, 0xCE5C3E16);
+ t2 = FF3(t2, t1, t0, t7, t6, t5, t4, t3, X11, 0x9B87931E);
+ t1 = FF3(t1, t0, t7, t6, t5, t4, t3, t2, X5, 0xAFD6BA33);
+ t0 = FF3(t0, t7, t6, t5, t4, t3, t2, t1, X2, 0x6C24CF5C);
+
+ if (rounds >= 4)
+ {
+ t7 = FF4(t7, t6, t5, t4, t3, t2, t1, t0, X24, 0x7A325381);
+ t6 = FF4(t6, t5, t4, t3, t2, t1, t0, t7, X4, 0x28958677);
+ t5 = FF4(t5, t4, t3, t2, t1, t0, t7, t6, X0, 0x3B8F4898);
+ t4 = FF4(t4, t3, t2, t1, t0, t7, t6, t5, X14, 0x6B4BB9AF);
+ t3 = FF4(t3, t2, t1, t0, t7, t6, t5, t4, X2, 0xC4BFE81B);
+ t2 = FF4(t2, t1, t0, t7, t6, t5, t4, t3, X7, 0x66282193);
+ t1 = FF4(t1, t0, t7, t6, t5, t4, t3, t2, X28, 0x61D809CC);
+ t0 = FF4(t0, t7, t6, t5, t4, t3, t2, t1, X23, 0xFB21A991);
+ t7 = FF4(t7, t6, t5, t4, t3, t2, t1, t0, X26, 0x487CAC60);
+ t6 = FF4(t6, t5, t4, t3, t2, t1, t0, t7, X6, 0x5DEC8032);
+ t5 = FF4(t5, t4, t3, t2, t1, t0, t7, t6, X30, 0xEF845D5D);
+ t4 = FF4(t4, t3, t2, t1, t0, t7, t6, t5, X20, 0xE98575B1);
+ t3 = FF4(t3, t2, t1, t0, t7, t6, t5, t4, X18, 0xDC262302);
+ t2 = FF4(t2, t1, t0, t7, t6, t5, t4, t3, X25, 0xEB651B88);
+ t1 = FF4(t1, t0, t7, t6, t5, t4, t3, t2, X19, 0x23893E81);
+ t0 = FF4(t0, t7, t6, t5, t4, t3, t2, t1, X3, 0xD396ACC5);
+
+ t7 = FF4(t7, t6, t5, t4, t3, t2, t1, t0, X22, 0x0F6D6FF3);
+ t6 = FF4(t6, t5, t4, t3, t2, t1, t0, t7, X11, 0x83F44239);
+ t5 = FF4(t5, t4, t3, t2, t1, t0, t7, t6, X31, 0x2E0B4482);
+ t4 = FF4(t4, t3, t2, t1, t0, t7, t6, t5, X21, 0xA4842004);
+ t3 = FF4(t3, t2, t1, t0, t7, t6, t5, t4, X8, 0x69C8F04A);
+ t2 = FF4(t2, t1, t0, t7, t6, t5, t4, t3, X27, 0x9E1F9B5E);
+ t1 = FF4(t1, t0, t7, t6, t5, t4, t3, t2, X12, 0x21C66842);
+ t0 = FF4(t0, t7, t6, t5, t4, t3, t2, t1, X9, 0xF6E96C9A);
+ t7 = FF4(t7, t6, t5, t4, t3, t2, t1, t0, X1, 0x670C9C61);
+ t6 = FF4(t6, t5, t4, t3, t2, t1, t0, t7, X29, 0xABD388F0);
+ t5 = FF4(t5, t4, t3, t2, t1, t0, t7, t6, X5, 0x6A51A0D2);
+ t4 = FF4(t4, t3, t2, t1, t0, t7, t6, t5, X15, 0xD8542F68);
+ t3 = FF4(t3, t2, t1, t0, t7, t6, t5, t4, X17, 0x960FA728);
+ t2 = FF4(t2, t1, t0, t7, t6, t5, t4, t3, X10, 0xAB5133A3);
+ t1 = FF4(t1, t0, t7, t6, t5, t4, t3, t2, X16, 0x6EEF0B6C);
+ t0 = FF4(t0, t7, t6, t5, t4, t3, t2, t1, X13, 0x137A3BE4);
+
+ if (rounds == 5)
+ {
+ t7 = FF5(t7, t6, t5, t4, t3, t2, t1, t0, X27, 0xBA3BF050);
+ t6 = FF5(t6, t5, t4, t3, t2, t1, t0, t7, X3, 0x7EFB2A98);
+ t5 = FF5(t5, t4, t3, t2, t1, t0, t7, t6, X21, 0xA1F1651D);
+ t4 = FF5(t4, t3, t2, t1, t0, t7, t6, t5, X26, 0x39AF0176);
+ t3 = FF5(t3, t2, t1, t0, t7, t6, t5, t4, X17, 0x66CA593E);
+ t2 = FF5(t2, t1, t0, t7, t6, t5, t4, t3, X11, 0x82430E88);
+ t1 = FF5(t1, t0, t7, t6, t5, t4, t3, t2, X20, 0x8CEE8619);
+ t0 = FF5(t0, t7, t6, t5, t4, t3, t2, t1, X29, 0x456F9FB4);
+
+ t7 = FF5(t7, t6, t5, t4, t3, t2, t1, t0, X19, 0x7D84A5C3);
+ t6 = FF5(t6, t5, t4, t3, t2, t1, t0, t7, X0, 0x3B8B5EBE);
+ t5 = FF5(t5, t4, t3, t2, t1, t0, t7, t6, X12, 0xE06F75D8);
+ t4 = FF5(t4, t3, t2, t1, t0, t7, t6, t5, X7, 0x85C12073);
+ t3 = FF5(t3, t2, t1, t0, t7, t6, t5, t4, X13, 0x401A449F);
+ t2 = FF5(t2, t1, t0, t7, t6, t5, t4, t3, X8, 0x56C16AA6);
+ t1 = FF5(t1, t0, t7, t6, t5, t4, t3, t2, X31, 0x4ED3AA62);
+ t0 = FF5(t0, t7, t6, t5, t4, t3, t2, t1, X10, 0x363F7706);
+
+ t7 = FF5(t7, t6, t5, t4, t3, t2, t1, t0, X5, 0x1BFEDF72);
+ t6 = FF5(t6, t5, t4, t3, t2, t1, t0, t7, X9, 0x429B023D);
+ t5 = FF5(t5, t4, t3, t2, t1, t0, t7, t6, X14, 0x37D0D724);
+ t4 = FF5(t4, t3, t2, t1, t0, t7, t6, t5, X30, 0xD00A1248);
+ t3 = FF5(t3, t2, t1, t0, t7, t6, t5, t4, X18, 0xDB0FEAD3);
+ t2 = FF5(t2, t1, t0, t7, t6, t5, t4, t3, X6, 0x49F1C09B);
+ t1 = FF5(t1, t0, t7, t6, t5, t4, t3, t2, X28, 0x075372C9);
+ t0 = FF5(t0, t7, t6, t5, t4, t3, t2, t1, X24, 0x80991B7B);
+
+ t7 = FF5(t7, t6, t5, t4, t3, t2, t1, t0, X2, 0x25D479D8);
+ t6 = FF5(t6, t5, t4, t3, t2, t1, t0, t7, X23, 0xF6E8DEF7);
+ t5 = FF5(t5, t4, t3, t2, t1, t0, t7, t6, X16, 0xE3FE501A);
+ t4 = FF5(t4, t3, t2, t1, t0, t7, t6, t5, X22, 0xB6794C3B);
+ t3 = FF5(t3, t2, t1, t0, t7, t6, t5, t4, X4, 0x976CE0BD);
+ t2 = FF5(t2, t1, t0, t7, t6, t5, t4, t3, X1, 0x04C006BA);
+ t1 = FF5(t1, t0, t7, t6, t5, t4, t3, t2, X25, 0xC1A94FB6);
+ t0 = FF5(t0, t7, t6, t5, t4, t3, t2, t1, X15, 0x409F60C4);
+ }
+ }
+
+ h7 += t7;
+ h6 += t6;
+ h5 += t5;
+ h4 += t4;
+ h3 += t3;
+ h2 += t2;
+ h1 += t1;
+ h0 += t0;
+ }
+
+ protected byte[] padBuffer()
+ {
+ // pad out to 118 mod 128. other 10 bytes have special use.
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 118) ? (118 - n) : (246 - n);
+ byte[] result = new byte[padding + 10];
+ result[0] = (byte) 0x01;
+
+ // save the version number (LSB 3), the number of rounds (3 bits in the
+ // middle), the fingerprint length (MSB 2 bits and next byte) and the
+ // number of bits in the unpadded message.
+ int bl = hashSize * 8;
+ result[padding++] = (byte) (((bl & 0x03) << 6) | ((rounds & 0x07) << 3) | (HAVAL_VERSION & 0x07));
+ result[padding++] = (byte) (bl >>> 2);
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) bits;
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding] = (byte) (bits >>> 56);
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ tailorDigestBits(); // tailor context for the designated output size
+ // cast enough top context values into an array of hashSize bytes
+ byte[] result = new byte[hashSize];
+ if (hashSize >= HAVAL_256_BIT)
+ {
+ result[31] = (byte) (h7 >>> 24);
+ result[30] = (byte) (h7 >>> 16);
+ result[29] = (byte) (h7 >>> 8);
+ result[28] = (byte) h7;
+ }
+ if (hashSize >= HAVAL_224_BIT)
+ {
+ result[27] = (byte) (h6 >>> 24);
+ result[26] = (byte) (h6 >>> 16);
+ result[25] = (byte) (h6 >>> 8);
+ result[24] = (byte) h6;
+ }
+ if (hashSize >= HAVAL_192_BIT)
+ {
+ result[23] = (byte) (h5 >>> 24);
+ result[22] = (byte) (h5 >>> 16);
+ result[21] = (byte) (h5 >>> 8);
+ result[20] = (byte) h5;
+ }
+ if (hashSize >= HAVAL_160_BIT)
+ {
+ result[19] = (byte) (h4 >>> 24);
+ result[18] = (byte) (h4 >>> 16);
+ result[17] = (byte) (h4 >>> 8);
+ result[16] = (byte) h4;
+ }
+ result[15] = (byte) (h3 >>> 24);
+ result[14] = (byte) (h3 >>> 16);
+ result[13] = (byte) (h3 >>> 8);
+ result[12] = (byte) h3;
+ result[11] = (byte) (h2 >>> 24);
+ result[10] = (byte) (h2 >>> 16);
+ result[9] = (byte) (h2 >>> 8);
+ result[8] = (byte) h2;
+ result[7] = (byte) (h1 >>> 24);
+ result[6] = (byte) (h1 >>> 16);
+ result[5] = (byte) (h1 >>> 8);
+ result[4] = (byte) h1;
+ result[3] = (byte) (h0 >>> 24);
+ result[2] = (byte) (h0 >>> 16);
+ result[1] = (byte) (h0 >>> 8);
+ result[0] = (byte) h0;
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ h0 = 0x243F6A88;
+ h1 = 0x85A308D3;
+ h2 = 0x13198A2E;
+ h3 = 0x03707344;
+ h4 = 0xA4093822;
+ h5 = 0x299F31D0;
+ h6 = 0x082EFA98;
+ h7 = 0xEC4E6C89;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new Haval().digest())));
+ }
+ return valid.booleanValue();
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /** Tailors the last output. */
+ private void tailorDigestBits()
+ {
+ int t;
+ switch (hashSize)
+ {
+ case HAVAL_128_BIT:
+ t = (h7 & 0x000000FF) | (h6 & 0xFF000000) | (h5 & 0x00FF0000)
+ | (h4 & 0x0000FF00);
+ h0 += t >>> 8 | t << 24;
+ t = (h7 & 0x0000FF00) | (h6 & 0x000000FF) | (h5 & 0xFF000000)
+ | (h4 & 0x00FF0000);
+ h1 += t >>> 16 | t << 16;
+ t = (h7 & 0x00FF0000) | (h6 & 0x0000FF00) | (h5 & 0x000000FF)
+ | (h4 & 0xFF000000);
+ h2 += t >>> 24 | t << 8;
+ t = (h7 & 0xFF000000) | (h6 & 0x00FF0000) | (h5 & 0x0000FF00)
+ | (h4 & 0x000000FF);
+ h3 += t;
+ break;
+ case HAVAL_160_BIT:
+ t = (h7 & 0x3F) | (h6 & (0x7F << 25)) | (h5 & (0x3F << 19));
+ h0 += t >>> 19 | t << 13;
+ t = (h7 & (0x3F << 6)) | (h6 & 0x3F) | (h5 & (0x7F << 25));
+ h1 += t >>> 25 | t << 7;
+ t = (h7 & (0x7F << 12)) | (h6 & (0x3F << 6)) | (h5 & 0x3F);
+ h2 += t;
+ t = (h7 & (0x3F << 19)) | (h6 & (0x7F << 12)) | (h5 & (0x3F << 6));
+ h3 += (t >>> 6);
+ t = (h7 & (0x7F << 25)) | (h6 & (0x3F << 19)) | (h5 & (0x7F << 12));
+ h4 += (t >>> 12);
+ break;
+ case HAVAL_192_BIT:
+ t = (h7 & 0x1F) | (h6 & (0x3F << 26));
+ h0 += t >>> 26 | t << 6;
+ t = (h7 & (0x1F << 5)) | (h6 & 0x1F);
+ h1 += t;
+ t = (h7 & (0x3F << 10)) | (h6 & (0x1F << 5));
+ h2 += (t >>> 5);
+ t = (h7 & (0x1F << 16)) | (h6 & (0x3F << 10));
+ h3 += (t >>> 10);
+ t = (h7 & (0x1F << 21)) | (h6 & (0x1F << 16));
+ h4 += (t >>> 16);
+ t = (h7 & (0x3F << 26)) | (h6 & (0x1F << 21));
+ h5 += (t >>> 21);
+ break;
+ case HAVAL_224_BIT:
+ h0 += ((h7 >>> 27) & 0x1F);
+ h1 += ((h7 >>> 22) & 0x1F);
+ h2 += ((h7 >>> 18) & 0x0F);
+ h3 += ((h7 >>> 13) & 0x1F);
+ h4 += ((h7 >>> 9) & 0x0F);
+ h5 += ((h7 >>> 4) & 0x1F);
+ h6 += (h7 & 0x0F);
+ }
+ }
+
+ /**
+ * Permutations phi_{i,j}, i=3,4,5, j=1,...,i.
+ *
+ * rounds = 3: 6 5 4 3 2 1 0
+ * | | | | | | | (replaced by)
+ * phi_{3,1}: 1 0 3 5 6 2 4
+ * phi_{3,2}: 4 2 1 0 5 3 6
+ * phi_{3,3}: 6 1 2 3 4 5 0
+ *
+ * rounds = 4: 6 5 4 3 2 1 0
+ * | | | | | | | (replaced by)
+ * phi_{4,1}: 2 6 1 4 5 3 0
+ * phi_{4,2}: 3 5 2 0 1 6 4
+ * phi_{4,3}: 1 4 3 6 0 2 5
+ * phi_{4,4}: 6 4 0 5 2 1 3
+ *
+ * rounds = 5: 6 5 4 3 2 1 0
+ * | | | | | | | (replaced by)
+ * phi_{5,1}: 3 4 1 0 5 2 6
+ * phi_{5,2}: 6 2 1 0 3 4 5
+ * phi_{5,3}: 2 6 0 4 3 1 5
+ * phi_{5,4}: 1 5 3 2 0 4 6
+ * phi_{5,5}: 2 5 0 6 4 3 1
+ */
+ private int FF1(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w)
+ {
+ int t;
+ switch (rounds)
+ {
+ case 3:
+ t = f1(x1, x0, x3, x5, x6, x2, x4);
+ break;
+ case 4:
+ t = f1(x2, x6, x1, x4, x5, x3, x0);
+ break;
+ default:
+ t = f1(x3, x4, x1, x0, x5, x2, x6);
+ }
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w;
+ }
+
+ private int FF2(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w, int c)
+ {
+ int t;
+ switch (rounds)
+ {
+ case 3:
+ t = f2(x4, x2, x1, x0, x5, x3, x6);
+ break;
+ case 4:
+ t = f2(x3, x5, x2, x0, x1, x6, x4);
+ break;
+ default:
+ t = f2(x6, x2, x1, x0, x3, x4, x5);
+ }
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w + c;
+ }
+
+ private int FF3(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w, int c)
+ {
+ int t;
+ switch (rounds)
+ {
+ case 3:
+ t = f3(x6, x1, x2, x3, x4, x5, x0);
+ break;
+ case 4:
+ t = f3(x1, x4, x3, x6, x0, x2, x5);
+ break;
+ default:
+ t = f3(x2, x6, x0, x4, x3, x1, x5);
+ }
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w + c;
+ }
+
+ private int FF4(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w, int c)
+ {
+ int t;
+ switch (rounds)
+ {
+ case 4:
+ t = f4(x6, x4, x0, x5, x2, x1, x3);
+ break;
+ default:
+ t = f4(x1, x5, x3, x2, x0, x4, x6);
+ }
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w + c;
+ }
+
+ private int FF5(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w, int c)
+ {
+ int t = f5(x2, x5, x0, x6, x4, x3, x1);
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w + c;
+ }
+
+ private int f1(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x1 & (x0 ^ x4) ^ x2 & x5 ^ x3 & x6 ^ x0;
+ }
+
+ private int f2(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x2 & (x1 & ~x3 ^ x4 & x5 ^ x6 ^ x0) ^ x4 & (x1 ^ x5) ^ x3 & x5 ^ x0;
+ }
+
+ private int f3(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x3 & (x1 & x2 ^ x6 ^ x0) ^ x1 & x4 ^ x2 & x5 ^ x0;
+ }
+
+ private int f4(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x4 & (x5 & ~x2 ^ x3 & ~x6 ^ x1 ^ x6 ^ x0) ^ x3 & (x1 & x2 ^ x5 ^ x6)
+ ^ x2 & x6 ^ x0;
+ }
+
+ private int f5(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x0 & (x1 & x2 & x3 ^ ~x5) ^ x1 & x4 ^ x2 & x5 ^ x3 & x6;
+ }
+}
diff --git a/gnu/java/security/hash/IMessageDigest.java b/gnu/java/security/hash/IMessageDigest.java
new file mode 100644
index 000000000..b3d7f69ca
--- /dev/null
+++ b/gnu/java/security/hash/IMessageDigest.java
@@ -0,0 +1,135 @@
+/* IMessageDigest.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+/**
+ * <p>The basic visible methods of any hash algorithm.</p>
+ *
+ * <p>A hash (or message digest) algorithm produces its output by iterating a
+ * basic compression function on blocks of data.</p>
+ */
+public interface IMessageDigest extends Cloneable
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of this algorithm.</p>
+ *
+ * @return the canonical name of this instance.
+ */
+ String name();
+
+ /**
+ * <p>Returns the output length in bytes of this message digest algorithm.</p>
+ *
+ * @return the output length in bytes of this message digest algorithm.
+ */
+ int hashSize();
+
+ /**
+ * <p>Returns the algorithm's (inner) block size in bytes.</p>
+ *
+ * @return the algorithm's inner block size in bytes.
+ */
+ int blockSize();
+
+ /**
+ * <p>Continues a message digest operation using the input byte.</p>
+ *
+ * @param b the input byte to digest.
+ */
+ void update(byte b);
+
+ /**
+ * <p>Continues a message digest operation, by filling the buffer, processing
+ * data in the algorithm's HASH_SIZE-bit block(s), updating the context and
+ * count, and buffering the remaining bytes in buffer for the next
+ * operation.</p>
+ *
+ * @param in the input block.
+ */
+ void update(byte[] in);
+
+ /**
+ * <p>Continues a message digest operation, by filling the buffer, processing
+ * data in the algorithm's HASH_SIZE-bit block(s), updating the context and
+ * count, and buffering the remaining bytes in buffer for the next
+ * operation.</p>
+ *
+ * @param in the input block.
+ * @param offset start of meaningful bytes in input block.
+ * @param length number of bytes, in input block, to consider.
+ */
+ void update(byte[] in, int offset, int length);
+
+ /**
+ * <p>Completes the message digest by performing final operations such as
+ * padding and resetting the instance.</p>
+ *
+ * @return the array of bytes representing the hash value.
+ */
+ byte[] digest();
+
+ /**
+ * <p>Resets the current context of this instance clearing any eventually cached
+ * intermediary values.</p>
+ */
+ void reset();
+
+ /**
+ * <p>A basic test. Ensures that the digest of a pre-determined message is equal
+ * to a known pre-computed value.</p>
+ *
+ * @return <tt>true</tt> if the implementation passes a basic self-test.
+ * Returns <tt>false</tt> otherwise.
+ */
+ boolean selfTest();
+
+ /**
+ * <p>Returns a clone copy of this instance.</p>
+ *
+ * @return a clone copy of this instance.
+ */
+ Object clone();
+}
diff --git a/gnu/java/security/hash/MD2.java b/gnu/java/security/hash/MD2.java
new file mode 100644
index 000000000..41e876983
--- /dev/null
+++ b/gnu/java/security/hash/MD2.java
@@ -0,0 +1,301 @@
+/* MD2.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>An implementation of the MD2 message digest algorithm.</p>
+ *
+ * <p>MD2 is not widely used. Unless it is needed for compatibility with
+ * existing systems, it is not recommended for use in new applications.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>The <a href="http://www.ietf.org/rfc/rfc1319.txt">MD2</a>
+ * Message-Digest Algorithm.<br>
+ * B. Kaliski.</li>
+ * <li>The <a href="http://www.rfc-editor.org/errata.html">RFC ERRATA PAGE</a>
+ * under section RFC 1319.</li>
+ * </ol>
+ */
+public class MD2 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** An MD2 message digest is always 128-bits long, or 16 bytes. */
+ private static final int DIGEST_LENGTH = 16;
+
+ /** The MD2 algorithm operates on 128-bit blocks, or 16 bytes. */
+ private static final int BLOCK_LENGTH = 16;
+
+ /** 256 byte "random" permutation of the digits of pi. */
+ private static final byte[] PI = { 41, 46, 67, -55, -94, -40, 124, 1, 61, 54,
+ 84, -95, -20, -16, 6, 19, 98, -89, 5, -13,
+ -64, -57, 115, -116, -104, -109, 43, -39,
+ -68, 76, -126, -54, 30, -101, 87, 60, -3,
+ -44, -32, 22, 103, 66, 111, 24, -118, 23,
+ -27, 18, -66, 78, -60, -42, -38, -98, -34,
+ 73, -96, -5, -11, -114, -69, 47, -18, 122,
+ -87, 104, 121, -111, 21, -78, 7, 63, -108,
+ -62, 16, -119, 11, 34, 95, 33, -128, 127,
+ 93, -102, 90, -112, 50, 39, 53, 62, -52,
+ -25, -65, -9, -105, 3, -1, 25, 48, -77, 72,
+ -91, -75, -47, -41, 94, -110, 42, -84, 86,
+ -86, -58, 79, -72, 56, -46, -106, -92, 125,
+ -74, 118, -4, 107, -30, -100, 116, 4, -15,
+ 69, -99, 112, 89, 100, 113, -121, 32, -122,
+ 91, -49, 101, -26, 45, -88, 2, 27, 96, 37,
+ -83, -82, -80, -71, -10, 28, 70, 97, 105,
+ 52, 64, 126, 15, 85, 71, -93, 35, -35, 81,
+ -81, 58, -61, 92, -7, -50, -70, -59, -22,
+ 38, 44, 83, 13, 110, -123, 40, -124, 9,
+ -45, -33, -51, -12, 65, -127, 77, 82, 106,
+ -36, 55, -56, 108, -63, -85, -6, 36, -31,
+ 123, 8, 12, -67, -79, 74, 120, -120, -107,
+ -117, -29, 99, -24, 109, -23, -53, -43, -2,
+ 59, 0, 29, 57, -14, -17, -73, 14, 102, 88,
+ -48, -28, -90, 119, 114, -8, -21, 117, 75,
+ 10, 49, 68, 80, -76, -113, -19, 31, 26,
+ -37, -103, -115, 51, -97, 17, -125, 20 };
+
+ /** The output of this message digest when no data has been input. */
+ private static final String DIGEST0 = "8350E5A3E24C153DF2275C9F80692773";
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** The checksum computed so far. */
+ private byte[] checksum;
+
+ /**
+ * Work array needed by encrypt method. First <code>BLOCK_LENGTH</code> bytes
+ * are also used to store the running digest.
+ */
+ private byte[] work;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Creates a new MD2 digest ready for use. */
+ public MD2()
+ {
+ super(Registry.MD2_HASH, DIGEST_LENGTH, BLOCK_LENGTH);
+ }
+
+ /**
+ * <p>Private constructor used for cloning.</p>
+ *
+ * @param md2 the instance to clone.
+ */
+ private MD2(MD2 md2)
+ {
+ this();
+
+ // superclass field
+ this.count = md2.count;
+ this.buffer = (byte[]) md2.buffer.clone();
+
+ // private field
+ this.checksum = (byte[]) md2.checksum.clone();
+ this.work = (byte[]) md2.work.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new MD2(this);
+ }
+
+ // Implementation of abstract methods in BaseHash --------------------------
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[DIGEST_LENGTH];
+
+ // Encrypt checksum as last block.
+ encryptBlock(checksum, 0);
+
+ for (int i = 0; i < BLOCK_LENGTH; i++)
+ {
+ result[i] = work[i];
+ }
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ checksum = new byte[BLOCK_LENGTH];
+ work = new byte[BLOCK_LENGTH * 3];
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new MD2().digest())));
+ }
+ return valid.booleanValue();
+ }
+
+ /**
+ * <p>Generates an array of padding bytes. The padding is defined as
+ * <code>i</code> bytes of value <code>i</code>, where <code>i</code> is the
+ * number of bytes to fill the last block of the message to
+ * <code>BLOCK_LENGTH</code> bytes (or <code>BLOCK_LENGTH</code> bytes when
+ * the last block was completely full).</p>
+ *
+ * @return the bytes to pad the remaining bytes in the buffer before
+ * completing a hash operation.
+ */
+ protected byte[] padBuffer()
+ {
+ int length = BLOCK_LENGTH - (int) (count % BLOCK_LENGTH);
+ if (length == 0)
+ {
+ length = BLOCK_LENGTH;
+ }
+ byte[] pad = new byte[length];
+ for (int i = 0; i < length; i++)
+ {
+ pad[i] = (byte) length;
+ }
+ return pad;
+ }
+
+ /**
+ * <p>Adds <code>BLOCK_LENGTH</code> bytes to the running digest.</p>
+ *
+ * @param in the byte array to take the <code>BLOCK_LENGTH</code> bytes from.
+ * @param off the offset to start from in the given byte array.
+ */
+ protected void transform(byte[] in, int off)
+ {
+ // encryptBlock(in, off);
+ // updateCheckSum(in, off);
+ updateCheckSumAndEncryptBlock(in, off);
+ }
+
+ // Private instance methods ------------------------------------------------
+
+ /**
+ * Updates the checksum with the <code>BLOCK_LENGTH</code> bytes from the
+ * given array starting at <code>off</code>.
+ */
+ /*
+ private void updateCheckSum(byte[] in, int off) {
+ byte l = checksum[BLOCK_LENGTH-1];
+ for (int i = 0; i < BLOCK_LENGTH; i++) {
+ byte b = in[off+i];
+ // l = (byte)((checksum[i] & 0xFF) ^ (PI[((b & 0xFF) ^ (l & 0xFF))] & 0xFF));
+ l = (byte)(checksum[i] ^ PI[(b ^ l) & 0xFF]);
+ checksum[i] = l;
+ }
+ }
+ */
+ /**
+ * Adds a new block (<code>BLOCK_LENGTH</code> bytes) to the running digest
+ * from the given byte array starting from the given offset.
+ */
+ private void encryptBlock(byte[] in, int off)
+ {
+ for (int i = 0; i < BLOCK_LENGTH; i++)
+ {
+ byte b = in[off + i];
+ work[BLOCK_LENGTH + i] = b;
+ work[BLOCK_LENGTH * 2 + i] = (byte) (work[i] ^ b);
+ }
+
+ byte t = 0;
+ for (int i = 0; i < 18; i++)
+ {
+ for (int j = 0; j < 3 * BLOCK_LENGTH; j++)
+ {
+ // t = (byte)((work[j] & 0xFF) ^ (PI[t & 0xFF] & 0xFF));
+ t = (byte) (work[j] ^ PI[t & 0xFF]);
+ work[j] = t;
+ }
+ // t = (byte)((t + i) & 0xFF);
+ t = (byte) (t + i);
+ }
+ }
+
+ /**
+ * Optimized method that combines a checksum update and encrypt of a block.
+ */
+ private void updateCheckSumAndEncryptBlock(byte[] in, int off)
+ {
+ byte l = checksum[BLOCK_LENGTH - 1];
+ for (int i = 0; i < BLOCK_LENGTH; i++)
+ {
+ byte b = in[off + i];
+ work[BLOCK_LENGTH + i] = b;
+ // work[BLOCK_LENGTH*2+i] = (byte)((work[i] & 0xFF) ^ (b & 0xFF));
+ work[BLOCK_LENGTH * 2 + i] = (byte) (work[i] ^ b);
+ // l = (byte)((checksum[i] & 0xFF) ^ (PI[((b & 0xFF) ^ (l & 0xFF))] & 0xFF));
+ l = (byte) (checksum[i] ^ PI[(b ^ l) & 0xFF]);
+ checksum[i] = l;
+ }
+
+ byte t = 0;
+ for (int i = 0; i < 18; i++)
+ {
+ for (int j = 0; j < 3 * BLOCK_LENGTH; j++)
+ {
+ // t = (byte)((work[j] & 0xFF) ^ (PI[t & 0xFF] & 0xFF));
+ t = (byte) (work[j] ^ PI[t & 0xFF]);
+ work[j] = t;
+ }
+ // t = (byte)((t + i) & 0xFF);
+ t = (byte) (t + i);
+ }
+ }
+}
diff --git a/gnu/java/security/hash/MD4.java b/gnu/java/security/hash/MD4.java
new file mode 100644
index 000000000..54dda358b
--- /dev/null
+++ b/gnu/java/security/hash/MD4.java
@@ -0,0 +1,328 @@
+/* MD4.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>An implementation of Ron Rivest's MD4 message digest algorithm.</p>
+ *
+ * <p>MD4 was the precursor to the stronger {@link gnu.crypto.hash.MD5}
+ * algorithm, and while not considered cryptograpically secure itself, MD4 is
+ * in use in various applications. It is slightly faster than MD5.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>The <a href="http://www.ietf.org/rfc/rfc1320.txt">MD4</a>
+ * Message-Digest Algorithm.<br>
+ * R. Rivest.</li>
+ * </ol>
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public class MD4 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** An MD4 message digest is always 128-bits long, or 16 bytes. */
+ private static final int DIGEST_LENGTH = 16;
+
+ /** The MD4 algorithm operates on 512-bit blocks, or 64 bytes. */
+ private static final int BLOCK_LENGTH = 64;
+
+ private static final int A = 0x67452301;
+
+ private static final int B = 0xefcdab89;
+
+ private static final int C = 0x98badcfe;
+
+ private static final int D = 0x10325476;
+
+ /** The output of this message digest when no data has been input. */
+ private static final String DIGEST0 = "31D6CFE0D16AE931B73C59D7E0C089C0";
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ private int a, b, c, d;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Public constructor. Initializes the chaining variables, sets the byte
+ * count to <code>0</code>, and creates a new block of <code>512</code> bits.
+ * </p>
+ */
+ public MD4()
+ {
+ super(Registry.MD4_HASH, DIGEST_LENGTH, BLOCK_LENGTH);
+ }
+
+ /**
+ * <p>Trivial private constructor for cloning purposes.</p>
+ *
+ * @param that the instance to clone.
+ */
+ private MD4(MD4 that)
+ {
+ this();
+
+ this.a = that.a;
+ this.b = that.b;
+ this.c = that.c;
+ this.d = that.d;
+ this.count = that.count;
+ this.buffer = (byte[]) that.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new MD4(this);
+ }
+
+ // Implementation of abstract methods in BashHash --------------------------
+
+ protected byte[] getResult()
+ {
+ byte[] digest = { (byte) a, (byte) (a >>> 8), (byte) (a >>> 16),
+ (byte) (a >>> 24), (byte) b, (byte) (b >>> 8),
+ (byte) (b >>> 16), (byte) (b >>> 24), (byte) c,
+ (byte) (c >>> 8), (byte) (c >>> 16), (byte) (c >>> 24),
+ (byte) d, (byte) (d >>> 8), (byte) (d >>> 16),
+ (byte) (d >>> 24) };
+ return digest;
+ }
+
+ protected void resetContext()
+ {
+ a = A;
+ b = B;
+ c = C;
+ d = D;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new MD4().digest())));
+ }
+ return valid.booleanValue();
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_LENGTH);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] pad = new byte[padding + 8];
+
+ pad[0] = (byte) 0x80;
+ long bits = count << 3;
+ pad[padding++] = (byte) bits;
+ pad[padding++] = (byte) (bits >>> 8);
+ pad[padding++] = (byte) (bits >>> 16);
+ pad[padding++] = (byte) (bits >>> 24);
+ pad[padding++] = (byte) (bits >>> 32);
+ pad[padding++] = (byte) (bits >>> 40);
+ pad[padding++] = (byte) (bits >>> 48);
+ pad[padding] = (byte) (bits >>> 56);
+
+ return pad;
+ }
+
+ protected void transform(byte[] in, int i)
+ {
+ int X0 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X1 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X2 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X3 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X4 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X5 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X6 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X7 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X8 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X9 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X10 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X11 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X12 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X13 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X14 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X15 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i] << 24;
+
+ int aa, bb, cc, dd;
+
+ aa = a;
+ bb = b;
+ cc = c;
+ dd = d;
+
+ aa += ((bb & cc) | ((~bb) & dd)) + X0;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & bb) | ((~aa) & cc)) + X1;
+ dd = dd << 7 | dd >>> -7;
+ cc += ((dd & aa) | ((~dd) & bb)) + X2;
+ cc = cc << 11 | cc >>> -11;
+ bb += ((cc & dd) | ((~cc) & aa)) + X3;
+ bb = bb << 19 | bb >>> -19;
+ aa += ((bb & cc) | ((~bb) & dd)) + X4;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & bb) | ((~aa) & cc)) + X5;
+ dd = dd << 7 | dd >>> -7;
+ cc += ((dd & aa) | ((~dd) & bb)) + X6;
+ cc = cc << 11 | cc >>> -11;
+ bb += ((cc & dd) | ((~cc) & aa)) + X7;
+ bb = bb << 19 | bb >>> -19;
+ aa += ((bb & cc) | ((~bb) & dd)) + X8;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & bb) | ((~aa) & cc)) + X9;
+ dd = dd << 7 | dd >>> -7;
+ cc += ((dd & aa) | ((~dd) & bb)) + X10;
+ cc = cc << 11 | cc >>> -11;
+ bb += ((cc & dd) | ((~cc) & aa)) + X11;
+ bb = bb << 19 | bb >>> -19;
+ aa += ((bb & cc) | ((~bb) & dd)) + X12;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & bb) | ((~aa) & cc)) + X13;
+ dd = dd << 7 | dd >>> -7;
+ cc += ((dd & aa) | ((~dd) & bb)) + X14;
+ cc = cc << 11 | cc >>> -11;
+ bb += ((cc & dd) | ((~cc) & aa)) + X15;
+ bb = bb << 19 | bb >>> -19;
+
+ aa += ((bb & (cc | dd)) | (cc & dd)) + X0 + 0x5a827999;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & (bb | cc)) | (bb & cc)) + X4 + 0x5a827999;
+ dd = dd << 5 | dd >>> -5;
+ cc += ((dd & (aa | bb)) | (aa & bb)) + X8 + 0x5a827999;
+ cc = cc << 9 | cc >>> -9;
+ bb += ((cc & (dd | aa)) | (dd & aa)) + X12 + 0x5a827999;
+ bb = bb << 13 | bb >>> -13;
+ aa += ((bb & (cc | dd)) | (cc & dd)) + X1 + 0x5a827999;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & (bb | cc)) | (bb & cc)) + X5 + 0x5a827999;
+ dd = dd << 5 | dd >>> -5;
+ cc += ((dd & (aa | bb)) | (aa & bb)) + X9 + 0x5a827999;
+ cc = cc << 9 | cc >>> -9;
+ bb += ((cc & (dd | aa)) | (dd & aa)) + X13 + 0x5a827999;
+ bb = bb << 13 | bb >>> -13;
+ aa += ((bb & (cc | dd)) | (cc & dd)) + X2 + 0x5a827999;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & (bb | cc)) | (bb & cc)) + X6 + 0x5a827999;
+ dd = dd << 5 | dd >>> -5;
+ cc += ((dd & (aa | bb)) | (aa & bb)) + X10 + 0x5a827999;
+ cc = cc << 9 | cc >>> -9;
+ bb += ((cc & (dd | aa)) | (dd & aa)) + X14 + 0x5a827999;
+ bb = bb << 13 | bb >>> -13;
+ aa += ((bb & (cc | dd)) | (cc & dd)) + X3 + 0x5a827999;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & (bb | cc)) | (bb & cc)) + X7 + 0x5a827999;
+ dd = dd << 5 | dd >>> -5;
+ cc += ((dd & (aa | bb)) | (aa & bb)) + X11 + 0x5a827999;
+ cc = cc << 9 | cc >>> -9;
+ bb += ((cc & (dd | aa)) | (dd & aa)) + X15 + 0x5a827999;
+ bb = bb << 13 | bb >>> -13;
+
+ aa += (bb ^ cc ^ dd) + X0 + 0x6ed9eba1;
+ aa = aa << 3 | aa >>> -3;
+ dd += (aa ^ bb ^ cc) + X8 + 0x6ed9eba1;
+ dd = dd << 9 | dd >>> -9;
+ cc += (dd ^ aa ^ bb) + X4 + 0x6ed9eba1;
+ cc = cc << 11 | cc >>> -11;
+ bb += (cc ^ dd ^ aa) + X12 + 0x6ed9eba1;
+ bb = bb << 15 | bb >>> -15;
+ aa += (bb ^ cc ^ dd) + X2 + 0x6ed9eba1;
+ aa = aa << 3 | aa >>> -3;
+ dd += (aa ^ bb ^ cc) + X10 + 0x6ed9eba1;
+ dd = dd << 9 | dd >>> -9;
+ cc += (dd ^ aa ^ bb) + X6 + 0x6ed9eba1;
+ cc = cc << 11 | cc >>> -11;
+ bb += (cc ^ dd ^ aa) + X14 + 0x6ed9eba1;
+ bb = bb << 15 | bb >>> -15;
+ aa += (bb ^ cc ^ dd) + X1 + 0x6ed9eba1;
+ aa = aa << 3 | aa >>> -3;
+ dd += (aa ^ bb ^ cc) + X9 + 0x6ed9eba1;
+ dd = dd << 9 | dd >>> -9;
+ cc += (dd ^ aa ^ bb) + X5 + 0x6ed9eba1;
+ cc = cc << 11 | cc >>> -11;
+ bb += (cc ^ dd ^ aa) + X13 + 0x6ed9eba1;
+ bb = bb << 15 | bb >>> -15;
+ aa += (bb ^ cc ^ dd) + X3 + 0x6ed9eba1;
+ aa = aa << 3 | aa >>> -3;
+ dd += (aa ^ bb ^ cc) + X11 + 0x6ed9eba1;
+ dd = dd << 9 | dd >>> -9;
+ cc += (dd ^ aa ^ bb) + X7 + 0x6ed9eba1;
+ cc = cc << 11 | cc >>> -11;
+ bb += (cc ^ dd ^ aa) + X15 + 0x6ed9eba1;
+ bb = bb << 15 | bb >>> -15;
+
+ a += aa;
+ b += bb;
+ c += cc;
+ d += dd;
+ }
+}
diff --git a/gnu/java/security/hash/MD5.java b/gnu/java/security/hash/MD5.java
new file mode 100644
index 000000000..463292984
--- /dev/null
+++ b/gnu/java/security/hash/MD5.java
@@ -0,0 +1,365 @@
+/* MD5.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>The MD5 message-digest algorithm takes as input a message of arbitrary
+ * length and produces as output a 128-bit "fingerprint" or "message digest" of
+ * the input. It is conjectured that it is computationally infeasible to
+ * produce two messages having the same message digest, or to produce any
+ * message having a given prespecified target message digest.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>The <a href="http://www.ietf.org/rfc/rfc1321.txt">MD5</a> Message-
+ * Digest Algorithm.<br>
+ * R. Rivest.</li>
+ * </ol>
+ */
+public class MD5 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "D41D8CD98F00B204E9800998ECF8427E";
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 128-bit interim result. */
+ private int h0, h1, h2, h3;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public MD5()
+ {
+ super(Registry.MD5_HASH, 16, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private MD5(MD5 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new MD5(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected synchronized void transform(byte[] in, int i)
+ {
+ int X0 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X1 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X2 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X3 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X4 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X5 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X6 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X7 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X8 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X9 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X10 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X11 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X12 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X13 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X14 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X15 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i] << 24;
+
+ int A = h0;
+ int B = h1;
+ int C = h2;
+ int D = h3;
+
+ // hex constants are from md5.c in FSF Gnu Privacy Guard 0.9.2
+ // round 1
+ A += ((B & C) | (~B & D)) + X0 + 0xD76AA478;
+ A = B + (A << 7 | A >>> -7);
+ D += ((A & B) | (~A & C)) + X1 + 0xE8C7B756;
+ D = A + (D << 12 | D >>> -12);
+ C += ((D & A) | (~D & B)) + X2 + 0x242070DB;
+ C = D + (C << 17 | C >>> -17);
+ B += ((C & D) | (~C & A)) + X3 + 0xC1BDCEEE;
+ B = C + (B << 22 | B >>> -22);
+
+ A += ((B & C) | (~B & D)) + X4 + 0xF57C0FAF;
+ A = B + (A << 7 | A >>> -7);
+ D += ((A & B) | (~A & C)) + X5 + 0x4787C62A;
+ D = A + (D << 12 | D >>> -12);
+ C += ((D & A) | (~D & B)) + X6 + 0xA8304613;
+ C = D + (C << 17 | C >>> -17);
+ B += ((C & D) | (~C & A)) + X7 + 0xFD469501;
+ B = C + (B << 22 | B >>> -22);
+
+ A += ((B & C) | (~B & D)) + X8 + 0x698098D8;
+ A = B + (A << 7 | A >>> -7);
+ D += ((A & B) | (~A & C)) + X9 + 0x8B44F7AF;
+ D = A + (D << 12 | D >>> -12);
+ C += ((D & A) | (~D & B)) + X10 + 0xFFFF5BB1;
+ C = D + (C << 17 | C >>> -17);
+ B += ((C & D) | (~C & A)) + X11 + 0x895CD7BE;
+ B = C + (B << 22 | B >>> -22);
+
+ A += ((B & C) | (~B & D)) + X12 + 0x6B901122;
+ A = B + (A << 7 | A >>> -7);
+ D += ((A & B) | (~A & C)) + X13 + 0xFD987193;
+ D = A + (D << 12 | D >>> -12);
+ C += ((D & A) | (~D & B)) + X14 + 0xA679438E;
+ C = D + (C << 17 | C >>> -17);
+ B += ((C & D) | (~C & A)) + X15 + 0x49B40821;
+ B = C + (B << 22 | B >>> -22);
+
+ // round 2
+ A += ((B & D) | (C & ~D)) + X1 + 0xF61E2562;
+ A = B + (A << 5 | A >>> -5);
+ D += ((A & C) | (B & ~C)) + X6 + 0xC040B340;
+ D = A + (D << 9 | D >>> -9);
+ C += ((D & B) | (A & ~B)) + X11 + 0x265E5A51;
+ C = D + (C << 14 | C >>> -14);
+ B += ((C & A) | (D & ~A)) + X0 + 0xE9B6C7AA;
+ B = C + (B << 20 | B >>> -20);
+
+ A += ((B & D) | (C & ~D)) + X5 + 0xD62F105D;
+ A = B + (A << 5 | A >>> -5);
+ D += ((A & C) | (B & ~C)) + X10 + 0x02441453;
+ D = A + (D << 9 | D >>> -9);
+ C += ((D & B) | (A & ~B)) + X15 + 0xD8A1E681;
+ C = D + (C << 14 | C >>> -14);
+ B += ((C & A) | (D & ~A)) + X4 + 0xE7D3FBC8;
+ B = C + (B << 20 | B >>> -20);
+
+ A += ((B & D) | (C & ~D)) + X9 + 0x21E1CDE6;
+ A = B + (A << 5 | A >>> -5);
+ D += ((A & C) | (B & ~C)) + X14 + 0xC33707D6;
+ D = A + (D << 9 | D >>> -9);
+ C += ((D & B) | (A & ~B)) + X3 + 0xF4D50D87;
+ C = D + (C << 14 | C >>> -14);
+ B += ((C & A) | (D & ~A)) + X8 + 0x455A14ED;
+ B = C + (B << 20 | B >>> -20);
+
+ A += ((B & D) | (C & ~D)) + X13 + 0xA9E3E905;
+ A = B + (A << 5 | A >>> -5);
+ D += ((A & C) | (B & ~C)) + X2 + 0xFCEFA3F8;
+ D = A + (D << 9 | D >>> -9);
+ C += ((D & B) | (A & ~B)) + X7 + 0x676F02D9;
+ C = D + (C << 14 | C >>> -14);
+ B += ((C & A) | (D & ~A)) + X12 + 0x8D2A4C8A;
+ B = C + (B << 20 | B >>> -20);
+
+ // round 3
+ A += (B ^ C ^ D) + X5 + 0xFFFA3942;
+ A = B + (A << 4 | A >>> -4);
+ D += (A ^ B ^ C) + X8 + 0x8771F681;
+ D = A + (D << 11 | D >>> -11);
+ C += (D ^ A ^ B) + X11 + 0x6D9D6122;
+ C = D + (C << 16 | C >>> -16);
+ B += (C ^ D ^ A) + X14 + 0xFDE5380C;
+ B = C + (B << 23 | B >>> -23);
+
+ A += (B ^ C ^ D) + X1 + 0xA4BEEA44;
+ A = B + (A << 4 | A >>> -4);
+ D += (A ^ B ^ C) + X4 + 0x4BDECFA9;
+ D = A + (D << 11 | D >>> -11);
+ C += (D ^ A ^ B) + X7 + 0xF6BB4B60;
+ C = D + (C << 16 | C >>> -16);
+ B += (C ^ D ^ A) + X10 + 0xBEBFBC70;
+ B = C + (B << 23 | B >>> -23);
+
+ A += (B ^ C ^ D) + X13 + 0x289B7EC6;
+ A = B + (A << 4 | A >>> -4);
+ D += (A ^ B ^ C) + X0 + 0xEAA127FA;
+ D = A + (D << 11 | D >>> -11);
+ C += (D ^ A ^ B) + X3 + 0xD4EF3085;
+ C = D + (C << 16 | C >>> -16);
+ B += (C ^ D ^ A) + X6 + 0x04881D05;
+ B = C + (B << 23 | B >>> -23);
+
+ A += (B ^ C ^ D) + X9 + 0xD9D4D039;
+ A = B + (A << 4 | A >>> -4);
+ D += (A ^ B ^ C) + X12 + 0xE6DB99E5;
+ D = A + (D << 11 | D >>> -11);
+ C += (D ^ A ^ B) + X15 + 0x1FA27CF8;
+ C = D + (C << 16 | C >>> -16);
+ B += (C ^ D ^ A) + X2 + 0xC4AC5665;
+ B = C + (B << 23 | B >>> -23);
+
+ // round 4
+ A += (C ^ (B | ~D)) + X0 + 0xF4292244;
+ A = B + (A << 6 | A >>> -6);
+ D += (B ^ (A | ~C)) + X7 + 0x432AFF97;
+ D = A + (D << 10 | D >>> -10);
+ C += (A ^ (D | ~B)) + X14 + 0xAB9423A7;
+ C = D + (C << 15 | C >>> -15);
+ B += (D ^ (C | ~A)) + X5 + 0xFC93A039;
+ B = C + (B << 21 | B >>> -21);
+
+ A += (C ^ (B | ~D)) + X12 + 0x655B59C3;
+ A = B + (A << 6 | A >>> -6);
+ D += (B ^ (A | ~C)) + X3 + 0x8F0CCC92;
+ D = A + (D << 10 | D >>> -10);
+ C += (A ^ (D | ~B)) + X10 + 0xFFEFF47D;
+ C = D + (C << 15 | C >>> -15);
+ B += (D ^ (C | ~A)) + X1 + 0x85845dd1;
+ B = C + (B << 21 | B >>> -21);
+
+ A += (C ^ (B | ~D)) + X8 + 0x6FA87E4F;
+ A = B + (A << 6 | A >>> -6);
+ D += (B ^ (A | ~C)) + X15 + 0xFE2CE6E0;
+ D = A + (D << 10 | D >>> -10);
+ C += (A ^ (D | ~B)) + X6 + 0xA3014314;
+ C = D + (C << 15 | C >>> -15);
+ B += (D ^ (C | ~A)) + X13 + 0x4E0811A1;
+ B = C + (B << 21 | B >>> -21);
+
+ A += (C ^ (B | ~D)) + X4 + 0xF7537E82;
+ A = B + (A << 6 | A >>> -6);
+ D += (B ^ (A | ~C)) + X11 + 0xBD3AF235;
+ D = A + (D << 10 | D >>> -10);
+ C += (A ^ (D | ~B)) + X2 + 0x2AD7D2BB;
+ C = D + (C << 15 | C >>> -15);
+ B += (D ^ (C | ~A)) + X9 + 0xEB86D391;
+ B = C + (B << 21 | B >>> -21);
+
+ h0 += A;
+ h1 += B;
+ h2 += C;
+ h3 += D;
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) bits;
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding] = (byte) (bits >>> 56);
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[] { (byte) h0, (byte) (h0 >>> 8),
+ (byte) (h0 >>> 16), (byte) (h0 >>> 24),
+ (byte) h1, (byte) (h1 >>> 8),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 24),
+ (byte) h2, (byte) (h2 >>> 8),
+ (byte) (h2 >>> 16), (byte) (h2 >>> 24),
+ (byte) h3, (byte) (h3 >>> 8),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 24) };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ // magic MD5/RIPEMD128 initialisation constants
+ h0 = 0x67452301;
+ h1 = 0xEFCDAB89;
+ h2 = 0x98BADCFE;
+ h3 = 0x10325476;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new MD5().digest())));
+ }
+ return valid.booleanValue();
+ }
+}
diff --git a/gnu/java/security/hash/RipeMD128.java b/gnu/java/security/hash/RipeMD128.java
new file mode 100644
index 000000000..83e8f2504
--- /dev/null
+++ b/gnu/java/security/hash/RipeMD128.java
@@ -0,0 +1,291 @@
+/* RipeMD128.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>RIPEMD-128 is a 128-bit message digest.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html">
+ * RIPEMD160</a>: A Strengthened Version of RIPEMD.<br>
+ * Hans Dobbertin, Antoon Bosselaers and Bart Preneel.</li>
+ * </ol>
+ */
+public class RipeMD128 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "CDF26213A150DC3ECB610F18F6B38B46";
+
+ /** Constants for the transform method. */
+ // selection of message word
+ private static final int[] R = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0,
+ 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8,
+ 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10,
+ 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 };
+
+ private static final int[] Rp = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1,
+ 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14,
+ 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14,
+ 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4,
+ 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 };
+
+ // amount for rotate left (rol)
+ private static final int[] S = { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15,
+ 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12,
+ 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9,
+ 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12,
+ 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5,
+ 12 };
+
+ private static final int[] Sp = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11,
+ 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11,
+ 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8,
+ 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15,
+ 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5,
+ 15, 8 };
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 128-bit h0, h1, h2, h3 (interim result) */
+ private int h0, h1, h2, h3;
+
+ /** 512 bits work buffer = 16 x 32-bit words */
+ private int[] X = new int[16];
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public RipeMD128()
+ {
+ super(Registry.RIPEMD128_HASH, 16, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private RipeMD128(RipeMD128 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new RipeMD128(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ int A, B, C, D, Ap, Bp, Cp, Dp, T, s, i;
+
+ // encode 64 bytes from input block into an array of 16 unsigned
+ // integers.
+ for (i = 0; i < 16; i++)
+ {
+ X[i] = (in[offset++] & 0xFF) | (in[offset++] & 0xFF) << 8
+ | (in[offset++] & 0xFF) << 16 | in[offset++] << 24;
+ }
+
+ A = Ap = h0;
+ B = Bp = h1;
+ C = Cp = h2;
+ D = Dp = h3;
+
+ for (i = 0; i < 16; i++)
+ { // rounds 0...15
+ s = S[i];
+ T = A + (B ^ C ^ D) + X[i];
+ A = D;
+ D = C;
+ C = B;
+ B = T << s | T >>> (32 - s);
+
+ s = Sp[i];
+ T = Ap + ((Bp & Dp) | (Cp & ~Dp)) + X[Rp[i]] + 0x50A28BE6;
+ Ap = Dp;
+ Dp = Cp;
+ Cp = Bp;
+ Bp = T << s | T >>> (32 - s);
+ }
+
+ for (; i < 32; i++)
+ { // rounds 16...31
+ s = S[i];
+ T = A + ((B & C) | (~B & D)) + X[R[i]] + 0x5A827999;
+ A = D;
+ D = C;
+ C = B;
+ B = T << s | T >>> (32 - s);
+
+ s = Sp[i];
+ T = Ap + ((Bp | ~Cp) ^ Dp) + X[Rp[i]] + 0x5C4DD124;
+ Ap = Dp;
+ Dp = Cp;
+ Cp = Bp;
+ Bp = T << s | T >>> (32 - s);
+ }
+
+ for (; i < 48; i++)
+ { // rounds 32...47
+ s = S[i];
+ T = A + ((B | ~C) ^ D) + X[R[i]] + 0x6ED9EBA1;
+ A = D;
+ D = C;
+ C = B;
+ B = T << s | T >>> (32 - s);
+
+ s = Sp[i];
+ T = Ap + ((Bp & Cp) | (~Bp & Dp)) + X[Rp[i]] + 0x6D703EF3;
+ Ap = Dp;
+ Dp = Cp;
+ Cp = Bp;
+ Bp = T << s | T >>> (32 - s);
+ }
+
+ for (; i < 64; i++)
+ { // rounds 48...63
+ s = S[i];
+ T = A + ((B & D) | (C & ~D)) + X[R[i]] + 0x8F1BBCDC;
+ A = D;
+ D = C;
+ C = B;
+ B = T << s | T >>> (32 - s);
+
+ s = Sp[i];
+ T = Ap + (Bp ^ Cp ^ Dp) + X[Rp[i]];
+ Ap = Dp;
+ Dp = Cp;
+ Cp = Bp;
+ Bp = T << s | T >>> (32 - s);
+ }
+
+ T = h1 + C + Dp;
+ h1 = h2 + D + Ap;
+ h2 = h3 + A + Bp;
+ h3 = h0 + B + Cp;
+ h0 = T;
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) bits;
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding] = (byte) (bits >>> 56);
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[] { (byte) h0, (byte) (h0 >>> 8),
+ (byte) (h0 >>> 16), (byte) (h0 >>> 24),
+ (byte) h1, (byte) (h1 >>> 8),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 24),
+ (byte) h2, (byte) (h2 >>> 8),
+ (byte) (h2 >>> 16), (byte) (h2 >>> 24),
+ (byte) h3, (byte) (h3 >>> 8),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 24) };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ // magic RIPEMD128 initialisation constants
+ h0 = 0x67452301;
+ h1 = 0xEFCDAB89;
+ h2 = 0x98BADCFE;
+ h3 = 0x10325476;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean
+ (DIGEST0.equals(Util.toString(new RipeMD128().digest())));
+ }
+ return valid.booleanValue();
+ }
+}
diff --git a/gnu/java/security/hash/RipeMD160.java b/gnu/java/security/hash/RipeMD160.java
new file mode 100644
index 000000000..73ecc5161
--- /dev/null
+++ b/gnu/java/security/hash/RipeMD160.java
@@ -0,0 +1,328 @@
+/* RipeMD160.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>RIPEMD-160 is a 160-bit message digest.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html">
+ * RIPEMD160</a>: A Strengthened Version of RIPEMD.<br>
+ * Hans Dobbertin, Antoon Bosselaers and Bart Preneel.</li>
+ * </ol>
+ */
+public class RipeMD160 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "9C1185A5C5E9FC54612808977EE8F548B2258D31";
+
+ // selection of message word
+ private static final int[] R = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0,
+ 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8,
+ 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10,
+ 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0,
+ 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15,
+ 13 };
+
+ private static final int[] Rp = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1,
+ 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14,
+ 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14,
+ 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4,
+ 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
+ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0,
+ 3, 9, 11 };
+
+ // amount for rotate left (rol)
+ private static final int[] S = { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15,
+ 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12,
+ 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9,
+ 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12,
+ 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5,
+ 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13,
+ 14, 11, 8, 5, 6 };
+
+ private static final int[] Sp = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11,
+ 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11,
+ 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8,
+ 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15,
+ 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5,
+ 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6,
+ 5, 15, 13, 11, 11 };
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 160-bit h0, h1, h2, h3, h4 (interim result) */
+ private int h0, h1, h2, h3, h4;
+
+ /** 512 bits work buffer = 16 x 32-bit words */
+ private int[] X = new int[16];
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public RipeMD160()
+ {
+ super(Registry.RIPEMD160_HASH, 20, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private RipeMD160(RipeMD160 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return (new RipeMD160(this));
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ int A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, T, s, i;
+
+ // encode 64 bytes from input block into an array of 16 unsigned integers
+ for (i = 0; i < 16; i++)
+ {
+ X[i] = (in[offset++] & 0xFF) | (in[offset++] & 0xFF) << 8
+ | (in[offset++] & 0xFF) << 16 | in[offset++] << 24;
+ }
+
+ A = Ap = h0;
+ B = Bp = h1;
+ C = Cp = h2;
+ D = Dp = h3;
+ E = Ep = h4;
+
+ for (i = 0; i < 16; i++)
+ { // rounds 0...15
+ s = S[i];
+ T = A + (B ^ C ^ D) + X[i];
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + (Bp ^ (Cp | ~Dp)) + X[Rp[i]] + 0x50A28BE6;
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ for (; i < 32; i++)
+ { // rounds 16...31
+ s = S[i];
+ T = A + ((B & C) | (~B & D)) + X[R[i]] + 0x5A827999;
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + ((Bp & Dp) | (Cp & ~Dp)) + X[Rp[i]] + 0x5C4DD124;
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ for (; i < 48; i++)
+ { // rounds 32...47
+ s = S[i];
+ T = A + ((B | ~C) ^ D) + X[R[i]] + 0x6ED9EBA1;
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + ((Bp | ~Cp) ^ Dp) + X[Rp[i]] + 0x6D703EF3;
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ for (; i < 64; i++)
+ { // rounds 48...63
+ s = S[i];
+ T = A + ((B & D) | (C & ~D)) + X[R[i]] + 0x8F1BBCDC;
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + ((Bp & Cp) | (~Bp & Dp)) + X[Rp[i]] + 0x7A6D76E9;
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ for (; i < 80; i++)
+ { // rounds 64...79
+ s = S[i];
+ T = A + (B ^ (C | ~D)) + X[R[i]] + 0xA953FD4E;
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + (Bp ^ Cp ^ Dp) + X[Rp[i]];
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ T = h1 + C + Dp;
+ h1 = h2 + D + Ep;
+ h2 = h3 + E + Ap;
+ h3 = h4 + A + Bp;
+ h4 = h0 + B + Cp;
+ h0 = T;
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) bits;
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding] = (byte) (bits >>> 56);
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[] { (byte) h0, (byte) (h0 >>> 8),
+ (byte) (h0 >>> 16), (byte) (h0 >>> 24),
+ (byte) h1, (byte) (h1 >>> 8),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 24),
+ (byte) h2, (byte) (h2 >>> 8),
+ (byte) (h2 >>> 16), (byte) (h2 >>> 24),
+ (byte) h3, (byte) (h3 >>> 8),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 24),
+ (byte) h4, (byte) (h4 >>> 8),
+ (byte) (h4 >>> 16), (byte) (h4 >>> 24) };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ // magic RIPEMD160 initialisation constants
+ h0 = 0x67452301;
+ h1 = 0xEFCDAB89;
+ h2 = 0x98BADCFE;
+ h3 = 0x10325476;
+ h4 = 0xC3D2E1F0;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean
+ (DIGEST0.equals(Util.toString(new RipeMD160().digest())));
+ }
+ return valid.booleanValue();
+ }
+}
diff --git a/gnu/java/security/hash/Sha160.java b/gnu/java/security/hash/Sha160.java
new file mode 100644
index 000000000..bf5f45652
--- /dev/null
+++ b/gnu/java/security/hash/Sha160.java
@@ -0,0 +1,308 @@
+/* Sha160.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>The Secure Hash Algorithm (SHA-1) is required for use with the Digital
+ * Signature Algorithm (DSA) as specified in the Digital Signature Standard
+ * (DSS) and whenever a secure hash algorithm is required for federal
+ * applications. For a message of length less than 2^64 bits, the SHA-1
+ * produces a 160-bit condensed representation of the message called a message
+ * digest. The message digest is used during generation of a signature for the
+ * message. The SHA-1 is also used to compute a message digest for the received
+ * version of the message during the process of verifying the signature. Any
+ * change to the message in transit will, with very high probability, result in
+ * a different message digest, and the signature will fail to verify.</p>
+ *
+ * <p>The SHA-1 is designed to have the following properties: it is
+ * computationally infeasible to find a message which corresponds to a given
+ * message digest, or to find two different messages which produce the same
+ * message digest.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.itl.nist.gov/fipspubs/fip180-1.htm">SECURE HASH
+ * STANDARD</a><br>
+ * Federal Information, Processing Standards Publication 180-1, 1995 April 17.
+ * </li>
+ * </ol>
+ */
+public class Sha160 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "A9993E364706816ABA3E25717850C26C9CD0D89D";
+
+ private static final int[] w = new int[80];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 160-bit interim result. */
+ private int h0, h1, h2, h3, h4;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Sha160()
+ {
+ super(Registry.SHA160_HASH, 20, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Sha160(Sha160 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final int[] G(int hh0, int hh1, int hh2, int hh3, int hh4,
+ byte[] in, int offset)
+ {
+ // int[] w = new int[80];
+ // int i, T;
+ // for (i = 0; i < 16; i++) {
+ // w[i] = in[offset++] << 24 |
+ // (in[offset++] & 0xFF) << 16 |
+ // (in[offset++] & 0xFF) << 8 |
+ // (in[offset++] & 0xFF);
+ // }
+ // for (i = 16; i < 80; i++) {
+ // T = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
+ // w[i] = T << 1 | T >>> 31;
+ // }
+
+ // return sha(hh0, hh1, hh2, hh3, hh4, in, offset, w);
+ return sha(hh0, hh1, hh2, hh3, hh4, in, offset);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Sha160(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ // int i, T;
+ // for (i = 0; i < 16; i++) {
+ // W[i] = in[offset++] << 24 |
+ // (in[offset++] & 0xFF) << 16 |
+ // (in[offset++] & 0xFF) << 8 |
+ // (in[offset++] & 0xFF);
+ // }
+ // for (i = 16; i < 80; i++) {
+ // T = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+ // W[i] = T << 1 | T >>> 31;
+ // }
+
+ // int[] result = sha(h0, h1, h2, h3, h4, in, offset, W);
+ int[] result = sha(h0, h1, h2, h3, h4, in, offset);
+
+ h0 = result[0];
+ h1 = result[1];
+ h2 = result[2];
+ h3 = result[3];
+ h4 = result[4];
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) (bits >>> 56);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[] { (byte) (h0 >>> 24), (byte) (h0 >>> 16),
+ (byte) (h0 >>> 8), (byte) h0,
+ (byte) (h1 >>> 24), (byte) (h1 >>> 16),
+ (byte) (h1 >>> 8), (byte) h1,
+ (byte) (h2 >>> 24), (byte) (h2 >>> 16),
+ (byte) (h2 >>> 8), (byte) h2,
+ (byte) (h3 >>> 24), (byte) (h3 >>> 16),
+ (byte) (h3 >>> 8), (byte) h3,
+ (byte) (h4 >>> 24), (byte) (h4 >>> 16),
+ (byte) (h4 >>> 8), (byte) h4 };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ // magic SHA-1/RIPEMD160 initialisation constants
+ h0 = 0x67452301;
+ h1 = 0xEFCDAB89;
+ h2 = 0x98BADCFE;
+ h3 = 0x10325476;
+ h4 = 0xC3D2E1F0;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ Sha160 md = new Sha160();
+ md.update((byte) 0x61); // a
+ md.update((byte) 0x62); // b
+ md.update((byte) 0x63); // c
+ String result = Util.toString(md.digest());
+ valid = new Boolean(DIGEST0.equals(result));
+ }
+ return valid.booleanValue();
+ }
+
+ // SHA specific methods ----------------------------------------------------
+
+ private static final synchronized int[]
+ // sha(int hh0, int hh1, int hh2, int hh3, int hh4, byte[] in, int offset, int[] w) {
+ sha(int hh0, int hh1, int hh2, int hh3, int hh4, byte[] in, int offset)
+ {
+ int A = hh0;
+ int B = hh1;
+ int C = hh2;
+ int D = hh3;
+ int E = hh4;
+ int r, T;
+
+ for (r = 0; r < 16; r++)
+ {
+ w[r] = in[offset++] << 24 | (in[offset++] & 0xFF) << 16
+ | (in[offset++] & 0xFF) << 8 | (in[offset++] & 0xFF);
+ }
+ for (r = 16; r < 80; r++)
+ {
+ T = w[r - 3] ^ w[r - 8] ^ w[r - 14] ^ w[r - 16];
+ w[r] = T << 1 | T >>> 31;
+ }
+
+ // rounds 0-19
+ for (r = 0; r < 20; r++)
+ {
+ T = (A << 5 | A >>> 27) + ((B & C) | (~B & D)) + E + w[r] + 0x5A827999;
+ E = D;
+ D = C;
+ C = B << 30 | B >>> 2;
+ B = A;
+ A = T;
+ }
+
+ // rounds 20-39
+ for (r = 20; r < 40; r++)
+ {
+ T = (A << 5 | A >>> 27) + (B ^ C ^ D) + E + w[r] + 0x6ED9EBA1;
+ E = D;
+ D = C;
+ C = B << 30 | B >>> 2;
+ B = A;
+ A = T;
+ }
+
+ // rounds 40-59
+ for (r = 40; r < 60; r++)
+ {
+ T = (A << 5 | A >>> 27) + (B & C | B & D | C & D) + E + w[r]
+ + 0x8F1BBCDC;
+ E = D;
+ D = C;
+ C = B << 30 | B >>> 2;
+ B = A;
+ A = T;
+ }
+
+ // rounds 60-79
+ for (r = 60; r < 80; r++)
+ {
+ T = (A << 5 | A >>> 27) + (B ^ C ^ D) + E + w[r] + 0xCA62C1D6;
+ E = D;
+ D = C;
+ C = B << 30 | B >>> 2;
+ B = A;
+ A = T;
+ }
+
+ return new int[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E };
+ }
+}
diff --git a/gnu/java/security/hash/Sha256.java b/gnu/java/security/hash/Sha256.java
new file mode 100644
index 000000000..9ef70a1a6
--- /dev/null
+++ b/gnu/java/security/hash/Sha256.java
@@ -0,0 +1,278 @@
+/* Sha256.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>Implementation of SHA2-1 [SHA-256] per the IETF Draft Specification.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://ftp.ipv4.heanet.ie/pub/ietf/internet-drafts/draft-ietf-ipsec-ciph-aes-cbc-03.txt">
+ * Descriptions of SHA-256, SHA-384, and SHA-512</a>,</li>
+ * <li>http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf</li>
+ * </ol>
+ */
+public class Sha256 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+ private static final int[] k = { 0x428a2f98, 0x71374491, 0xb5c0fbcf,
+ 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98,
+ 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
+ 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
+ 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8,
+ 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85,
+ 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e,
+ 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819,
+ 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c,
+ 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee,
+ 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
+ 0xc67178f2 };
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD";
+
+ private static final int[] w = new int[64];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 256-bit interim result. */
+ private int h0, h1, h2, h3, h4, h5, h6, h7;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Sha256()
+ {
+ super(Registry.SHA256_HASH, 32, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Sha256(Sha256 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.h5 = md.h5;
+ this.h6 = md.h6;
+ this.h7 = md.h7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final int[] G(int hh0, int hh1, int hh2, int hh3, int hh4,
+ int hh5, int hh6, int hh7, byte[] in, int offset)
+ {
+ return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Sha256(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ int[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
+
+ h0 = result[0];
+ h1 = result[1];
+ h2 = result[2];
+ h3 = result[3];
+ h4 = result[4];
+ h5 = result[5];
+ h6 = result[6];
+ h7 = result[7];
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) (bits >>> 56);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ return new byte[] { (byte) (h0 >>> 24), (byte) (h0 >>> 16),
+ (byte) (h0 >>> 8), (byte) h0, (byte) (h1 >>> 24),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 8), (byte) h1,
+ (byte) (h2 >>> 24), (byte) (h2 >>> 16),
+ (byte) (h2 >>> 8), (byte) h2, (byte) (h3 >>> 24),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 8), (byte) h3,
+ (byte) (h4 >>> 24), (byte) (h4 >>> 16),
+ (byte) (h4 >>> 8), (byte) h4, (byte) (h5 >>> 24),
+ (byte) (h5 >>> 16), (byte) (h5 >>> 8), (byte) h5,
+ (byte) (h6 >>> 24), (byte) (h6 >>> 16),
+ (byte) (h6 >>> 8), (byte) h6, (byte) (h7 >>> 24),
+ (byte) (h7 >>> 16), (byte) (h7 >>> 8), (byte) h7 };
+ }
+
+ protected void resetContext()
+ {
+ // magic SHA-256 initialisation constants
+ h0 = 0x6a09e667;
+ h1 = 0xbb67ae85;
+ h2 = 0x3c6ef372;
+ h3 = 0xa54ff53a;
+ h4 = 0x510e527f;
+ h5 = 0x9b05688c;
+ h6 = 0x1f83d9ab;
+ h7 = 0x5be0cd19;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ Sha256 md = new Sha256();
+ md.update((byte) 0x61); // a
+ md.update((byte) 0x62); // b
+ md.update((byte) 0x63); // c
+ String result = Util.toString(md.digest());
+ valid = new Boolean(DIGEST0.equals(result));
+ }
+
+ return valid.booleanValue();
+ }
+
+ // SHA specific methods ----------------------------------------------------
+
+ private static final synchronized int[] sha(int hh0, int hh1, int hh2,
+ int hh3, int hh4, int hh5,
+ int hh6, int hh7, byte[] in,
+ int offset)
+ {
+ int A = hh0;
+ int B = hh1;
+ int C = hh2;
+ int D = hh3;
+ int E = hh4;
+ int F = hh5;
+ int G = hh6;
+ int H = hh7;
+ int r, T, T2;
+
+ for (r = 0; r < 16; r++)
+ {
+ w[r] = (in[offset++] << 24 | (in[offset++] & 0xFF) << 16
+ | (in[offset++] & 0xFF) << 8 | (in[offset++] & 0xFF));
+ }
+ for (r = 16; r < 64; r++)
+ {
+ T = w[r - 2];
+ T2 = w[r - 15];
+ w[r] = ((((T >>> 17) | (T << 15)) ^ ((T >>> 19) | (T << 13)) ^ (T >>> 10))
+ + w[r - 7]
+ + (((T2 >>> 7) | (T2 << 25)) ^ ((T2 >>> 18) | (T2 << 14)) ^ (T2 >>> 3))
+ + w[r - 16]);
+ }
+
+ for (r = 0; r < 64; r++)
+ {
+ T = (H
+ + (((E >>> 6) | (E << 26)) ^ ((E >>> 11) | (E << 21)) ^ ((E >>> 25) | (E << 7)))
+ + ((E & F) ^ (~E & G)) + k[r] + w[r]);
+ T2 = ((((A >>> 2) | (A << 30)) ^ ((A >>> 13) | (A << 19)) ^ ((A >>> 22) | (A << 10)))
+ + ((A & B) ^ (A & C) ^ (B & C)));
+ H = G;
+ G = F;
+ F = E;
+ E = D + T;
+ D = C;
+ C = B;
+ B = A;
+ A = T + T2;
+ }
+
+ return new int[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E, hh5 + F,
+ hh6 + G, hh7 + H };
+ }
+}
diff --git a/gnu/java/security/hash/Sha384.java b/gnu/java/security/hash/Sha384.java
new file mode 100644
index 000000000..2f619dc98
--- /dev/null
+++ b/gnu/java/security/hash/Sha384.java
@@ -0,0 +1,322 @@
+/* Sha384.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>Implementation of SHA2-2 [SHA-384] per the IETF Draft Specification.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://ftp.ipv4.heanet.ie/pub/ietf/internet-drafts/draft-ietf-ipsec-ciph-aes-cbc-03.txt">
+ * Descriptions of SHA-256, SHA-384, and SHA-512</a>,</li>
+ * <li>http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf</li>
+ * </ol>
+ */
+public class Sha384 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final long[] k = { 0x428a2f98d728ae22L, 0x7137449123ef65cdL,
+ 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
+ 0x3956c25bf348b538L, 0x59f111f1b605d019L,
+ 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
+ 0xd807aa98a3030242L, 0x12835b0145706fbeL,
+ 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
+ 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L,
+ 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
+ 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L,
+ 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
+ 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L,
+ 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
+ 0x983e5152ee66dfabL, 0xa831c66d2db43210L,
+ 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
+ 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L,
+ 0x06ca6351e003826fL, 0x142929670a0e6e70L,
+ 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L,
+ 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
+ 0x650a73548baf63deL, 0x766a0abb3c77b2a8L,
+ 0x81c2c92e47edaee6L, 0x92722c851482353bL,
+ 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L,
+ 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
+ 0xd192e819d6ef5218L, 0xd69906245565a910L,
+ 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
+ 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L,
+ 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
+ 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL,
+ 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
+ 0x748f82ee5defb2fcL, 0x78a5636f43172f60L,
+ 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
+ 0x90befffa23631e28L, 0xa4506cebde82bde9L,
+ 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
+ 0xca273eceea26619cL, 0xd186b8c721c0c207L,
+ 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
+ 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L,
+ 0x113f9804bef90daeL, 0x1b710b35131c471bL,
+ 0x28db77f523047d84L, 0x32caab7b40c72493L,
+ 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
+ 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL,
+ 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L };
+
+ private static final int BLOCK_SIZE = 128; // inner block size in bytes
+
+ private static final String DIGEST0 = "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED"
+ + "8086072BA1E7CC2358BAECA134C825A7";
+
+ private static final long[] w = new long[80];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 512-bit interim result. */
+ private long h0, h1, h2, h3, h4, h5, h6, h7;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Sha384()
+ {
+ super(Registry.SHA384_HASH, 48, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Sha384(Sha384 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.h5 = md.h5;
+ this.h6 = md.h6;
+ this.h7 = md.h7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final long[] G(long hh0, long hh1, long hh2, long hh3,
+ long hh4, long hh5, long hh6, long hh7,
+ byte[] in, int offset)
+ {
+ return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Sha384(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ long[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
+
+ h0 = result[0];
+ h1 = result[1];
+ h2 = result[2];
+ h3 = result[3];
+ h4 = result[4];
+ h5 = result[5];
+ h6 = result[6];
+ h7 = result[7];
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 112) ? (112 - n) : (240 - n);
+ byte[] result = new byte[padding + 16];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ // TODO: FIX Only ~35 bits of 128 bit counter usable this way
+ long bits = count << 3;
+ padding += 8;
+ result[padding++] = (byte) (bits >>> 56);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ return new byte[] { (byte) (h0 >>> 56), (byte) (h0 >>> 48),
+ (byte) (h0 >>> 40), (byte) (h0 >>> 32),
+ (byte) (h0 >>> 24), (byte) (h0 >>> 16),
+ (byte) (h0 >>> 8), (byte) h0, (byte) (h1 >>> 56),
+ (byte) (h1 >>> 48), (byte) (h1 >>> 40),
+ (byte) (h1 >>> 32), (byte) (h1 >>> 24),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 8), (byte) h1,
+ (byte) (h2 >>> 56), (byte) (h2 >>> 48),
+ (byte) (h2 >>> 40), (byte) (h2 >>> 32),
+ (byte) (h2 >>> 24), (byte) (h2 >>> 16),
+ (byte) (h2 >>> 8), (byte) h2, (byte) (h3 >>> 56),
+ (byte) (h3 >>> 48), (byte) (h3 >>> 40),
+ (byte) (h3 >>> 32), (byte) (h3 >>> 24),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 8), (byte) h3,
+ (byte) (h4 >>> 56), (byte) (h4 >>> 48),
+ (byte) (h4 >>> 40), (byte) (h4 >>> 32),
+ (byte) (h4 >>> 24), (byte) (h4 >>> 16),
+ (byte) (h4 >>> 8), (byte) h4, (byte) (h5 >>> 56),
+ (byte) (h5 >>> 48), (byte) (h5 >>> 40),
+ (byte) (h5 >>> 32), (byte) (h5 >>> 24),
+ (byte) (h5 >>> 16), (byte) (h5 >>> 8), (byte) h5
+ // (byte)(h6 >>> 56), (byte)(h6 >>> 48), (byte)(h6 >>> 40), (byte)(h6 >>> 32),
+ // (byte)(h6 >>> 24), (byte)(h6 >>> 16), (byte)(h6 >>> 8), (byte) h6,
+ // (byte)(h7 >>> 56), (byte)(h7 >>> 48), (byte)(h7 >>> 40), (byte)(h7 >>> 32),
+ // (byte)(h7 >>> 24), (byte)(h7 >>> 16), (byte)(h7 >>> 8), (byte) h7
+ };
+ }
+
+ protected void resetContext()
+ {
+ // magic SHA-384 initialisation constants
+ h0 = 0xcbbb9d5dc1059ed8L;
+ h1 = 0x629a292a367cd507L;
+ h2 = 0x9159015a3070dd17L;
+ h3 = 0x152fecd8f70e5939L;
+ h4 = 0x67332667ffc00b31L;
+ h5 = 0x8eb44a8768581511L;
+ h6 = 0xdb0c2e0d64f98fa7L;
+ h7 = 0x47b5481dbefa4fa4L;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ Sha384 md = new Sha384();
+ md.update((byte) 0x61); // a
+ md.update((byte) 0x62); // b
+ md.update((byte) 0x63); // c
+ String result = Util.toString(md.digest());
+ valid = new Boolean(DIGEST0.equals(result));
+ }
+ return valid.booleanValue();
+ }
+
+ // SHA specific methods ----------------------------------------------------
+
+ private static final synchronized long[] sha(long hh0, long hh1, long hh2,
+ long hh3, long hh4, long hh5,
+ long hh6, long hh7, byte[] in,
+ int offset)
+ {
+ long A = hh0;
+ long B = hh1;
+ long C = hh2;
+ long D = hh3;
+ long E = hh4;
+ long F = hh5;
+ long G = hh6;
+ long H = hh7;
+ long T, T2;
+ int r;
+
+ for (r = 0; r < 16; r++)
+ {
+ w[r] = (long) in[offset++] << 56 | ((long) in[offset++] & 0xFF) << 48
+ | ((long) in[offset++] & 0xFF) << 40
+ | ((long) in[offset++] & 0xFF) << 32
+ | ((long) in[offset++] & 0xFF) << 24
+ | ((long) in[offset++] & 0xFF) << 16
+ | ((long) in[offset++] & 0xFF) << 8
+ | ((long) in[offset++] & 0xFF);
+ }
+ for (r = 16; r < 80; r++)
+ {
+ T = w[r - 2];
+ T2 = w[r - 15];
+ w[r] = (((T >>> 19) | (T << 45)) ^ ((T >>> 61) | (T << 3)) ^ (T >>> 6))
+ + w[r - 7]
+ + (((T2 >>> 1) | (T2 << 63)) ^ ((T2 >>> 8) | (T2 << 56)) ^ (T2 >>> 7))
+ + w[r - 16];
+ }
+
+ for (r = 0; r < 80; r++)
+ {
+
+ T = H
+ + (((E >>> 14) | (E << 50)) ^ ((E >>> 18) | (E << 46)) ^ ((E >>> 41) | (E << 23)))
+ + ((E & F) ^ ((~E) & G)) + k[r] + w[r];
+ // T IS INCORRECT SOMEHOW
+ T2 = (((A >>> 28) | (A << 36)) ^ ((A >>> 34) | (A << 30)) ^ ((A >>> 39) | (A << 25)))
+ + ((A & B) ^ (A & C) ^ (B & C));
+ H = G;
+ G = F;
+ F = E;
+ E = D + T;
+ D = C;
+ C = B;
+ B = A;
+ A = T + T2;
+ }
+
+ return new long[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E, hh5 + F,
+ hh6 + G, hh7 + H };
+ }
+}
diff --git a/gnu/java/security/hash/Sha512.java b/gnu/java/security/hash/Sha512.java
new file mode 100644
index 000000000..798b34dfc
--- /dev/null
+++ b/gnu/java/security/hash/Sha512.java
@@ -0,0 +1,322 @@
+/* Sha512.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>Implementation of SHA2-3 [SHA-512] per the IETF Draft Specification.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://ftp.ipv4.heanet.ie/pub/ietf/internet-drafts/draft-ietf-ipsec-ciph-aes-cbc-03.txt">
+ * Descriptions of SHA-256, SHA-384, and SHA-512</a>,</li>
+ * <li>http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf</li>
+ * </ol>
+ */
+public class Sha512 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final long[] k = { 0x428a2f98d728ae22L, 0x7137449123ef65cdL,
+ 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
+ 0x3956c25bf348b538L, 0x59f111f1b605d019L,
+ 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
+ 0xd807aa98a3030242L, 0x12835b0145706fbeL,
+ 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
+ 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L,
+ 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
+ 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L,
+ 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
+ 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L,
+ 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
+ 0x983e5152ee66dfabL, 0xa831c66d2db43210L,
+ 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
+ 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L,
+ 0x06ca6351e003826fL, 0x142929670a0e6e70L,
+ 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L,
+ 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
+ 0x650a73548baf63deL, 0x766a0abb3c77b2a8L,
+ 0x81c2c92e47edaee6L, 0x92722c851482353bL,
+ 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L,
+ 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
+ 0xd192e819d6ef5218L, 0xd69906245565a910L,
+ 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
+ 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L,
+ 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
+ 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL,
+ 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
+ 0x748f82ee5defb2fcL, 0x78a5636f43172f60L,
+ 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
+ 0x90befffa23631e28L, 0xa4506cebde82bde9L,
+ 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
+ 0xca273eceea26619cL, 0xd186b8c721c0c207L,
+ 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
+ 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L,
+ 0x113f9804bef90daeL, 0x1b710b35131c471bL,
+ 0x28db77f523047d84L, 0x32caab7b40c72493L,
+ 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
+ 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL,
+ 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L };
+
+ private static final int BLOCK_SIZE = 128; // inner block size in bytes
+
+ private static final String DIGEST0 = "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A"
+ + "2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F";
+
+ private static final long[] w = new long[80];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 512-bit interim result. */
+ private long h0, h1, h2, h3, h4, h5, h6, h7;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Sha512()
+ {
+ super(Registry.SHA512_HASH, 64, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Sha512(Sha512 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.h5 = md.h5;
+ this.h6 = md.h6;
+ this.h7 = md.h7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final long[] G(long hh0, long hh1, long hh2, long hh3,
+ long hh4, long hh5, long hh6, long hh7,
+ byte[] in, int offset)
+ {
+ return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Sha512(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ long[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
+
+ h0 = result[0];
+ h1 = result[1];
+ h2 = result[2];
+ h3 = result[3];
+ h4 = result[4];
+ h5 = result[5];
+ h6 = result[6];
+ h7 = result[7];
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 112) ? (112 - n) : (240 - n);
+ byte[] result = new byte[padding + 16];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ // TODO: FIX Only ~35 bits of 128 bit counter usable this way
+ long bits = count << 3;
+ padding += 8;
+ result[padding++] = (byte) (bits >>> 56);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ return new byte[] { (byte) (h0 >>> 56), (byte) (h0 >>> 48),
+ (byte) (h0 >>> 40), (byte) (h0 >>> 32),
+ (byte) (h0 >>> 24), (byte) (h0 >>> 16),
+ (byte) (h0 >>> 8), (byte) h0, (byte) (h1 >>> 56),
+ (byte) (h1 >>> 48), (byte) (h1 >>> 40),
+ (byte) (h1 >>> 32), (byte) (h1 >>> 24),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 8), (byte) h1,
+ (byte) (h2 >>> 56), (byte) (h2 >>> 48),
+ (byte) (h2 >>> 40), (byte) (h2 >>> 32),
+ (byte) (h2 >>> 24), (byte) (h2 >>> 16),
+ (byte) (h2 >>> 8), (byte) h2, (byte) (h3 >>> 56),
+ (byte) (h3 >>> 48), (byte) (h3 >>> 40),
+ (byte) (h3 >>> 32), (byte) (h3 >>> 24),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 8), (byte) h3,
+ (byte) (h4 >>> 56), (byte) (h4 >>> 48),
+ (byte) (h4 >>> 40), (byte) (h4 >>> 32),
+ (byte) (h4 >>> 24), (byte) (h4 >>> 16),
+ (byte) (h4 >>> 8), (byte) h4, (byte) (h5 >>> 56),
+ (byte) (h5 >>> 48), (byte) (h5 >>> 40),
+ (byte) (h5 >>> 32), (byte) (h5 >>> 24),
+ (byte) (h5 >>> 16), (byte) (h5 >>> 8), (byte) h5,
+ (byte) (h6 >>> 56), (byte) (h6 >>> 48),
+ (byte) (h6 >>> 40), (byte) (h6 >>> 32),
+ (byte) (h6 >>> 24), (byte) (h6 >>> 16),
+ (byte) (h6 >>> 8), (byte) h6, (byte) (h7 >>> 56),
+ (byte) (h7 >>> 48), (byte) (h7 >>> 40),
+ (byte) (h7 >>> 32), (byte) (h7 >>> 24),
+ (byte) (h7 >>> 16), (byte) (h7 >>> 8), (byte) h7 };
+ }
+
+ protected void resetContext()
+ {
+ // magic SHA-512 initialisation constants
+ h0 = 0x6a09e667f3bcc908L;
+ h1 = 0xbb67ae8584caa73bL;
+ h2 = 0x3c6ef372fe94f82bL;
+ h3 = 0xa54ff53a5f1d36f1L;
+ h4 = 0x510e527fade682d1L;
+ h5 = 0x9b05688c2b3e6c1fL;
+ h6 = 0x1f83d9abfb41bd6bL;
+ h7 = 0x5be0cd19137e2179L;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ Sha512 md = new Sha512();
+ md.update((byte) 0x61); // a
+ md.update((byte) 0x62); // b
+ md.update((byte) 0x63); // c
+ String result = Util.toString(md.digest());
+ valid = new Boolean(DIGEST0.equals(result));
+ }
+ return valid.booleanValue();
+ }
+
+ // SHA specific methods ----------------------------------------------------
+
+ private static final synchronized long[] sha(long hh0, long hh1, long hh2,
+ long hh3, long hh4, long hh5,
+ long hh6, long hh7, byte[] in,
+ int offset)
+ {
+ long A = hh0;
+ long B = hh1;
+ long C = hh2;
+ long D = hh3;
+ long E = hh4;
+ long F = hh5;
+ long G = hh6;
+ long H = hh7;
+ long T, T2;
+ int r;
+
+ for (r = 0; r < 16; r++)
+ {
+ w[r] = (long) in[offset++] << 56 | ((long) in[offset++] & 0xFF) << 48
+ | ((long) in[offset++] & 0xFF) << 40
+ | ((long) in[offset++] & 0xFF) << 32
+ | ((long) in[offset++] & 0xFF) << 24
+ | ((long) in[offset++] & 0xFF) << 16
+ | ((long) in[offset++] & 0xFF) << 8
+ | ((long) in[offset++] & 0xFF);
+ }
+ for (r = 16; r < 80; r++)
+ {
+ T = w[r - 2];
+ T2 = w[r - 15];
+ w[r] = (((T >>> 19) | (T << 45)) ^ ((T >>> 61) | (T << 3)) ^ (T >>> 6))
+ + w[r - 7]
+ + (((T2 >>> 1) | (T2 << 63)) ^ ((T2 >>> 8) | (T2 << 56)) ^ (T2 >>> 7))
+ + w[r - 16];
+ }
+
+ for (r = 0; r < 80; r++)
+ {
+ T = H
+ + (((E >>> 14) | (E << 50)) ^ ((E >>> 18) | (E << 46)) ^ ((E >>> 41) | (E << 23)))
+ + ((E & F) ^ ((~E) & G)) + k[r] + w[r];
+ T2 = (((A >>> 28) | (A << 36)) ^ ((A >>> 34) | (A << 30)) ^ ((A >>> 39) | (A << 25)))
+ + ((A & B) ^ (A & C) ^ (B & C));
+ H = G;
+ G = F;
+ F = E;
+ E = D + T;
+ D = C;
+ C = B;
+ B = A;
+ A = T + T2;
+ }
+
+ return new long[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E, hh5 + F,
+ hh6 + G, hh7 + H };
+ }
+}
diff --git a/gnu/java/security/hash/Tiger.java b/gnu/java/security/hash/Tiger.java
new file mode 100644
index 000000000..f39fed30d
--- /dev/null
+++ b/gnu/java/security/hash/Tiger.java
@@ -0,0 +1,943 @@
+/* Tiger.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * The Tiger message digest. Tiger was designed by Ross Anderson and Eli
+ * Biham, with the goal of producing a secure, fast hash function that
+ * performs especially well on next-generation 64-bit architectures, but
+ * is still efficient on 32- and 16-bit architectures.
+ *
+ * <p>Tiger processes data in 512-bit blocks and produces a 192-bit
+ * digest.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a
+ * href="http://www.cs.technion.ac.il/~biham/Reports/Tiger/">Tiger: A
+ * Fast New Hash Function</a>, Ross Anderson and Eli Biham.</a></li>
+ * </ol>
+ */
+public class Tiger extends BaseHash
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ private static final int HASH_SIZE = 24;
+
+ private static final int BLOCK_SIZE = 64;
+
+ /** Result when no data has been input. */
+ private static final String DIGEST0 = "3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3";
+
+ private static final long A = 0x0123456789ABCDEFL;
+
+ private static final long B = 0xFEDCBA9876543210L;
+
+ private static final long C = 0xF096A5B4C3B2E187L;
+
+ /** S-Box T1. */
+ private static final long[] T1 = { 0x02AAB17CF7E90C5EL, 0xAC424B03E243A8ECL,
+ 0x72CD5BE30DD5FCD3L, 0x6D019B93F6F97F3AL,
+ 0xCD9978FFD21F9193L, 0x7573A1C9708029E2L,
+ 0xB164326B922A83C3L, 0x46883EEE04915870L,
+ 0xEAACE3057103ECE6L, 0xC54169B808A3535CL,
+ 0x4CE754918DDEC47CL, 0x0AA2F4DFDC0DF40CL,
+ 0x10B76F18A74DBEFAL, 0xC6CCB6235AD1AB6AL,
+ 0x13726121572FE2FFL, 0x1A488C6F199D921EL,
+ 0x4BC9F9F4DA0007CAL, 0x26F5E6F6E85241C7L,
+ 0x859079DBEA5947B6L, 0x4F1885C5C99E8C92L,
+ 0xD78E761EA96F864BL, 0x8E36428C52B5C17DL,
+ 0x69CF6827373063C1L, 0xB607C93D9BB4C56EL,
+ 0x7D820E760E76B5EAL, 0x645C9CC6F07FDC42L,
+ 0xBF38A078243342E0L, 0x5F6B343C9D2E7D04L,
+ 0xF2C28AEB600B0EC6L, 0x6C0ED85F7254BCACL,
+ 0x71592281A4DB4FE5L, 0x1967FA69CE0FED9FL,
+ 0xFD5293F8B96545DBL, 0xC879E9D7F2A7600BL,
+ 0x860248920193194EL, 0xA4F9533B2D9CC0B3L,
+ 0x9053836C15957613L, 0xDB6DCF8AFC357BF1L,
+ 0x18BEEA7A7A370F57L, 0x037117CA50B99066L,
+ 0x6AB30A9774424A35L, 0xF4E92F02E325249BL,
+ 0x7739DB07061CCAE1L, 0xD8F3B49CECA42A05L,
+ 0xBD56BE3F51382F73L, 0x45FAED5843B0BB28L,
+ 0x1C813D5C11BF1F83L, 0x8AF0E4B6D75FA169L,
+ 0x33EE18A487AD9999L, 0x3C26E8EAB1C94410L,
+ 0xB510102BC0A822F9L, 0x141EEF310CE6123BL,
+ 0xFC65B90059DDB154L, 0xE0158640C5E0E607L,
+ 0x884E079826C3A3CFL, 0x930D0D9523C535FDL,
+ 0x35638D754E9A2B00L, 0x4085FCCF40469DD5L,
+ 0xC4B17AD28BE23A4CL, 0xCAB2F0FC6A3E6A2EL,
+ 0x2860971A6B943FCDL, 0x3DDE6EE212E30446L,
+ 0x6222F32AE01765AEL, 0x5D550BB5478308FEL,
+ 0xA9EFA98DA0EDA22AL, 0xC351A71686C40DA7L,
+ 0x1105586D9C867C84L, 0xDCFFEE85FDA22853L,
+ 0xCCFBD0262C5EEF76L, 0xBAF294CB8990D201L,
+ 0xE69464F52AFAD975L, 0x94B013AFDF133E14L,
+ 0x06A7D1A32823C958L, 0x6F95FE5130F61119L,
+ 0xD92AB34E462C06C0L, 0xED7BDE33887C71D2L,
+ 0x79746D6E6518393EL, 0x5BA419385D713329L,
+ 0x7C1BA6B948A97564L, 0x31987C197BFDAC67L,
+ 0xDE6C23C44B053D02L, 0x581C49FED002D64DL,
+ 0xDD474D6338261571L, 0xAA4546C3E473D062L,
+ 0x928FCE349455F860L, 0x48161BBACAAB94D9L,
+ 0x63912430770E6F68L, 0x6EC8A5E602C6641CL,
+ 0x87282515337DDD2BL, 0x2CDA6B42034B701BL,
+ 0xB03D37C181CB096DL, 0xE108438266C71C6FL,
+ 0x2B3180C7EB51B255L, 0xDF92B82F96C08BBCL,
+ 0x5C68C8C0A632F3BAL, 0x5504CC861C3D0556L,
+ 0xABBFA4E55FB26B8FL, 0x41848B0AB3BACEB4L,
+ 0xB334A273AA445D32L, 0xBCA696F0A85AD881L,
+ 0x24F6EC65B528D56CL, 0x0CE1512E90F4524AL,
+ 0x4E9DD79D5506D35AL, 0x258905FAC6CE9779L,
+ 0x2019295B3E109B33L, 0xF8A9478B73A054CCL,
+ 0x2924F2F934417EB0L, 0x3993357D536D1BC4L,
+ 0x38A81AC21DB6FF8BL, 0x47C4FBF17D6016BFL,
+ 0x1E0FAADD7667E3F5L, 0x7ABCFF62938BEB96L,
+ 0xA78DAD948FC179C9L, 0x8F1F98B72911E50DL,
+ 0x61E48EAE27121A91L, 0x4D62F7AD31859808L,
+ 0xECEBA345EF5CEAEBL, 0xF5CEB25EBC9684CEL,
+ 0xF633E20CB7F76221L, 0xA32CDF06AB8293E4L,
+ 0x985A202CA5EE2CA4L, 0xCF0B8447CC8A8FB1L,
+ 0x9F765244979859A3L, 0xA8D516B1A1240017L,
+ 0x0BD7BA3EBB5DC726L, 0xE54BCA55B86ADB39L,
+ 0x1D7A3AFD6C478063L, 0x519EC608E7669EDDL,
+ 0x0E5715A2D149AA23L, 0x177D4571848FF194L,
+ 0xEEB55F3241014C22L, 0x0F5E5CA13A6E2EC2L,
+ 0x8029927B75F5C361L, 0xAD139FABC3D6E436L,
+ 0x0D5DF1A94CCF402FL, 0x3E8BD948BEA5DFC8L,
+ 0xA5A0D357BD3FF77EL, 0xA2D12E251F74F645L,
+ 0x66FD9E525E81A082L, 0x2E0C90CE7F687A49L,
+ 0xC2E8BCBEBA973BC5L, 0x000001BCE509745FL,
+ 0x423777BBE6DAB3D6L, 0xD1661C7EAEF06EB5L,
+ 0xA1781F354DAACFD8L, 0x2D11284A2B16AFFCL,
+ 0xF1FC4F67FA891D1FL, 0x73ECC25DCB920ADAL,
+ 0xAE610C22C2A12651L, 0x96E0A810D356B78AL,
+ 0x5A9A381F2FE7870FL, 0xD5AD62EDE94E5530L,
+ 0xD225E5E8368D1427L, 0x65977B70C7AF4631L,
+ 0x99F889B2DE39D74FL, 0x233F30BF54E1D143L,
+ 0x9A9675D3D9A63C97L, 0x5470554FF334F9A8L,
+ 0x166ACB744A4F5688L, 0x70C74CAAB2E4AEADL,
+ 0xF0D091646F294D12L, 0x57B82A89684031D1L,
+ 0xEFD95A5A61BE0B6BL, 0x2FBD12E969F2F29AL,
+ 0x9BD37013FEFF9FE8L, 0x3F9B0404D6085A06L,
+ 0x4940C1F3166CFE15L, 0x09542C4DCDF3DEFBL,
+ 0xB4C5218385CD5CE3L, 0xC935B7DC4462A641L,
+ 0x3417F8A68ED3B63FL, 0xB80959295B215B40L,
+ 0xF99CDAEF3B8C8572L, 0x018C0614F8FCB95DL,
+ 0x1B14ACCD1A3ACDF3L, 0x84D471F200BB732DL,
+ 0xC1A3110E95E8DA16L, 0x430A7220BF1A82B8L,
+ 0xB77E090D39DF210EL, 0x5EF4BD9F3CD05E9DL,
+ 0x9D4FF6DA7E57A444L, 0xDA1D60E183D4A5F8L,
+ 0xB287C38417998E47L, 0xFE3EDC121BB31886L,
+ 0xC7FE3CCC980CCBEFL, 0xE46FB590189BFD03L,
+ 0x3732FD469A4C57DCL, 0x7EF700A07CF1AD65L,
+ 0x59C64468A31D8859L, 0x762FB0B4D45B61F6L,
+ 0x155BAED099047718L, 0x68755E4C3D50BAA6L,
+ 0xE9214E7F22D8B4DFL, 0x2ADDBF532EAC95F4L,
+ 0x32AE3909B4BD0109L, 0x834DF537B08E3450L,
+ 0xFA209DA84220728DL, 0x9E691D9B9EFE23F7L,
+ 0x0446D288C4AE8D7FL, 0x7B4CC524E169785BL,
+ 0x21D87F0135CA1385L, 0xCEBB400F137B8AA5L,
+ 0x272E2B66580796BEL, 0x3612264125C2B0DEL,
+ 0x057702BDAD1EFBB2L, 0xD4BABB8EACF84BE9L,
+ 0x91583139641BC67BL, 0x8BDC2DE08036E024L,
+ 0x603C8156F49F68EDL, 0xF7D236F7DBEF5111L,
+ 0x9727C4598AD21E80L, 0xA08A0896670A5FD7L,
+ 0xCB4A8F4309EBA9CBL, 0x81AF564B0F7036A1L,
+ 0xC0B99AA778199ABDL, 0x959F1EC83FC8E952L,
+ 0x8C505077794A81B9L, 0x3ACAAF8F056338F0L,
+ 0x07B43F50627A6778L, 0x4A44AB49F5ECCC77L,
+ 0x3BC3D6E4B679EE98L, 0x9CC0D4D1CF14108CL,
+ 0x4406C00B206BC8A0L, 0x82A18854C8D72D89L,
+ 0x67E366B35C3C432CL, 0xB923DD61102B37F2L,
+ 0x56AB2779D884271DL, 0xBE83E1B0FF1525AFL,
+ 0xFB7C65D4217E49A9L, 0x6BDBE0E76D48E7D4L,
+ 0x08DF828745D9179EL, 0x22EA6A9ADD53BD34L,
+ 0xE36E141C5622200AL, 0x7F805D1B8CB750EEL,
+ 0xAFE5C7A59F58E837L, 0xE27F996A4FB1C23CL,
+ 0xD3867DFB0775F0D0L, 0xD0E673DE6E88891AL,
+ 0x123AEB9EAFB86C25L, 0x30F1D5D5C145B895L,
+ 0xBB434A2DEE7269E7L, 0x78CB67ECF931FA38L,
+ 0xF33B0372323BBF9CL, 0x52D66336FB279C74L,
+ 0x505F33AC0AFB4EAAL, 0xE8A5CD99A2CCE187L,
+ 0x534974801E2D30BBL, 0x8D2D5711D5876D90L,
+ 0x1F1A412891BC038EL, 0xD6E2E71D82E56648L,
+ 0x74036C3A497732B7L, 0x89B67ED96361F5ABL,
+ 0xFFED95D8F1EA02A2L, 0xE72B3BD61464D43DL,
+ 0xA6300F170BDC4820L, 0xEBC18760ED78A77AL };
+
+ /** S-Box T2. */
+ private static final long[] T2 = { 0xE6A6BE5A05A12138L, 0xB5A122A5B4F87C98L,
+ 0x563C6089140B6990L, 0x4C46CB2E391F5DD5L,
+ 0xD932ADDBC9B79434L, 0x08EA70E42015AFF5L,
+ 0xD765A6673E478CF1L, 0xC4FB757EAB278D99L,
+ 0xDF11C6862D6E0692L, 0xDDEB84F10D7F3B16L,
+ 0x6F2EF604A665EA04L, 0x4A8E0F0FF0E0DFB3L,
+ 0xA5EDEEF83DBCBA51L, 0xFC4F0A2A0EA4371EL,
+ 0xE83E1DA85CB38429L, 0xDC8FF882BA1B1CE2L,
+ 0xCD45505E8353E80DL, 0x18D19A00D4DB0717L,
+ 0x34A0CFEDA5F38101L, 0x0BE77E518887CAF2L,
+ 0x1E341438B3C45136L, 0xE05797F49089CCF9L,
+ 0xFFD23F9DF2591D14L, 0x543DDA228595C5CDL,
+ 0x661F81FD99052A33L, 0x8736E641DB0F7B76L,
+ 0x15227725418E5307L, 0xE25F7F46162EB2FAL,
+ 0x48A8B2126C13D9FEL, 0xAFDC541792E76EEAL,
+ 0x03D912BFC6D1898FL, 0x31B1AAFA1B83F51BL,
+ 0xF1AC2796E42AB7D9L, 0x40A3A7D7FCD2EBACL,
+ 0x1056136D0AFBBCC5L, 0x7889E1DD9A6D0C85L,
+ 0xD33525782A7974AAL, 0xA7E25D09078AC09BL,
+ 0xBD4138B3EAC6EDD0L, 0x920ABFBE71EB9E70L,
+ 0xA2A5D0F54FC2625CL, 0xC054E36B0B1290A3L,
+ 0xF6DD59FF62FE932BL, 0x3537354511A8AC7DL,
+ 0xCA845E9172FADCD4L, 0x84F82B60329D20DCL,
+ 0x79C62CE1CD672F18L, 0x8B09A2ADD124642CL,
+ 0xD0C1E96A19D9E726L, 0x5A786A9B4BA9500CL,
+ 0x0E020336634C43F3L, 0xC17B474AEB66D822L,
+ 0x6A731AE3EC9BAAC2L, 0x8226667AE0840258L,
+ 0x67D4567691CAECA5L, 0x1D94155C4875ADB5L,
+ 0x6D00FD985B813FDFL, 0x51286EFCB774CD06L,
+ 0x5E8834471FA744AFL, 0xF72CA0AEE761AE2EL,
+ 0xBE40E4CDAEE8E09AL, 0xE9970BBB5118F665L,
+ 0x726E4BEB33DF1964L, 0x703B000729199762L,
+ 0x4631D816F5EF30A7L, 0xB880B5B51504A6BEL,
+ 0x641793C37ED84B6CL, 0x7B21ED77F6E97D96L,
+ 0x776306312EF96B73L, 0xAE528948E86FF3F4L,
+ 0x53DBD7F286A3F8F8L, 0x16CADCE74CFC1063L,
+ 0x005C19BDFA52C6DDL, 0x68868F5D64D46AD3L,
+ 0x3A9D512CCF1E186AL, 0x367E62C2385660AEL,
+ 0xE359E7EA77DCB1D7L, 0x526C0773749ABE6EL,
+ 0x735AE5F9D09F734BL, 0x493FC7CC8A558BA8L,
+ 0xB0B9C1533041AB45L, 0x321958BA470A59BDL,
+ 0x852DB00B5F46C393L, 0x91209B2BD336B0E5L,
+ 0x6E604F7D659EF19FL, 0xB99A8AE2782CCB24L,
+ 0xCCF52AB6C814C4C7L, 0x4727D9AFBE11727BL,
+ 0x7E950D0C0121B34DL, 0x756F435670AD471FL,
+ 0xF5ADD442615A6849L, 0x4E87E09980B9957AL,
+ 0x2ACFA1DF50AEE355L, 0xD898263AFD2FD556L,
+ 0xC8F4924DD80C8FD6L, 0xCF99CA3D754A173AL,
+ 0xFE477BACAF91BF3CL, 0xED5371F6D690C12DL,
+ 0x831A5C285E687094L, 0xC5D3C90A3708A0A4L,
+ 0x0F7F903717D06580L, 0x19F9BB13B8FDF27FL,
+ 0xB1BD6F1B4D502843L, 0x1C761BA38FFF4012L,
+ 0x0D1530C4E2E21F3BL, 0x8943CE69A7372C8AL,
+ 0xE5184E11FEB5CE66L, 0x618BDB80BD736621L,
+ 0x7D29BAD68B574D0BL, 0x81BB613E25E6FE5BL,
+ 0x071C9C10BC07913FL, 0xC7BEEB7909AC2D97L,
+ 0xC3E58D353BC5D757L, 0xEB017892F38F61E8L,
+ 0xD4EFFB9C9B1CC21AL, 0x99727D26F494F7ABL,
+ 0xA3E063A2956B3E03L, 0x9D4A8B9A4AA09C30L,
+ 0x3F6AB7D500090FB4L, 0x9CC0F2A057268AC0L,
+ 0x3DEE9D2DEDBF42D1L, 0x330F49C87960A972L,
+ 0xC6B2720287421B41L, 0x0AC59EC07C00369CL,
+ 0xEF4EAC49CB353425L, 0xF450244EEF0129D8L,
+ 0x8ACC46E5CAF4DEB6L, 0x2FFEAB63989263F7L,
+ 0x8F7CB9FE5D7A4578L, 0x5BD8F7644E634635L,
+ 0x427A7315BF2DC900L, 0x17D0C4AA2125261CL,
+ 0x3992486C93518E50L, 0xB4CBFEE0A2D7D4C3L,
+ 0x7C75D6202C5DDD8DL, 0xDBC295D8E35B6C61L,
+ 0x60B369D302032B19L, 0xCE42685FDCE44132L,
+ 0x06F3DDB9DDF65610L, 0x8EA4D21DB5E148F0L,
+ 0x20B0FCE62FCD496FL, 0x2C1B912358B0EE31L,
+ 0xB28317B818F5A308L, 0xA89C1E189CA6D2CFL,
+ 0x0C6B18576AAADBC8L, 0xB65DEAA91299FAE3L,
+ 0xFB2B794B7F1027E7L, 0x04E4317F443B5BEBL,
+ 0x4B852D325939D0A6L, 0xD5AE6BEEFB207FFCL,
+ 0x309682B281C7D374L, 0xBAE309A194C3B475L,
+ 0x8CC3F97B13B49F05L, 0x98A9422FF8293967L,
+ 0x244B16B01076FF7CL, 0xF8BF571C663D67EEL,
+ 0x1F0D6758EEE30DA1L, 0xC9B611D97ADEB9B7L,
+ 0xB7AFD5887B6C57A2L, 0x6290AE846B984FE1L,
+ 0x94DF4CDEACC1A5FDL, 0x058A5BD1C5483AFFL,
+ 0x63166CC142BA3C37L, 0x8DB8526EB2F76F40L,
+ 0xE10880036F0D6D4EL, 0x9E0523C9971D311DL,
+ 0x45EC2824CC7CD691L, 0x575B8359E62382C9L,
+ 0xFA9E400DC4889995L, 0xD1823ECB45721568L,
+ 0xDAFD983B8206082FL, 0xAA7D29082386A8CBL,
+ 0x269FCD4403B87588L, 0x1B91F5F728BDD1E0L,
+ 0xE4669F39040201F6L, 0x7A1D7C218CF04ADEL,
+ 0x65623C29D79CE5CEL, 0x2368449096C00BB1L,
+ 0xAB9BF1879DA503BAL, 0xBC23ECB1A458058EL,
+ 0x9A58DF01BB401ECCL, 0xA070E868A85F143DL,
+ 0x4FF188307DF2239EL, 0x14D565B41A641183L,
+ 0xEE13337452701602L, 0x950E3DCF3F285E09L,
+ 0x59930254B9C80953L, 0x3BF299408930DA6DL,
+ 0xA955943F53691387L, 0xA15EDECAA9CB8784L,
+ 0x29142127352BE9A0L, 0x76F0371FFF4E7AFBL,
+ 0x0239F450274F2228L, 0xBB073AF01D5E868BL,
+ 0xBFC80571C10E96C1L, 0xD267088568222E23L,
+ 0x9671A3D48E80B5B0L, 0x55B5D38AE193BB81L,
+ 0x693AE2D0A18B04B8L, 0x5C48B4ECADD5335FL,
+ 0xFD743B194916A1CAL, 0x2577018134BE98C4L,
+ 0xE77987E83C54A4ADL, 0x28E11014DA33E1B9L,
+ 0x270CC59E226AA213L, 0x71495F756D1A5F60L,
+ 0x9BE853FB60AFEF77L, 0xADC786A7F7443DBFL,
+ 0x0904456173B29A82L, 0x58BC7A66C232BD5EL,
+ 0xF306558C673AC8B2L, 0x41F639C6B6C9772AL,
+ 0x216DEFE99FDA35DAL, 0x11640CC71C7BE615L,
+ 0x93C43694565C5527L, 0xEA038E6246777839L,
+ 0xF9ABF3CE5A3E2469L, 0x741E768D0FD312D2L,
+ 0x0144B883CED652C6L, 0xC20B5A5BA33F8552L,
+ 0x1AE69633C3435A9DL, 0x97A28CA4088CFDECL,
+ 0x8824A43C1E96F420L, 0x37612FA66EEEA746L,
+ 0x6B4CB165F9CF0E5AL, 0x43AA1C06A0ABFB4AL,
+ 0x7F4DC26FF162796BL, 0x6CBACC8E54ED9B0FL,
+ 0xA6B7FFEFD2BB253EL, 0x2E25BC95B0A29D4FL,
+ 0x86D6A58BDEF1388CL, 0xDED74AC576B6F054L,
+ 0x8030BDBC2B45805DL, 0x3C81AF70E94D9289L,
+ 0x3EFF6DDA9E3100DBL, 0xB38DC39FDFCC8847L,
+ 0x123885528D17B87EL, 0xF2DA0ED240B1B642L,
+ 0x44CEFADCD54BF9A9L, 0x1312200E433C7EE6L,
+ 0x9FFCC84F3A78C748L, 0xF0CD1F72248576BBL,
+ 0xEC6974053638CFE4L, 0x2BA7B67C0CEC4E4CL,
+ 0xAC2F4DF3E5CE32EDL, 0xCB33D14326EA4C11L,
+ 0xA4E9044CC77E58BCL, 0x5F513293D934FCEFL,
+ 0x5DC9645506E55444L, 0x50DE418F317DE40AL,
+ 0x388CB31A69DDE259L, 0x2DB4A83455820A86L,
+ 0x9010A91E84711AE9L, 0x4DF7F0B7B1498371L,
+ 0xD62A2EABC0977179L, 0x22FAC097AA8D5C0EL };
+
+ /** S-Box T3. */
+ private static final long[] T3 = { 0xF49FCC2FF1DAF39BL, 0x487FD5C66FF29281L,
+ 0xE8A30667FCDCA83FL, 0x2C9B4BE3D2FCCE63L,
+ 0xDA3FF74B93FBBBC2L, 0x2FA165D2FE70BA66L,
+ 0xA103E279970E93D4L, 0xBECDEC77B0E45E71L,
+ 0xCFB41E723985E497L, 0xB70AAA025EF75017L,
+ 0xD42309F03840B8E0L, 0x8EFC1AD035898579L,
+ 0x96C6920BE2B2ABC5L, 0x66AF4163375A9172L,
+ 0x2174ABDCCA7127FBL, 0xB33CCEA64A72FF41L,
+ 0xF04A4933083066A5L, 0x8D970ACDD7289AF5L,
+ 0x8F96E8E031C8C25EL, 0xF3FEC02276875D47L,
+ 0xEC7BF310056190DDL, 0xF5ADB0AEBB0F1491L,
+ 0x9B50F8850FD58892L, 0x4975488358B74DE8L,
+ 0xA3354FF691531C61L, 0x0702BBE481D2C6EEL,
+ 0x89FB24057DEDED98L, 0xAC3075138596E902L,
+ 0x1D2D3580172772EDL, 0xEB738FC28E6BC30DL,
+ 0x5854EF8F63044326L, 0x9E5C52325ADD3BBEL,
+ 0x90AA53CF325C4623L, 0xC1D24D51349DD067L,
+ 0x2051CFEEA69EA624L, 0x13220F0A862E7E4FL,
+ 0xCE39399404E04864L, 0xD9C42CA47086FCB7L,
+ 0x685AD2238A03E7CCL, 0x066484B2AB2FF1DBL,
+ 0xFE9D5D70EFBF79ECL, 0x5B13B9DD9C481854L,
+ 0x15F0D475ED1509ADL, 0x0BEBCD060EC79851L,
+ 0xD58C6791183AB7F8L, 0xD1187C5052F3EEE4L,
+ 0xC95D1192E54E82FFL, 0x86EEA14CB9AC6CA2L,
+ 0x3485BEB153677D5DL, 0xDD191D781F8C492AL,
+ 0xF60866BAA784EBF9L, 0x518F643BA2D08C74L,
+ 0x8852E956E1087C22L, 0xA768CB8DC410AE8DL,
+ 0x38047726BFEC8E1AL, 0xA67738B4CD3B45AAL,
+ 0xAD16691CEC0DDE19L, 0xC6D4319380462E07L,
+ 0xC5A5876D0BA61938L, 0x16B9FA1FA58FD840L,
+ 0x188AB1173CA74F18L, 0xABDA2F98C99C021FL,
+ 0x3E0580AB134AE816L, 0x5F3B05B773645ABBL,
+ 0x2501A2BE5575F2F6L, 0x1B2F74004E7E8BA9L,
+ 0x1CD7580371E8D953L, 0x7F6ED89562764E30L,
+ 0xB15926FF596F003DL, 0x9F65293DA8C5D6B9L,
+ 0x6ECEF04DD690F84CL, 0x4782275FFF33AF88L,
+ 0xE41433083F820801L, 0xFD0DFE409A1AF9B5L,
+ 0x4325A3342CDB396BL, 0x8AE77E62B301B252L,
+ 0xC36F9E9F6655615AL, 0x85455A2D92D32C09L,
+ 0xF2C7DEA949477485L, 0x63CFB4C133A39EBAL,
+ 0x83B040CC6EBC5462L, 0x3B9454C8FDB326B0L,
+ 0x56F56A9E87FFD78CL, 0x2DC2940D99F42BC6L,
+ 0x98F7DF096B096E2DL, 0x19A6E01E3AD852BFL,
+ 0x42A99CCBDBD4B40BL, 0xA59998AF45E9C559L,
+ 0x366295E807D93186L, 0x6B48181BFAA1F773L,
+ 0x1FEC57E2157A0A1DL, 0x4667446AF6201AD5L,
+ 0xE615EBCACFB0F075L, 0xB8F31F4F68290778L,
+ 0x22713ED6CE22D11EL, 0x3057C1A72EC3C93BL,
+ 0xCB46ACC37C3F1F2FL, 0xDBB893FD02AAF50EL,
+ 0x331FD92E600B9FCFL, 0xA498F96148EA3AD6L,
+ 0xA8D8426E8B6A83EAL, 0xA089B274B7735CDCL,
+ 0x87F6B3731E524A11L, 0x118808E5CBC96749L,
+ 0x9906E4C7B19BD394L, 0xAFED7F7E9B24A20CL,
+ 0x6509EADEEB3644A7L, 0x6C1EF1D3E8EF0EDEL,
+ 0xB9C97D43E9798FB4L, 0xA2F2D784740C28A3L,
+ 0x7B8496476197566FL, 0x7A5BE3E6B65F069DL,
+ 0xF96330ED78BE6F10L, 0xEEE60DE77A076A15L,
+ 0x2B4BEE4AA08B9BD0L, 0x6A56A63EC7B8894EL,
+ 0x02121359BA34FEF4L, 0x4CBF99F8283703FCL,
+ 0x398071350CAF30C8L, 0xD0A77A89F017687AL,
+ 0xF1C1A9EB9E423569L, 0x8C7976282DEE8199L,
+ 0x5D1737A5DD1F7ABDL, 0x4F53433C09A9FA80L,
+ 0xFA8B0C53DF7CA1D9L, 0x3FD9DCBC886CCB77L,
+ 0xC040917CA91B4720L, 0x7DD00142F9D1DCDFL,
+ 0x8476FC1D4F387B58L, 0x23F8E7C5F3316503L,
+ 0x032A2244E7E37339L, 0x5C87A5D750F5A74BL,
+ 0x082B4CC43698992EL, 0xDF917BECB858F63CL,
+ 0x3270B8FC5BF86DDAL, 0x10AE72BB29B5DD76L,
+ 0x576AC94E7700362BL, 0x1AD112DAC61EFB8FL,
+ 0x691BC30EC5FAA427L, 0xFF246311CC327143L,
+ 0x3142368E30E53206L, 0x71380E31E02CA396L,
+ 0x958D5C960AAD76F1L, 0xF8D6F430C16DA536L,
+ 0xC8FFD13F1BE7E1D2L, 0x7578AE66004DDBE1L,
+ 0x05833F01067BE646L, 0xBB34B5AD3BFE586DL,
+ 0x095F34C9A12B97F0L, 0x247AB64525D60CA8L,
+ 0xDCDBC6F3017477D1L, 0x4A2E14D4DECAD24DL,
+ 0xBDB5E6D9BE0A1EEBL, 0x2A7E70F7794301ABL,
+ 0xDEF42D8A270540FDL, 0x01078EC0A34C22C1L,
+ 0xE5DE511AF4C16387L, 0x7EBB3A52BD9A330AL,
+ 0x77697857AA7D6435L, 0x004E831603AE4C32L,
+ 0xE7A21020AD78E312L, 0x9D41A70C6AB420F2L,
+ 0x28E06C18EA1141E6L, 0xD2B28CBD984F6B28L,
+ 0x26B75F6C446E9D83L, 0xBA47568C4D418D7FL,
+ 0xD80BADBFE6183D8EL, 0x0E206D7F5F166044L,
+ 0xE258A43911CBCA3EL, 0x723A1746B21DC0BCL,
+ 0xC7CAA854F5D7CDD3L, 0x7CAC32883D261D9CL,
+ 0x7690C26423BA942CL, 0x17E55524478042B8L,
+ 0xE0BE477656A2389FL, 0x4D289B5E67AB2DA0L,
+ 0x44862B9C8FBBFD31L, 0xB47CC8049D141365L,
+ 0x822C1B362B91C793L, 0x4EB14655FB13DFD8L,
+ 0x1ECBBA0714E2A97BL, 0x6143459D5CDE5F14L,
+ 0x53A8FBF1D5F0AC89L, 0x97EA04D81C5E5B00L,
+ 0x622181A8D4FDB3F3L, 0xE9BCD341572A1208L,
+ 0x1411258643CCE58AL, 0x9144C5FEA4C6E0A4L,
+ 0x0D33D06565CF620FL, 0x54A48D489F219CA1L,
+ 0xC43E5EAC6D63C821L, 0xA9728B3A72770DAFL,
+ 0xD7934E7B20DF87EFL, 0xE35503B61A3E86E5L,
+ 0xCAE321FBC819D504L, 0x129A50B3AC60BFA6L,
+ 0xCD5E68EA7E9FB6C3L, 0xB01C90199483B1C7L,
+ 0x3DE93CD5C295376CL, 0xAED52EDF2AB9AD13L,
+ 0x2E60F512C0A07884L, 0xBC3D86A3E36210C9L,
+ 0x35269D9B163951CEL, 0x0C7D6E2AD0CDB5FAL,
+ 0x59E86297D87F5733L, 0x298EF221898DB0E7L,
+ 0x55000029D1A5AA7EL, 0x8BC08AE1B5061B45L,
+ 0xC2C31C2B6C92703AL, 0x94CC596BAF25EF42L,
+ 0x0A1D73DB22540456L, 0x04B6A0F9D9C4179AL,
+ 0xEFFDAFA2AE3D3C60L, 0xF7C8075BB49496C4L,
+ 0x9CC5C7141D1CD4E3L, 0x78BD1638218E5534L,
+ 0xB2F11568F850246AL, 0xEDFABCFA9502BC29L,
+ 0x796CE5F2DA23051BL, 0xAAE128B0DC93537CL,
+ 0x3A493DA0EE4B29AEL, 0xB5DF6B2C416895D7L,
+ 0xFCABBD25122D7F37L, 0x70810B58105DC4B1L,
+ 0xE10FDD37F7882A90L, 0x524DCAB5518A3F5CL,
+ 0x3C9E85878451255BL, 0x4029828119BD34E2L,
+ 0x74A05B6F5D3CECCBL, 0xB610021542E13ECAL,
+ 0x0FF979D12F59E2ACL, 0x6037DA27E4F9CC50L,
+ 0x5E92975A0DF1847DL, 0xD66DE190D3E623FEL,
+ 0x5032D6B87B568048L, 0x9A36B7CE8235216EL,
+ 0x80272A7A24F64B4AL, 0x93EFED8B8C6916F7L,
+ 0x37DDBFF44CCE1555L, 0x4B95DB5D4B99BD25L,
+ 0x92D3FDA169812FC0L, 0xFB1A4A9A90660BB6L,
+ 0x730C196946A4B9B2L, 0x81E289AA7F49DA68L,
+ 0x64669A0F83B1A05FL, 0x27B3FF7D9644F48BL,
+ 0xCC6B615C8DB675B3L, 0x674F20B9BCEBBE95L,
+ 0x6F31238275655982L, 0x5AE488713E45CF05L,
+ 0xBF619F9954C21157L, 0xEABAC46040A8EAE9L,
+ 0x454C6FE9F2C0C1CDL, 0x419CF6496412691CL,
+ 0xD3DC3BEF265B0F70L, 0x6D0E60F5C3578A9EL };
+
+ /** S-Box T4. */
+ private static final long[] T4 = { 0x5B0E608526323C55L, 0x1A46C1A9FA1B59F5L,
+ 0xA9E245A17C4C8FFAL, 0x65CA5159DB2955D7L,
+ 0x05DB0A76CE35AFC2L, 0x81EAC77EA9113D45L,
+ 0x528EF88AB6AC0A0DL, 0xA09EA253597BE3FFL,
+ 0x430DDFB3AC48CD56L, 0xC4B3A67AF45CE46FL,
+ 0x4ECECFD8FBE2D05EL, 0x3EF56F10B39935F0L,
+ 0x0B22D6829CD619C6L, 0x17FD460A74DF2069L,
+ 0x6CF8CC8E8510ED40L, 0xD6C824BF3A6ECAA7L,
+ 0x61243D581A817049L, 0x048BACB6BBC163A2L,
+ 0xD9A38AC27D44CC32L, 0x7FDDFF5BAAF410ABL,
+ 0xAD6D495AA804824BL, 0xE1A6A74F2D8C9F94L,
+ 0xD4F7851235DEE8E3L, 0xFD4B7F886540D893L,
+ 0x247C20042AA4BFDAL, 0x096EA1C517D1327CL,
+ 0xD56966B4361A6685L, 0x277DA5C31221057DL,
+ 0x94D59893A43ACFF7L, 0x64F0C51CCDC02281L,
+ 0x3D33BCC4FF6189DBL, 0xE005CB184CE66AF1L,
+ 0xFF5CCD1D1DB99BEAL, 0xB0B854A7FE42980FL,
+ 0x7BD46A6A718D4B9FL, 0xD10FA8CC22A5FD8CL,
+ 0xD31484952BE4BD31L, 0xC7FA975FCB243847L,
+ 0x4886ED1E5846C407L, 0x28CDDB791EB70B04L,
+ 0xC2B00BE2F573417FL, 0x5C9590452180F877L,
+ 0x7A6BDDFFF370EB00L, 0xCE509E38D6D9D6A4L,
+ 0xEBEB0F00647FA702L, 0x1DCC06CF76606F06L,
+ 0xE4D9F28BA286FF0AL, 0xD85A305DC918C262L,
+ 0x475B1D8732225F54L, 0x2D4FB51668CCB5FEL,
+ 0xA679B9D9D72BBA20L, 0x53841C0D912D43A5L,
+ 0x3B7EAA48BF12A4E8L, 0x781E0E47F22F1DDFL,
+ 0xEFF20CE60AB50973L, 0x20D261D19DFFB742L,
+ 0x16A12B03062A2E39L, 0x1960EB2239650495L,
+ 0x251C16FED50EB8B8L, 0x9AC0C330F826016EL,
+ 0xED152665953E7671L, 0x02D63194A6369570L,
+ 0x5074F08394B1C987L, 0x70BA598C90B25CE1L,
+ 0x794A15810B9742F6L, 0x0D5925E9FCAF8C6CL,
+ 0x3067716CD868744EL, 0x910AB077E8D7731BL,
+ 0x6A61BBDB5AC42F61L, 0x93513EFBF0851567L,
+ 0xF494724B9E83E9D5L, 0xE887E1985C09648DL,
+ 0x34B1D3C675370CFDL, 0xDC35E433BC0D255DL,
+ 0xD0AAB84234131BE0L, 0x08042A50B48B7EAFL,
+ 0x9997C4EE44A3AB35L, 0x829A7B49201799D0L,
+ 0x263B8307B7C54441L, 0x752F95F4FD6A6CA6L,
+ 0x927217402C08C6E5L, 0x2A8AB754A795D9EEL,
+ 0xA442F7552F72943DL, 0x2C31334E19781208L,
+ 0x4FA98D7CEAEE6291L, 0x55C3862F665DB309L,
+ 0xBD0610175D53B1F3L, 0x46FE6CB840413F27L,
+ 0x3FE03792DF0CFA59L, 0xCFE700372EB85E8FL,
+ 0xA7BE29E7ADBCE118L, 0xE544EE5CDE8431DDL,
+ 0x8A781B1B41F1873EL, 0xA5C94C78A0D2F0E7L,
+ 0x39412E2877B60728L, 0xA1265EF3AFC9A62CL,
+ 0xBCC2770C6A2506C5L, 0x3AB66DD5DCE1CE12L,
+ 0xE65499D04A675B37L, 0x7D8F523481BFD216L,
+ 0x0F6F64FCEC15F389L, 0x74EFBE618B5B13C8L,
+ 0xACDC82B714273E1DL, 0xDD40BFE003199D17L,
+ 0x37E99257E7E061F8L, 0xFA52626904775AAAL,
+ 0x8BBBF63A463D56F9L, 0xF0013F1543A26E64L,
+ 0xA8307E9F879EC898L, 0xCC4C27A4150177CCL,
+ 0x1B432F2CCA1D3348L, 0xDE1D1F8F9F6FA013L,
+ 0x606602A047A7DDD6L, 0xD237AB64CC1CB2C7L,
+ 0x9B938E7225FCD1D3L, 0xEC4E03708E0FF476L,
+ 0xFEB2FBDA3D03C12DL, 0xAE0BCED2EE43889AL,
+ 0x22CB8923EBFB4F43L, 0x69360D013CF7396DL,
+ 0x855E3602D2D4E022L, 0x073805BAD01F784CL,
+ 0x33E17A133852F546L, 0xDF4874058AC7B638L,
+ 0xBA92B29C678AA14AL, 0x0CE89FC76CFAADCDL,
+ 0x5F9D4E0908339E34L, 0xF1AFE9291F5923B9L,
+ 0x6E3480F60F4A265FL, 0xEEBF3A2AB29B841CL,
+ 0xE21938A88F91B4ADL, 0x57DFEFF845C6D3C3L,
+ 0x2F006B0BF62CAAF2L, 0x62F479EF6F75EE78L,
+ 0x11A55AD41C8916A9L, 0xF229D29084FED453L,
+ 0x42F1C27B16B000E6L, 0x2B1F76749823C074L,
+ 0x4B76ECA3C2745360L, 0x8C98F463B91691BDL,
+ 0x14BCC93CF1ADE66AL, 0x8885213E6D458397L,
+ 0x8E177DF0274D4711L, 0xB49B73B5503F2951L,
+ 0x10168168C3F96B6BL, 0x0E3D963B63CAB0AEL,
+ 0x8DFC4B5655A1DB14L, 0xF789F1356E14DE5CL,
+ 0x683E68AF4E51DAC1L, 0xC9A84F9D8D4B0FD9L,
+ 0x3691E03F52A0F9D1L, 0x5ED86E46E1878E80L,
+ 0x3C711A0E99D07150L, 0x5A0865B20C4E9310L,
+ 0x56FBFC1FE4F0682EL, 0xEA8D5DE3105EDF9BL,
+ 0x71ABFDB12379187AL, 0x2EB99DE1BEE77B9CL,
+ 0x21ECC0EA33CF4523L, 0x59A4D7521805C7A1L,
+ 0x3896F5EB56AE7C72L, 0xAA638F3DB18F75DCL,
+ 0x9F39358DABE9808EL, 0xB7DEFA91C00B72ACL,
+ 0x6B5541FD62492D92L, 0x6DC6DEE8F92E4D5BL,
+ 0x353F57ABC4BEEA7EL, 0x735769D6DA5690CEL,
+ 0x0A234AA642391484L, 0xF6F9508028F80D9DL,
+ 0xB8E319A27AB3F215L, 0x31AD9C1151341A4DL,
+ 0x773C22A57BEF5805L, 0x45C7561A07968633L,
+ 0xF913DA9E249DBE36L, 0xDA652D9B78A64C68L,
+ 0x4C27A97F3BC334EFL, 0x76621220E66B17F4L,
+ 0x967743899ACD7D0BL, 0xF3EE5BCAE0ED6782L,
+ 0x409F753600C879FCL, 0x06D09A39B5926DB6L,
+ 0x6F83AEB0317AC588L, 0x01E6CA4A86381F21L,
+ 0x66FF3462D19F3025L, 0x72207C24DDFD3BFBL,
+ 0x4AF6B6D3E2ECE2EBL, 0x9C994DBEC7EA08DEL,
+ 0x49ACE597B09A8BC4L, 0xB38C4766CF0797BAL,
+ 0x131B9373C57C2A75L, 0xB1822CCE61931E58L,
+ 0x9D7555B909BA1C0CL, 0x127FAFDD937D11D2L,
+ 0x29DA3BADC66D92E4L, 0xA2C1D57154C2ECBCL,
+ 0x58C5134D82F6FE24L, 0x1C3AE3515B62274FL,
+ 0xE907C82E01CB8126L, 0xF8ED091913E37FCBL,
+ 0x3249D8F9C80046C9L, 0x80CF9BEDE388FB63L,
+ 0x1881539A116CF19EL, 0x5103F3F76BD52457L,
+ 0x15B7E6F5AE47F7A8L, 0xDBD7C6DED47E9CCFL,
+ 0x44E55C410228BB1AL, 0xB647D4255EDB4E99L,
+ 0x5D11882BB8AAFC30L, 0xF5098BBB29D3212AL,
+ 0x8FB5EA14E90296B3L, 0x677B942157DD025AL,
+ 0xFB58E7C0A390ACB5L, 0x89D3674C83BD4A01L,
+ 0x9E2DA4DF4BF3B93BL, 0xFCC41E328CAB4829L,
+ 0x03F38C96BA582C52L, 0xCAD1BDBD7FD85DB2L,
+ 0xBBB442C16082AE83L, 0xB95FE86BA5DA9AB0L,
+ 0xB22E04673771A93FL, 0x845358C9493152D8L,
+ 0xBE2A488697B4541EL, 0x95A2DC2DD38E6966L,
+ 0xC02C11AC923C852BL, 0x2388B1990DF2A87BL,
+ 0x7C8008FA1B4F37BEL, 0x1F70D0C84D54E503L,
+ 0x5490ADEC7ECE57D4L, 0x002B3C27D9063A3AL,
+ 0x7EAEA3848030A2BFL, 0xC602326DED2003C0L,
+ 0x83A7287D69A94086L, 0xC57A5FCB30F57A8AL,
+ 0xB56844E479EBE779L, 0xA373B40F05DCBCE9L,
+ 0xD71A786E88570EE2L, 0x879CBACDBDE8F6A0L,
+ 0x976AD1BCC164A32FL, 0xAB21E25E9666D78BL,
+ 0x901063AAE5E5C33CL, 0x9818B34448698D90L,
+ 0xE36487AE3E1E8ABBL, 0xAFBDF931893BDCB4L,
+ 0x6345A0DC5FBBD519L, 0x8628FE269B9465CAL,
+ 0x1E5D01603F9C51ECL, 0x4DE44006A15049B7L,
+ 0xBF6C70E5F776CBB1L, 0x411218F2EF552BEDL,
+ 0xCB0C0708705A36A3L, 0xE74D14754F986044L,
+ 0xCD56D9430EA8280EL, 0xC12591D7535F5065L,
+ 0xC83223F1720AEF96L, 0xC3A0396F7363A51FL };
+
+ // The cached self-test result.
+ private static Boolean valid;
+
+ // The context.
+ private long a, b, c;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Trivial 0-arguments constructor.
+ */
+ public Tiger()
+ {
+ super(Registry.TIGER_HASH, HASH_SIZE, BLOCK_SIZE);
+ }
+
+ /**
+ * Private copying constructor for cloning.
+ *
+ * @param that The instance being cloned.
+ */
+ private Tiger(Tiger that)
+ {
+ this();
+ this.a = that.a;
+ this.b = that.b;
+ this.c = that.c;
+ this.count = that.count;
+ this.buffer = (that.buffer != null) ? (byte[]) that.buffer.clone() : null;
+ }
+
+ // Instance methods implementing BaseHash.
+ // -----------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new Tiger(this);
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new Tiger().digest())));
+ }
+ return valid.booleanValue();
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] pad = new byte[padding + 8];
+
+ pad[0] = 1;
+ long bits = count << 3;
+
+ pad[padding++] = (byte) bits;
+ pad[padding++] = (byte) (bits >>> 8);
+ pad[padding++] = (byte) (bits >>> 16);
+ pad[padding++] = (byte) (bits >>> 24);
+ pad[padding++] = (byte) (bits >>> 32);
+ pad[padding++] = (byte) (bits >>> 40);
+ pad[padding++] = (byte) (bits >>> 48);
+ pad[padding] = (byte) (bits >>> 56);
+
+ return pad;
+ }
+
+ protected byte[] getResult()
+ {
+ return new byte[] { (byte) a, (byte) (a >>> 8), (byte) (a >>> 16),
+ (byte) (a >>> 24), (byte) (a >>> 32), (byte) (a >>> 40),
+ (byte) (a >>> 48), (byte) (a >>> 56), (byte) b,
+ (byte) (b >>> 8), (byte) (b >>> 16), (byte) (b >>> 24),
+ (byte) (b >>> 32), (byte) (b >>> 40), (byte) (b >>> 48),
+ (byte) (b >>> 56), (byte) c, (byte) (c >>> 8),
+ (byte) (c >>> 16), (byte) (c >>> 24), (byte) (c >>> 32),
+ (byte) (c >>> 40), (byte) (c >>> 48), (byte) (c >>> 56) };
+ }
+
+ protected void resetContext()
+ {
+ a = A;
+ b = B;
+ c = C;
+ }
+
+ protected void transform(byte[] in, int offset)
+ {
+ long x0, x1, x2, x3, x4, x5, x6, x7;
+
+ x0 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x1 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x2 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x3 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x4 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x5 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x6 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x7 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset] & 0xFF) << 56);
+
+ // save_abc ::=
+ long aa = a, bb = b, cc = c;
+
+ // pass(aa, bb, cc, 5) ::=
+ cc ^= x0;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 5;
+ aa ^= x1;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 5;
+ bb ^= x2;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 5;
+ cc ^= x3;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 5;
+ aa ^= x4;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 5;
+ bb ^= x5;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 5;
+ cc ^= x6;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 5;
+ aa ^= x7;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 5;
+
+ // key_schedule ::=
+ x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5L;
+ x1 ^= x0;
+ x2 += x1;
+ x3 -= x2 ^ ((~x1) << 19);
+ x4 ^= x3;
+ x5 += x4;
+ x6 -= x5 ^ ((~x4) >>> 23);
+ x7 ^= x6;
+ x0 += x7;
+ x1 -= x0 ^ ((~x7) << 19);
+ x2 ^= x1;
+ x3 += x2;
+ x4 -= x3 ^ ((~x2) >>> 23);
+ x5 ^= x4;
+ x6 += x5;
+ x7 -= x6 ^ 0x0123456789ABCDEFL;
+
+ // pass(cc, aa, bb, 7) ::=
+ bb ^= x0;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 7;
+ cc ^= x1;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 7;
+ aa ^= x2;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 7;
+ bb ^= x3;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 7;
+ cc ^= x4;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 7;
+ aa ^= x5;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 7;
+ bb ^= x6;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 7;
+ cc ^= x7;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 7;
+
+ // key_schedule ::=
+ x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5L;
+ x1 ^= x0;
+ x2 += x1;
+ x3 -= x2 ^ ((~x1) << 19);
+ x4 ^= x3;
+ x5 += x4;
+ x6 -= x5 ^ ((~x4) >>> 23);
+ x7 ^= x6;
+ x0 += x7;
+ x1 -= x0 ^ ((~x7) << 19);
+ x2 ^= x1;
+ x3 += x2;
+ x4 -= x3 ^ ((~x2) >>> 23);
+ x5 ^= x4;
+ x6 += x5;
+ x7 -= x6 ^ 0x0123456789ABCDEFL;
+
+ // pass(bb,cc,aa,9) ::=
+ aa ^= x0;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 9;
+ bb ^= x1;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 9;
+ cc ^= x2;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 9;
+ aa ^= x3;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 9;
+ bb ^= x4;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 9;
+ cc ^= x5;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 9;
+ aa ^= x6;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 9;
+ bb ^= x7;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 9;
+
+ // feedforward ::=
+ a ^= aa;
+ b = bb - b;
+ c += cc;
+ }
+}
diff --git a/gnu/java/security/hash/Whirlpool.java b/gnu/java/security/hash/Whirlpool.java
new file mode 100644
index 000000000..8c5d9f360
--- /dev/null
+++ b/gnu/java/security/hash/Whirlpool.java
@@ -0,0 +1,626 @@
+/* Whirlpool.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>Whirlpool, a new 512-bit hashing function operating on messages less than
+ * 2 ** 256 bits in length. The function structure is designed according to the
+ * Wide Trail strategy and permits a wide variety of implementation trade-offs.
+ * </p>
+ *
+ * <p><b>IMPORTANT</b>: This implementation is not thread-safe.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html">
+ * The WHIRLPOOL Hashing Function</a>.<br>
+ * <a href="mailto:paulo.barreto@terra.com.br">Paulo S.L.M. Barreto</a> and
+ * <a href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a>.</li>
+ * </ol>
+ */
+public final class Whirlpool extends BaseHash
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 3;
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ /** The digest of the 0-bit long message. */
+ private static final String DIGEST0 = "470F0409ABAA446E49667D4EBE12A14387CEDBD10DD17B8243CAD550A089DC0F"
+ + "EEA7AA40F6C2AAAB71C6EBD076E43C7CFCA0AD32567897DCB5969861049A0F5A";
+
+ private static final int R = 10; // default number of rounds
+
+ private static final String Sd = // p. 19 [WHIRLPOOL]
+ "\u1823\uc6E8\u87B8\u014F\u36A6\ud2F5\u796F\u9152"
+ + "\u60Bc\u9B8E\uA30c\u7B35\u1dE0\ud7c2\u2E4B\uFE57"
+ + "\u1577\u37E5\u9FF0\u4AdA\u58c9\u290A\uB1A0\u6B85"
+ + "\uBd5d\u10F4\ucB3E\u0567\uE427\u418B\uA77d\u95d8"
+ + "\uFBEE\u7c66\udd17\u479E\ucA2d\uBF07\uAd5A\u8333"
+ + "\u6302\uAA71\uc819\u49d9\uF2E3\u5B88\u9A26\u32B0"
+ + "\uE90F\ud580\uBEcd\u3448\uFF7A\u905F\u2068\u1AAE"
+ + "\uB454\u9322\u64F1\u7312\u4008\uc3Ec\udBA1\u8d3d"
+ + "\u9700\ucF2B\u7682\ud61B\uB5AF\u6A50\u45F3\u30EF"
+ + "\u3F55\uA2EA\u65BA\u2Fc0\udE1c\uFd4d\u9275\u068A"
+ + "\uB2E6\u0E1F\u62d4\uA896\uF9c5\u2559\u8472\u394c"
+ + "\u5E78\u388c\ud1A5\uE261\uB321\u9c1E\u43c7\uFc04"
+ + "\u5199\u6d0d\uFAdF\u7E24\u3BAB\ucE11\u8F4E\uB7EB"
+ + "\u3c81\u94F7\uB913\u2cd3\uE76E\uc403\u5644\u7FA9"
+ + "\u2ABB\uc153\udc0B\u9d6c\u3174\uF646\uAc89\u14E1"
+ + "\u163A\u6909\u70B6\ud0Ed\ucc42\u98A4\u285c\uF886";
+
+ private static final long[] T0 = new long[256];
+
+ private static final long[] T1 = new long[256];
+
+ private static final long[] T2 = new long[256];
+
+ private static final long[] T3 = new long[256];
+
+ private static final long[] T4 = new long[256];
+
+ private static final long[] T5 = new long[256];
+
+ private static final long[] T6 = new long[256];
+
+ private static final long[] T7 = new long[256];
+
+ private static final long[] rc = new long[R];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** The 512-bit context as 8 longs. */
+ private long H0, H1, H2, H3, H4, H5, H6, H7;
+
+ /** Work area for computing the round key schedule. */
+ private long k00, k01, k02, k03, k04, k05, k06, k07;
+
+ private long Kr0, Kr1, Kr2, Kr3, Kr4, Kr5, Kr6, Kr7;
+
+ /** work area for transforming the 512-bit buffer. */
+ private long n0, n1, n2, n3, n4, n5, n6, n7;
+
+ private long nn0, nn1, nn2, nn3, nn4, nn5, nn6, nn7;
+
+ /** work area for holding block cipher's intermediate values. */
+ private long w0, w1, w2, w3, w4, w5, w6, w7;
+
+ // Static code - to intialise lookup tables --------------------------------
+
+ static
+ {
+ long time = System.currentTimeMillis();
+
+ int ROOT = 0x11d; // para. 2.1 [WHIRLPOOL]
+ int i, r, j;
+ long s, s2, s3, s4, s5, s8, s9, t;
+ char c;
+ final byte[] S = new byte[256];
+ for (i = 0; i < 256; i++)
+ {
+ c = Sd.charAt(i >>> 1);
+
+ s = ((i & 1) == 0 ? c >>> 8 : c) & 0xFFL;
+ s2 = s << 1;
+ if (s2 > 0xFFL)
+ {
+ s2 ^= ROOT;
+ }
+ s3 = s2 ^ s;
+ s4 = s2 << 1;
+ if (s4 > 0xFFL)
+ {
+ s4 ^= ROOT;
+ }
+ s5 = s4 ^ s;
+ s8 = s4 << 1;
+ if (s8 > 0xFFL)
+ {
+ s8 ^= ROOT;
+ }
+ s9 = s8 ^ s;
+
+ S[i] = (byte) s;
+ T0[i] = t = s << 56 | s << 48 | s3 << 40 | s << 32 | s5 << 24
+ | s8 << 16 | s9 << 8 | s5;
+ T1[i] = t >>> 8 | t << 56;
+ T2[i] = t >>> 16 | t << 48;
+ T3[i] = t >>> 24 | t << 40;
+ T4[i] = t >>> 32 | t << 32;
+ T5[i] = t >>> 40 | t << 24;
+ T6[i] = t >>> 48 | t << 16;
+ T7[i] = t >>> 56 | t << 8;
+ }
+
+ for (r = 1, i = 0, j = 0; r < R + 1; r++)
+ {
+ rc[i++] = (S[j++] & 0xFFL) << 56 | (S[j++] & 0xFFL) << 48
+ | (S[j++] & 0xFFL) << 40 | (S[j++] & 0xFFL) << 32
+ | (S[j++] & 0xFFL) << 24 | (S[j++] & 0xFFL) << 16
+ | (S[j++] & 0xFFL) << 8 | (S[j++] & 0xFFL);
+ }
+
+ time = System.currentTimeMillis() - time;
+
+ if (DEBUG && debuglevel > 8)
+ {
+ System.out.println("==========");
+ System.out.println();
+ System.out.println("Static data");
+ System.out.println();
+
+ System.out.println();
+ System.out.println("T0[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T0[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T1[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T1[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T2[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T2[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T3[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T3[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T4[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T4[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T5[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T5[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T6[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T5[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T7[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T5[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("rc[]:");
+ for (i = 0; i < R; i++)
+ {
+ System.out.println("0x" + Util.toString(rc[i]));
+ }
+ System.out.println();
+
+ System.out.println();
+ System.out.println("Total initialization time: " + time + " ms.");
+ System.out.println();
+ }
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Whirlpool()
+ {
+ super(Registry.WHIRLPOOL_HASH, 20, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Whirlpool(Whirlpool md)
+ {
+ this();
+
+ this.H0 = md.H0;
+ this.H1 = md.H1;
+ this.H2 = md.H2;
+ this.H3 = md.H3;
+ this.H4 = md.H4;
+ this.H5 = md.H5;
+ this.H6 = md.H6;
+ this.H7 = md.H7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return (new Whirlpool(this));
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ // apply mu to the input
+ n0 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n1 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n2 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n3 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n4 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n5 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n6 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n7 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+
+ // transform K into the key schedule Kr; 0 <= r <= R
+ k00 = H0;
+ k01 = H1;
+ k02 = H2;
+ k03 = H3;
+ k04 = H4;
+ k05 = H5;
+ k06 = H6;
+ k07 = H7;
+
+ nn0 = n0 ^ k00;
+ nn1 = n1 ^ k01;
+ nn2 = n2 ^ k02;
+ nn3 = n3 ^ k03;
+ nn4 = n4 ^ k04;
+ nn5 = n5 ^ k05;
+ nn6 = n6 ^ k06;
+ nn7 = n7 ^ k07;
+
+ // intermediate cipher output
+ w0 = w1 = w2 = w3 = w4 = w5 = w6 = w7 = 0L;
+
+ for (int r = 0; r < R; r++)
+ {
+ // 1. compute intermediate round key schedule by applying ro[rc]
+ // to the previous round key schedule --rc being the round constant
+ Kr0 = T0[(int) ((k00 >> 56) & 0xFFL)] ^ T1[(int) ((k07 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k06 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k05 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k04 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k03 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k02 >> 8) & 0xFFL)] ^ T7[(int) (k01 & 0xFFL)]
+ ^ rc[r];
+
+ Kr1 = T0[(int) ((k01 >> 56) & 0xFFL)] ^ T1[(int) ((k00 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k07 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k06 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k05 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k04 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k03 >> 8) & 0xFFL)] ^ T7[(int) (k02 & 0xFFL)];
+
+ Kr2 = T0[(int) ((k02 >> 56) & 0xFFL)] ^ T1[(int) ((k01 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k00 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k07 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k06 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k05 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k04 >> 8) & 0xFFL)] ^ T7[(int) (k03 & 0xFFL)];
+
+ Kr3 = T0[(int) ((k03 >> 56) & 0xFFL)] ^ T1[(int) ((k02 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k01 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k00 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k07 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k06 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k05 >> 8) & 0xFFL)] ^ T7[(int) (k04 & 0xFFL)];
+
+ Kr4 = T0[(int) ((k04 >> 56) & 0xFFL)] ^ T1[(int) ((k03 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k02 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k01 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k00 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k07 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k06 >> 8) & 0xFFL)] ^ T7[(int) (k05 & 0xFFL)];
+
+ Kr5 = T0[(int) ((k05 >> 56) & 0xFFL)] ^ T1[(int) ((k04 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k03 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k02 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k01 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k00 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k07 >> 8) & 0xFFL)] ^ T7[(int) (k06 & 0xFFL)];
+
+ Kr6 = T0[(int) ((k06 >> 56) & 0xFFL)] ^ T1[(int) ((k05 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k04 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k03 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k02 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k01 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k00 >> 8) & 0xFFL)] ^ T7[(int) (k07 & 0xFFL)];
+
+ Kr7 = T0[(int) ((k07 >> 56) & 0xFFL)] ^ T1[(int) ((k06 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k05 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k04 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k03 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k02 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k01 >> 8) & 0xFFL)] ^ T7[(int) (k00 & 0xFFL)];
+
+ k00 = Kr0;
+ k01 = Kr1;
+ k02 = Kr2;
+ k03 = Kr3;
+ k04 = Kr4;
+ k05 = Kr5;
+ k06 = Kr6;
+ k07 = Kr7;
+
+ // 2. incrementally compute the cipher output
+ w0 = T0[(int) ((nn0 >> 56) & 0xFFL)] ^ T1[(int) ((nn7 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn6 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn5 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn4 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn3 >> 16) & 0xFFL)] ^ T6[(int) ((nn2 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn1 & 0xFFL)] ^ Kr0;
+ w1 = T0[(int) ((nn1 >> 56) & 0xFFL)] ^ T1[(int) ((nn0 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn7 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn6 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn5 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn4 >> 16) & 0xFFL)] ^ T6[(int) ((nn3 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn2 & 0xFFL)] ^ Kr1;
+ w2 = T0[(int) ((nn2 >> 56) & 0xFFL)] ^ T1[(int) ((nn1 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn0 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn7 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn6 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn5 >> 16) & 0xFFL)] ^ T6[(int) ((nn4 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn3 & 0xFFL)] ^ Kr2;
+ w3 = T0[(int) ((nn3 >> 56) & 0xFFL)] ^ T1[(int) ((nn2 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn1 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn0 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn7 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn6 >> 16) & 0xFFL)] ^ T6[(int) ((nn5 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn4 & 0xFFL)] ^ Kr3;
+ w4 = T0[(int) ((nn4 >> 56) & 0xFFL)] ^ T1[(int) ((nn3 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn2 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn1 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn0 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn7 >> 16) & 0xFFL)] ^ T6[(int) ((nn6 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn5 & 0xFFL)] ^ Kr4;
+ w5 = T0[(int) ((nn5 >> 56) & 0xFFL)] ^ T1[(int) ((nn4 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn3 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn2 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn1 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn0 >> 16) & 0xFFL)] ^ T6[(int) ((nn7 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn6 & 0xFFL)] ^ Kr5;
+ w6 = T0[(int) ((nn6 >> 56) & 0xFFL)] ^ T1[(int) ((nn5 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn4 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn3 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn2 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn1 >> 16) & 0xFFL)] ^ T6[(int) ((nn0 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn7 & 0xFFL)] ^ Kr6;
+ w7 = T0[(int) ((nn7 >> 56) & 0xFFL)] ^ T1[(int) ((nn6 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn5 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn4 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn3 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn2 >> 16) & 0xFFL)] ^ T6[(int) ((nn1 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn0 & 0xFFL)] ^ Kr7;
+
+ nn0 = w0;
+ nn1 = w1;
+ nn2 = w2;
+ nn3 = w3;
+ nn4 = w4;
+ nn5 = w5;
+ nn6 = w6;
+ nn7 = w7;
+ }
+
+ // apply the Miyaguchi-Preneel hash scheme
+ H0 ^= w0 ^ n0;
+ H1 ^= w1 ^ n1;
+ H2 ^= w2 ^ n2;
+ H3 ^= w3 ^ n3;
+ H4 ^= w4 ^ n4;
+ H5 ^= w5 ^ n5;
+ H6 ^= w6 ^ n6;
+ H7 ^= w7 ^ n7;
+ }
+
+ protected byte[] padBuffer()
+ {
+ // [WHIRLPOOL] p. 6:
+ // "...padded with a 1-bit, then with as few 0-bits as necessary to
+ // obtain a bit string whose length is an odd multiple of 256, and
+ // finally with the 256-bit right-justified binary representation of L."
+ // in this implementation we use 'count' as the number of bytes hashed
+ // so far. hence the minimal number of bytes added to the message proper
+ // are 33 (1 for the 1-bit followed by the 0-bits and the encoding of
+ // the count framed in a 256-bit block). our formula is then:
+ // count + 33 + padding = 0 (mod BLOCK_SIZE)
+ int n = (int) ((count + 33) % BLOCK_SIZE);
+ int padding = n == 0 ? 33 : BLOCK_SIZE - n + 33;
+
+ byte[] result = new byte[padding];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save (right justified) the number of bits hashed
+ long bits = count * 8;
+ int i = padding - 8;
+ result[i++] = (byte) (bits >>> 56);
+ result[i++] = (byte) (bits >>> 48);
+ result[i++] = (byte) (bits >>> 40);
+ result[i++] = (byte) (bits >>> 32);
+ result[i++] = (byte) (bits >>> 24);
+ result[i++] = (byte) (bits >>> 16);
+ result[i++] = (byte) (bits >>> 8);
+ result[i] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ // apply inverse mu to the context
+ byte[] result = new byte[] { (byte) (H0 >>> 56), (byte) (H0 >>> 48),
+ (byte) (H0 >>> 40), (byte) (H0 >>> 32),
+ (byte) (H0 >>> 24), (byte) (H0 >>> 16),
+ (byte) (H0 >>> 8), (byte) H0,
+ (byte) (H1 >>> 56), (byte) (H1 >>> 48),
+ (byte) (H1 >>> 40), (byte) (H1 >>> 32),
+ (byte) (H1 >>> 24), (byte) (H1 >>> 16),
+ (byte) (H1 >>> 8), (byte) H1,
+ (byte) (H2 >>> 56), (byte) (H2 >>> 48),
+ (byte) (H2 >>> 40), (byte) (H2 >>> 32),
+ (byte) (H2 >>> 24), (byte) (H2 >>> 16),
+ (byte) (H2 >>> 8), (byte) H2,
+ (byte) (H3 >>> 56), (byte) (H3 >>> 48),
+ (byte) (H3 >>> 40), (byte) (H3 >>> 32),
+ (byte) (H3 >>> 24), (byte) (H3 >>> 16),
+ (byte) (H3 >>> 8), (byte) H3,
+ (byte) (H4 >>> 56), (byte) (H4 >>> 48),
+ (byte) (H4 >>> 40), (byte) (H4 >>> 32),
+ (byte) (H4 >>> 24), (byte) (H4 >>> 16),
+ (byte) (H4 >>> 8), (byte) H4,
+ (byte) (H5 >>> 56), (byte) (H5 >>> 48),
+ (byte) (H5 >>> 40), (byte) (H5 >>> 32),
+ (byte) (H5 >>> 24), (byte) (H5 >>> 16),
+ (byte) (H5 >>> 8), (byte) H5,
+ (byte) (H6 >>> 56), (byte) (H6 >>> 48),
+ (byte) (H6 >>> 40), (byte) (H6 >>> 32),
+ (byte) (H6 >>> 24), (byte) (H6 >>> 16),
+ (byte) (H6 >>> 8), (byte) H6,
+ (byte) (H7 >>> 56), (byte) (H7 >>> 48),
+ (byte) (H7 >>> 40), (byte) (H7 >>> 32),
+ (byte) (H7 >>> 24), (byte) (H7 >>> 16),
+ (byte) (H7 >>> 8), (byte) H7 };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ H0 = H1 = H2 = H3 = H4 = H5 = H6 = H7 = 0L;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(
+ DIGEST0.equals(Util.toString(new Whirlpool().digest())));
+ }
+ return valid.booleanValue();
+ }
+}
diff --git a/gnu/java/security/jce/hash/HavalSpi.java b/gnu/java/security/jce/hash/HavalSpi.java
new file mode 100644
index 000000000..e127779ef
--- /dev/null
+++ b/gnu/java/security/jce/hash/HavalSpi.java
@@ -0,0 +1,68 @@
+/* HavalSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the <code>HAVAL</code> <i>Service Provider Interface</i>
+ * (<b>SPI</b>) Adapter.<p>
+ *
+ * @version Revision: $
+ */
+public class HavalSpi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public HavalSpi()
+ {
+ super(Registry.HAVAL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/MD2Spi.java b/gnu/java/security/jce/hash/MD2Spi.java
new file mode 100644
index 000000000..5b6b0e1e1
--- /dev/null
+++ b/gnu/java/security/jce/hash/MD2Spi.java
@@ -0,0 +1,69 @@
+/* MD2Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the MD2 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class MD2Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public MD2Spi()
+ {
+ super(Registry.MD2_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/MD4Spi.java b/gnu/java/security/jce/hash/MD4Spi.java
new file mode 100644
index 000000000..8be449934
--- /dev/null
+++ b/gnu/java/security/jce/hash/MD4Spi.java
@@ -0,0 +1,69 @@
+/* MD4Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the MD4 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class MD4Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public MD4Spi()
+ {
+ super(Registry.MD4_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/MD5Spi.java b/gnu/java/security/jce/hash/MD5Spi.java
new file mode 100644
index 000000000..92fb6ab38
--- /dev/null
+++ b/gnu/java/security/jce/hash/MD5Spi.java
@@ -0,0 +1,68 @@
+/* MD5Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the MD5 <i>Service Provider Interface</i> (<b>SPI</b>)
+ * adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class MD5Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public MD5Spi()
+ {
+ super(Registry.MD5_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/MessageDigestAdapter.java b/gnu/java/security/jce/hash/MessageDigestAdapter.java
new file mode 100644
index 000000000..9b8a73d55
--- /dev/null
+++ b/gnu/java/security/jce/hash/MessageDigestAdapter.java
@@ -0,0 +1,147 @@
+/* MessageDigestAdapter.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.hash.HashFactory;
+
+import java.security.DigestException;
+import java.security.MessageDigestSpi;
+
+/**
+ * The implementation of a generic {@link java.security.MessageDigest} adapter
+ * class to wrap gnu.crypto hash instances.<p>
+ *
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
+ * {@link java.security.MessageDigest} class, which provides the functionality
+ * of a message digest algorithm, such as MD5 or SHA. Message digests are secure
+ * one-way hash functions that take arbitrary-sized data and output a fixed-
+ * length hash value.<p>
+ *
+ * All the abstract methods in the {@link java.security.MessageDigestSpi} class
+ * are implemented by this class and all its sub-classes.<p>
+ *
+ * All the implementations which subclass this object, and which are serviced by
+ * the GNU Crypto provider implement the {@link java.lang.Cloneable} interface.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+class MessageDigestAdapter extends MessageDigestSpi implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying hash instance. */
+ private IMessageDigest adaptee;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial protected constructor.
+ *
+ * @param mdName the canonical name of the hash algorithm.
+ */
+ protected MessageDigestAdapter(String mdName)
+ {
+ this(HashFactory.getInstance(mdName));
+ }
+
+ /**
+ * Private constructor for cloning purposes.
+ *
+ * @param adaptee a clone of the underlying hash algorithm instance.
+ */
+ private MessageDigestAdapter(IMessageDigest adaptee)
+ {
+ super();
+
+ this.adaptee = adaptee;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // java.security.MessageDigestSpi interface implementation
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new MessageDigestAdapter((IMessageDigest) adaptee.clone());
+ }
+
+ public int engineGetDigestLength()
+ {
+ return adaptee.hashSize();
+ }
+
+ public void engineUpdate(byte input)
+ {
+ adaptee.update(input);
+ }
+
+ public void engineUpdate(byte[] input, int offset, int len)
+ {
+ adaptee.update(input, offset, len);
+ }
+
+ public byte[] engineDigest()
+ {
+ return adaptee.digest();
+ }
+
+ public int engineDigest(byte[] buf, int offset, int len)
+ throws DigestException
+ {
+ int result = adaptee.hashSize();
+ if (len < result)
+ {
+ throw new DigestException();
+ }
+ byte[] md = adaptee.digest();
+ System.arraycopy(md, 0, buf, offset, result);
+ return result;
+ }
+
+ public void engineReset()
+ {
+ adaptee.reset();
+ }
+}
diff --git a/gnu/java/security/jce/hash/RipeMD128Spi.java b/gnu/java/security/jce/hash/RipeMD128Spi.java
new file mode 100644
index 000000000..b8e90d4bf
--- /dev/null
+++ b/gnu/java/security/jce/hash/RipeMD128Spi.java
@@ -0,0 +1,68 @@
+/* RipeMD128Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the RIPEMD-128 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RipeMD128Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RipeMD128Spi()
+ {
+ super(Registry.RIPEMD128_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/RipeMD160Spi.java b/gnu/java/security/jce/hash/RipeMD160Spi.java
new file mode 100644
index 000000000..49615e2fc
--- /dev/null
+++ b/gnu/java/security/jce/hash/RipeMD160Spi.java
@@ -0,0 +1,68 @@
+/* RipeMD160Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the RIPEMD-160 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RipeMD160Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RipeMD160Spi()
+ {
+ super(Registry.RIPEMD160_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/Sha160Spi.java b/gnu/java/security/jce/hash/Sha160Spi.java
new file mode 100644
index 000000000..a9b72634d
--- /dev/null
+++ b/gnu/java/security/jce/hash/Sha160Spi.java
@@ -0,0 +1,68 @@
+/* Sha160Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the SHA-1 (160-bit) <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Sha160Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha160Spi()
+ {
+ super(Registry.SHA160_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/Sha256Spi.java b/gnu/java/security/jce/hash/Sha256Spi.java
new file mode 100644
index 000000000..9eeaebdea
--- /dev/null
+++ b/gnu/java/security/jce/hash/Sha256Spi.java
@@ -0,0 +1,68 @@
+/* Sha256Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-2-1 (256-bit) <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Sha256Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha256Spi()
+ {
+ super(Registry.SHA256_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/Sha384Spi.java b/gnu/java/security/jce/hash/Sha384Spi.java
new file mode 100644
index 000000000..96e1e6eb0
--- /dev/null
+++ b/gnu/java/security/jce/hash/Sha384Spi.java
@@ -0,0 +1,68 @@
+/* Sha384Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-2-2 (384-bit) <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Sha384Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha384Spi()
+ {
+ super(Registry.SHA384_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/Sha512Spi.java b/gnu/java/security/jce/hash/Sha512Spi.java
new file mode 100644
index 000000000..75c617046
--- /dev/null
+++ b/gnu/java/security/jce/hash/Sha512Spi.java
@@ -0,0 +1,68 @@
+/* Sha512Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-2-3 (512-bit) <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Sha512Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha512Spi()
+ {
+ super(Registry.SHA512_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/TigerSpi.java b/gnu/java/security/jce/hash/TigerSpi.java
new file mode 100644
index 000000000..b355d78d0
--- /dev/null
+++ b/gnu/java/security/jce/hash/TigerSpi.java
@@ -0,0 +1,69 @@
+/* TigerSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the Tiger <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class TigerSpi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public TigerSpi()
+ {
+ super(Registry.TIGER_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/hash/WhirlpoolSpi.java b/gnu/java/security/jce/hash/WhirlpoolSpi.java
new file mode 100644
index 000000000..e42e74ddb
--- /dev/null
+++ b/gnu/java/security/jce/hash/WhirlpoolSpi.java
@@ -0,0 +1,68 @@
+/* WhirlpoolSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Whirlpool <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class WhirlpoolSpi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public WhirlpoolSpi()
+ {
+ super(Registry.WHIRLPOOL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/HavalRandomSpi.java b/gnu/java/security/jce/prng/HavalRandomSpi.java
new file mode 100644
index 000000000..0c39a37fd
--- /dev/null
+++ b/gnu/java/security/jce/prng/HavalRandomSpi.java
@@ -0,0 +1,66 @@
+/* HavalRandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HAVAL-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) Adapter.<p>
+ */
+public class HavalRandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public HavalRandomSpi()
+ {
+ super(Registry.HAVAL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/MD2RandomSpi.java b/gnu/java/security/jce/prng/MD2RandomSpi.java
new file mode 100644
index 000000000..72a7f4873
--- /dev/null
+++ b/gnu/java/security/jce/prng/MD2RandomSpi.java
@@ -0,0 +1,66 @@
+/* MD2RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the MD2-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class MD2RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public MD2RandomSpi()
+ {
+ super(Registry.MD2_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/MD4RandomSpi.java b/gnu/java/security/jce/prng/MD4RandomSpi.java
new file mode 100644
index 000000000..f5f98f8f3
--- /dev/null
+++ b/gnu/java/security/jce/prng/MD4RandomSpi.java
@@ -0,0 +1,66 @@
+/* MD4RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the MD4-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class MD4RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public MD4RandomSpi()
+ {
+ super(Registry.MD4_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/MD5RandomSpi.java b/gnu/java/security/jce/prng/MD5RandomSpi.java
new file mode 100644
index 000000000..0181247bc
--- /dev/null
+++ b/gnu/java/security/jce/prng/MD5RandomSpi.java
@@ -0,0 +1,66 @@
+/* MD5RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the MD5-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class MD5RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public MD5RandomSpi()
+ {
+ super(Registry.MD5_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/RipeMD128RandomSpi.java b/gnu/java/security/jce/prng/RipeMD128RandomSpi.java
new file mode 100644
index 000000000..5580716a4
--- /dev/null
+++ b/gnu/java/security/jce/prng/RipeMD128RandomSpi.java
@@ -0,0 +1,66 @@
+/* RipeMD128RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the RIPEMD128-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class RipeMD128RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RipeMD128RandomSpi()
+ {
+ super(Registry.RIPEMD128_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/RipeMD160RandomSpi.java b/gnu/java/security/jce/prng/RipeMD160RandomSpi.java
new file mode 100644
index 000000000..734fe824a
--- /dev/null
+++ b/gnu/java/security/jce/prng/RipeMD160RandomSpi.java
@@ -0,0 +1,66 @@
+/* RipeMD160RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the RIPEMD160-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class RipeMD160RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RipeMD160RandomSpi()
+ {
+ super(Registry.RIPEMD160_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/SecureRandomAdapter.java b/gnu/java/security/jce/prng/SecureRandomAdapter.java
new file mode 100644
index 000000000..e7cb72091
--- /dev/null
+++ b/gnu/java/security/jce/prng/SecureRandomAdapter.java
@@ -0,0 +1,126 @@
+/* SecureRandomAdapter.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.prng.MDGenerator;
+
+import java.security.SecureRandomSpi;
+import java.util.HashMap;
+
+/**
+ * <p>The implementation of a generic {@link java.security.SecureRandom} adapter
+ * class to wrap gnu.crypto prng instances based on Message Digest algorithms.</p>
+ *
+ * <p>This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
+ * the {@link java.security.SecureRandom} class, which provides the
+ * functionality of a cryptographically strong pseudo-random number generator.</p>
+ *
+ * <p>All the abstract methods in the {@link SecureRandomSpi} class are
+ * implemented by this class and all its sub-classes.</p>
+ */
+abstract class SecureRandomAdapter extends SecureRandomSpi
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying prng instance. */
+ private MDGenerator adaptee = new MDGenerator();
+
+ /** The name of the message digest algorithm used by the adaptee. */
+ private String mdName;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial protected constructor.</p>
+ *
+ * @param mdName the canonical name of the underlying hash algorithm.
+ */
+ protected SecureRandomAdapter(String mdName)
+ {
+ super();
+
+ this.mdName = mdName;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.SecureRandomSpi interface implementation ------------------
+
+ public byte[] engineGenerateSeed(int numBytes)
+ {
+ if (numBytes < 1)
+ {
+ return new byte[0];
+ }
+ byte[] result = new byte[numBytes];
+ this.engineNextBytes(result);
+ return result;
+ }
+
+ public void engineNextBytes(byte[] bytes)
+ {
+ if (!adaptee.isInitialised())
+ {
+ this.engineSetSeed(new byte[0]);
+ }
+ try
+ {
+ adaptee.nextBytes(bytes, 0, bytes.length);
+ }
+ catch (LimitReachedException ignored)
+ {
+ }
+ }
+
+ public void engineSetSeed(byte[] seed)
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(MDGenerator.MD_NAME, mdName);
+ attributes.put(MDGenerator.SEEED, seed);
+ adaptee.init(attributes);
+ }
+}
diff --git a/gnu/java/security/jce/prng/Sha160RandomSpi.java b/gnu/java/security/jce/prng/Sha160RandomSpi.java
new file mode 100644
index 000000000..c93b02d3f
--- /dev/null
+++ b/gnu/java/security/jce/prng/Sha160RandomSpi.java
@@ -0,0 +1,66 @@
+/* Sha160RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the SHA1-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class Sha160RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha160RandomSpi()
+ {
+ super(Registry.SHA160_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/Sha256RandomSpi.java b/gnu/java/security/jce/prng/Sha256RandomSpi.java
new file mode 100644
index 000000000..736996430
--- /dev/null
+++ b/gnu/java/security/jce/prng/Sha256RandomSpi.java
@@ -0,0 +1,66 @@
+/* Sha256RandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-256 based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.</p>
+ */
+public class Sha256RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha256RandomSpi()
+ {
+ super(Registry.SHA256_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/Sha384RandomSpi.java b/gnu/java/security/jce/prng/Sha384RandomSpi.java
new file mode 100644
index 000000000..afbf19303
--- /dev/null
+++ b/gnu/java/security/jce/prng/Sha384RandomSpi.java
@@ -0,0 +1,66 @@
+/* Sha384RandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-384 based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.</p>
+ */
+public class Sha384RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha384RandomSpi()
+ {
+ super(Registry.SHA384_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/Sha512RandomSpi.java b/gnu/java/security/jce/prng/Sha512RandomSpi.java
new file mode 100644
index 000000000..b2b337760
--- /dev/null
+++ b/gnu/java/security/jce/prng/Sha512RandomSpi.java
@@ -0,0 +1,66 @@
+/* Sha512RandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-512 based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.</p>
+ */
+public class Sha512RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha512RandomSpi()
+ {
+ super(Registry.SHA512_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/TigerRandomSpi.java b/gnu/java/security/jce/prng/TigerRandomSpi.java
new file mode 100644
index 000000000..b4795b98e
--- /dev/null
+++ b/gnu/java/security/jce/prng/TigerRandomSpi.java
@@ -0,0 +1,66 @@
+/* TigerRandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Tiger based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class TigerRandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public TigerRandomSpi()
+ {
+ super(Registry.TIGER_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/prng/WhirlpoolRandomSpi.java b/gnu/java/security/jce/prng/WhirlpoolRandomSpi.java
new file mode 100644
index 000000000..f327f9df2
--- /dev/null
+++ b/gnu/java/security/jce/prng/WhirlpoolRandomSpi.java
@@ -0,0 +1,66 @@
+/* WhirlpoolRandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Whirlpool-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class WhirlpoolRandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public WhirlpoolRandomSpi()
+ {
+ super(Registry.WHIRLPOOL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java b/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java
new file mode 100644
index 000000000..5cb1380d2
--- /dev/null
+++ b/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java
@@ -0,0 +1,113 @@
+/* DSSKeyPairGeneratorSpi.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSKeyPairGenerator;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.DSAParameterSpec;
+import java.util.HashMap;
+
+/**
+ * The implementation of a {@link java.security.KeyPairGenerator} adapter class
+ * to wrap gnu.crypto DSS keypair generator instances.<p>
+ *
+ * In case the client does not explicitly initialize the KeyPairGenerator (via
+ * a call to an <code>initialize()</code> method), the GNU Crypto provider
+ * uses a default <i>modulus</i> size (keysize) of 1024 bits.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public DSSKeyPairGeneratorSpi()
+ {
+ super(Registry.DSS_KPG);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public void initialize(int keysize, SecureRandom random)
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(DSSKeyPairGenerator.MODULUS_LENGTH, new Integer(keysize));
+ if (random != null)
+ {
+ attributes.put(DSSKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+ }
+
+ adaptee.setup(attributes);
+ }
+
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ HashMap attributes = new HashMap();
+ if (params != null)
+ {
+ if (!(params instanceof DSAParameterSpec))
+ {
+ throw new InvalidAlgorithmParameterException("params");
+ }
+
+ attributes.put(DSSKeyPairGenerator.DSS_PARAMETERS, params);
+ }
+
+ if (random != null)
+ {
+ attributes.put(DSSKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+ }
+
+ adaptee.setup(attributes);
+ }
+}
diff --git a/gnu/java/security/jce/sig/DSSRawSignatureSpi.java b/gnu/java/security/jce/sig/DSSRawSignatureSpi.java
new file mode 100644
index 000000000..16e4ddd4e
--- /dev/null
+++ b/gnu/java/security/jce/sig/DSSRawSignatureSpi.java
@@ -0,0 +1,70 @@
+/* DSSRawSignatureSpi.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.dss.DSSSignatureRawCodec;
+
+/**
+ * The implementation of <i>Service Provider Interface</i> (<b>SPI</b>) adapter
+ * for the DSS (Digital Signature Standard) signature scheme, encoded and/or
+ * decoded in RAW format.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSRawSignatureSpi extends SignatureAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public DSSRawSignatureSpi()
+ {
+ super(Registry.DSS_SIG, new DSSSignatureRawCodec());
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java b/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java
new file mode 100644
index 000000000..21a596a5f
--- /dev/null
+++ b/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java
@@ -0,0 +1,109 @@
+/* KeyPairGeneratorAdapter.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.key.IKeyPairGenerator;
+import gnu.java.security.key.KeyPairGeneratorFactory;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGeneratorSpi;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * The implementation of a generic {@link java.security.KeyPairGenerator}
+ * adapter class to wrap gnu.crypto keypair generator instances.<p>
+ *
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
+ * {@link java.security.KeyPairGenerator} class, which is used to generate pairs
+ * of public and private keys.<p>
+ *
+ * All the abstract methods in the {@link java.security.KeyPairGeneratorSpi}
+ * class are implemented by this class and all its sub-classes.<p>
+ *
+ * In case the client does not explicitly initialize the KeyPairGenerator (via
+ * a call to an <code>initialize()</code> method), the GNU Crypto provider
+ * supplies (and document) default values to be used. For example, the GNU
+ * Crypto provider uses a default <i>modulus</i> size (keysize) of 1024 bits for
+ * the DSS (Digital Signature Standard) a.k.a <i>DSA</i>.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+abstract class KeyPairGeneratorAdapter extends KeyPairGeneratorSpi
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying keypair instance. */
+ protected IKeyPairGenerator adaptee;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial protected constructor.
+ *
+ * @param kpgName the canonical name of the keypair generator algorithm.
+ */
+ protected KeyPairGeneratorAdapter(String kpgName)
+ {
+ super();
+
+ this.adaptee = KeyPairGeneratorFactory.getInstance(kpgName);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // java.security.KeyPairGeneratorSpi interface implementation
+ // -------------------------------------------------------------------------
+
+ public abstract void initialize(int keysize, SecureRandom random);
+
+ public abstract void initialize(AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException;
+
+ public KeyPair generateKeyPair()
+ {
+ return adaptee.generate();
+ }
+}
diff --git a/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java b/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java
new file mode 100644
index 000000000..54783eacf
--- /dev/null
+++ b/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java
@@ -0,0 +1,111 @@
+/* RSAKeyPairGeneratorSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.rsa.RSAKeyPairGenerator;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.RSAKeyGenParameterSpec;
+import java.util.HashMap;
+
+/**
+ * The implementation of a {@link java.security.KeyPairGenerator} adapter class
+ * to wrap gnu.crypto RSA keypair generator instances.<p>
+ *
+ * In case the client does not explicitly initialize the KeyPairGenerator (via
+ * a call to an <code>initialize()</code> method), the GNU Crypto provider
+ * uses a default <i>modulus</i> size (keysize) of 1024 bits.<p>
+ */
+public class RSAKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RSAKeyPairGeneratorSpi()
+ {
+ super(Registry.RSA_KPG);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public void initialize(int keysize, SecureRandom random)
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(RSAKeyPairGenerator.MODULUS_LENGTH, new Integer(keysize));
+ if (random != null)
+ {
+ attributes.put(RSAKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+ }
+
+ adaptee.setup(attributes);
+ }
+
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ HashMap attributes = new HashMap();
+ if (params != null)
+ {
+ if (!(params instanceof RSAKeyGenParameterSpec))
+ {
+ throw new InvalidAlgorithmParameterException("params");
+ }
+
+ attributes.put(RSAKeyPairGenerator.RSA_PARAMETERS, params);
+ }
+
+ if (random != null)
+ {
+ attributes.put(RSAKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+ }
+
+ adaptee.setup(attributes);
+ }
+}
diff --git a/gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java b/gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java
new file mode 100644
index 000000000..e44b8adf1
--- /dev/null
+++ b/gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java
@@ -0,0 +1,69 @@
+/* RSAPSSRawSignatureSpi.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.RSAPSSSignatureRawCodec;
+
+/**
+ * The implementation of <i>Service Provider Interface</i> (<b>SPI</b>) adapter
+ * for the RSA-PSS signature scheme, encoded and/or decoded in RAW format.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RSAPSSRawSignatureSpi extends SignatureAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RSAPSSRawSignatureSpi()
+ {
+ super(Registry.RSA_PSS_SIG, new RSAPSSSignatureRawCodec());
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/jce/sig/SignatureAdapter.java b/gnu/java/security/jce/sig/SignatureAdapter.java
new file mode 100644
index 000000000..6f393478d
--- /dev/null
+++ b/gnu/java/security/jce/sig/SignatureAdapter.java
@@ -0,0 +1,258 @@
+/* SignatureAdapter.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.sig.BaseSignature;
+import gnu.java.security.sig.ISignature;
+import gnu.java.security.sig.ISignatureCodec;
+import gnu.java.security.sig.SignatureFactory;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.SignatureException;
+import java.security.SignatureSpi;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.HashMap;
+
+/**
+ * The implementation of a generic {@link java.security.Signature} adapter class
+ * to wrap gnu.crypto signature instances.<p>
+ *
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
+ * {@link java.security.Signature} class, which provides the functionality of a
+ * digital signature algorithm. Digital signatures are used for authentication
+ * and integrity assurance of digital data.<p>
+ *
+ * All the abstract methods in the {@link java.security.SignatureSpi} class are
+ * implemented by this class and all its sub-classes.<p>
+ *
+ * All the implementations which subclass this object, and which are serviced by
+ * the GNU Crypto provider implement the {@link java.lang.Cloneable} interface.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+class SignatureAdapter extends SignatureSpi implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying signature instance. */
+ private ISignature adaptee;
+
+ /** Our underlying signature encoder/decoder engine. */
+ private ISignatureCodec codec;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial protected constructor.<p>
+ *
+ * @param sigName the canonical name of the signature scheme.
+ * @param codec the signature codec engine to use with this scheme.
+ */
+ protected SignatureAdapter(String sigName, ISignatureCodec codec)
+ {
+ this(SignatureFactory.getInstance(sigName), codec);
+ }
+
+ /**
+ * Private constructor for cloning purposes.<p>
+ *
+ * @param adaptee a clone of the underlying signature scheme instance.
+ * @param codec the signature codec engine to use with this scheme.
+ */
+ private SignatureAdapter(ISignature adaptee, ISignatureCodec codec)
+ {
+ super();
+
+ this.adaptee = adaptee;
+ this.codec = codec;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // java.security.SignatureSpi interface implementation
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new SignatureAdapter((ISignature) adaptee.clone(), codec);
+ }
+
+ public void engineInitVerify(PublicKey publicKey) throws InvalidKeyException
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(BaseSignature.VERIFIER_KEY, publicKey);
+ try
+ {
+ adaptee.setupVerify(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new InvalidKeyException(String.valueOf(x));
+ }
+ }
+
+ public void engineInitSign(PrivateKey privateKey) throws InvalidKeyException
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(BaseSignature.SIGNER_KEY, privateKey);
+ try
+ {
+ adaptee.setupSign(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new InvalidKeyException(String.valueOf(x));
+ }
+ }
+
+ public void engineInitSign(PrivateKey privateKey, SecureRandom random)
+ throws InvalidKeyException
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(BaseSignature.SIGNER_KEY, privateKey);
+ attributes.put(BaseSignature.SOURCE_OF_RANDOMNESS, random);
+ try
+ {
+ adaptee.setupSign(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new InvalidKeyException(String.valueOf(x));
+ }
+ }
+
+ public void engineUpdate(byte b) throws SignatureException
+ {
+ try
+ {
+ adaptee.update(b);
+ }
+ catch (IllegalStateException x)
+ {
+ throw new SignatureException(String.valueOf(x));
+ }
+ }
+
+ public void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException
+ {
+ try
+ {
+ adaptee.update(b, off, len);
+ }
+ catch (IllegalStateException x)
+ {
+ throw new SignatureException(String.valueOf(x));
+ }
+ }
+
+ public byte[] engineSign() throws SignatureException
+ {
+ Object signature = null;
+ try
+ {
+ signature = adaptee.sign();
+ }
+ catch (IllegalStateException x)
+ {
+ throw new SignatureException(String.valueOf(x));
+ }
+
+ byte[] result = codec.encodeSignature(signature);
+ return result;
+ }
+
+ public int engineSign(byte[] outbuf, int offset, int len)
+ throws SignatureException
+ {
+ byte[] signature = this.engineSign();
+ int result = signature.length;
+ if (result > len)
+ {
+ throw new SignatureException("len");
+ }
+
+ System.arraycopy(signature, 0, outbuf, offset, result);
+ return result;
+ }
+
+ public boolean engineVerify(byte[] sigBytes) throws SignatureException
+ {
+ Object signature = codec.decodeSignature(sigBytes);
+ boolean result = false;
+ try
+ {
+ result = adaptee.verify(signature);
+ }
+ catch (IllegalStateException x)
+ {
+ throw new SignatureException(String.valueOf(x));
+ }
+
+ return result;
+ }
+
+ // Deprecated. Replaced by engineSetParameter.
+ public void engineSetParameter(String param, Object value)
+ throws InvalidParameterException
+ {
+ throw new InvalidParameterException("deprecated");
+ }
+
+ public void engineSetParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ }
+
+ // Deprecated
+ public Object engineGetParameter(String param)
+ throws InvalidParameterException
+ {
+ throw new InvalidParameterException("deprecated");
+ }
+}
diff --git a/gnu/java/security/key/IKeyPairCodec.java b/gnu/java/security/key/IKeyPairCodec.java
new file mode 100644
index 000000000..7ebfe7458
--- /dev/null
+++ b/gnu/java/security/key/IKeyPairCodec.java
@@ -0,0 +1,121 @@
+/* IKeyPairCodec.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key;
+
+import gnu.java.security.Registry;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>The visible methods of an object that knows how to encode and decode
+ * cryptographic asymmetric keypairs. Codecs are useful for (a) externalising
+ * public and private keys for storage and on-the-wire transmission, as well as
+ * (b) re-creating their internal Java representation from external sources.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface IKeyPairCodec
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** Constant identifying the <i>Raw</i> encoding format. */
+ int RAW_FORMAT = Registry.RAW_ENCODING_ID;
+
+ // Method(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the unique identifier (within this library) of the format used
+ * to externalise public and private keys.</p>
+ *
+ * @return the identifier of the format, the object supports.
+ */
+ int getFormatID();
+
+ /**
+ * <p>Encodes an instance of a public key for storage or transmission purposes.</p>
+ *
+ * @param key the non-null key to encode.
+ * @return a byte sequence representing the encoding of the designated key
+ * according to the format supported by this codec.
+ * @exception IllegalArgumentException if the designated key is not supported
+ * by this codec.
+ */
+ byte[] encodePublicKey(PublicKey key);
+
+ /**
+ * <p>Encodes an instance of a private key for storage or transmission purposes.</p>
+ *
+ * @param key the non-null key to encode.
+ * @return a byte sequence representing the encoding of the designated key
+ * according to the format supported by this codec.
+ * @exception IllegalArgumentException if the designated key is not supported
+ * by this codec.
+ */
+ byte[] encodePrivateKey(PrivateKey key);
+
+ /**
+ * <p>Decodes an instance of an external public key into its native Java
+ * representation.</p>
+ *
+ * @param input the source of the externalised key to decode.
+ * @return a concrete instance of a public key, reconstructed from the
+ * designated input.
+ * @exception IllegalArgumentException if the designated input does not
+ * contain a known representation of a public key for the format supported by
+ * the concrete codec.
+ */
+ PublicKey decodePublicKey(byte[] input);
+
+ /**
+ * <p>Decodes an instance of an external private key into its native Java
+ * representation.</p>
+ *
+ * @param input the source of the externalised key to decode.
+ * @return a concrete instance of a private key, reconstructed from the
+ * designated input.
+ * @exception IllegalArgumentException if the designated input does not
+ * contain a known representation of a private key for the format supported
+ * by the concrete codec.
+ */
+ PrivateKey decodePrivateKey(byte[] input);
+}
diff --git a/gnu/java/security/key/IKeyPairGenerator.java b/gnu/java/security/key/IKeyPairGenerator.java
new file mode 100644
index 000000000..219863d33
--- /dev/null
+++ b/gnu/java/security/key/IKeyPairGenerator.java
@@ -0,0 +1,82 @@
+/* IKeyPairGenerator.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key;
+
+import java.security.KeyPair;
+import java.util.Map;
+
+/**
+ * The visible methods of every asymmetric keypair generator.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface IKeyPairGenerator
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns the canonical name of this keypair generator.<p>
+ *
+ * @return the canonical name of this instance.
+ */
+ String name();
+
+ /**
+ * [Re]-initialises this instance for use with a given set of attributes.<p>
+ *
+ * @param attributes a map of name/value pairs to use for setting up the
+ * instance.
+ * @exception IllegalArgumentException if at least one of the mandatory
+ * attributes is missing or an invalid value was specified.
+ */
+ void setup(Map attributes);
+
+ /**
+ * Generates a new keypair based on the attributes used to configure the
+ * instance.
+ *
+ * @return a new keypair.
+ */
+ KeyPair generate();
+}
diff --git a/gnu/java/security/key/KeyPairCodecFactory.java b/gnu/java/security/key/KeyPairCodecFactory.java
new file mode 100644
index 000000000..0bf9e6657
--- /dev/null
+++ b/gnu/java/security/key/KeyPairCodecFactory.java
@@ -0,0 +1,263 @@
+/* KeyPairCodecFactory.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSKeyPairRawCodec;
+import gnu.java.security.key.dss.DSSPrivateKey;
+import gnu.java.security.key.dss.DSSPublicKey;
+import gnu.java.security.key.rsa.GnuRSAPrivateKey;
+import gnu.java.security.key.rsa.GnuRSAPublicKey;
+import gnu.java.security.key.rsa.RSAKeyPairRawCodec;
+
+import java.lang.reflect.Constructor;
+import java.util.Set;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>A <i>Factory</i> class to instantiate key encoder/decoder instances.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class KeyPairCodecFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private KeyPairCodecFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a keypair codec given its name.</p>
+ *
+ * @param name the case-insensitive key codec name.
+ * @return an instance of the keypair codec, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairCodec getInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ IKeyPairCodec result = null;
+ if (name.equalsIgnoreCase(Registry.DSA_KPG)
+ || name.equals(Registry.DSS_KPG))
+ {
+ result = new DSSKeyPairRawCodec();
+ }
+ else if (name.equalsIgnoreCase(Registry.RSA_KPG))
+ {
+ result = new RSAKeyPairRawCodec();
+ }
+ else if (name.equalsIgnoreCase(Registry.DH_KPG))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.dh.DHKeyPairRawCodec");
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP_KPG))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec");
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns an instance of a keypair codec given a byte array that is
+ * assumed to contain a previously encoded key (public or private).</p>
+ *
+ * @param buffer a byte array containing a previously encoded key.
+ * @return an instance of the keypair codec, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairCodec getInstance(byte[] buffer)
+ {
+ if (buffer == null)
+ {
+ return null;
+ }
+ // our codecs prefix the stream with a 4-byte magic
+ if (buffer.length < 5)
+ {
+ return null;
+ }
+ // the first byte is always 0x47
+ if (buffer[0] != 0x47)
+ {
+ return null;
+ }
+ // so far we only have RAW codecs
+ if (buffer[1] != Registry.RAW_ENCODING_ID)
+ {
+ return null;
+ }
+ IKeyPairCodec result = null;
+ switch (buffer[2])
+ {
+ case 0x44:
+ result = new DSSKeyPairRawCodec();
+ break;
+ case 0x52:
+ result = new RSAKeyPairRawCodec();
+ break;
+ case 0x48:
+ result = makeInstance ("gnu.javax.crypto.key.dh.DHKeyPairRawCodec");
+ break;
+ case 0x53:
+ result = makeInstance ("gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec");
+ break;
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns an instance of a keypair codec given a key.</p>
+ *
+ * @param key the key to encode.
+ * @return an instance of the keypair codec, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairCodec getInstance(Key key)
+ {
+ if (key == null)
+ {
+ return null;
+ }
+
+ IKeyPairCodec result = null;
+ if (key instanceof PublicKey)
+ {
+ if (key instanceof DSSPublicKey)
+ {
+ result = new DSSKeyPairRawCodec();
+ }
+ else if (key instanceof GnuRSAPublicKey)
+ {
+ result = new RSAKeyPairRawCodec();
+ }
+ else if (matches (key, "gnu.javax.crypto.key.dh.GnuDHPublicKey"))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.dh.DHKeyPairRawCodec");
+ }
+ else if (matches (key, "gnu.javax.crypto.key.srp6.SRPPublicKey"))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec");
+ }
+ }
+ else if (key instanceof PrivateKey)
+ {
+ if (key instanceof DSSPrivateKey)
+ {
+ result = new DSSKeyPairRawCodec();
+ }
+ else if (key instanceof GnuRSAPrivateKey)
+ {
+ result = new RSAKeyPairRawCodec();
+ }
+ else if (matches (key, "gnu.javax.crypto.key.dh.GnuDHPrivateKey"))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.dh.DHKeyPairRawCodec");
+ }
+ else if (matches (key, "gnu.javax.crypto.key.srp6.SRPPrivateKey"))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec");
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of keypair codec names supported by this
+ * <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of keypair codec names (Strings).
+ */
+ public static final Set getNames()
+ {
+ return KeyPairGeneratorFactory.getNames();
+ }
+
+ private static IKeyPairCodec makeInstance (String clazz)
+ {
+ try
+ {
+ Class c = Class.forName (clazz);
+ Constructor ctor = c.getConstructor (new Class[0]);
+ return (IKeyPairCodec) ctor.newInstance (new Object[0]);
+ }
+ catch (Exception x)
+ {
+ IllegalArgumentException iae =
+ new IllegalArgumentException ("strong crypto key codec not available: "
+ + clazz);
+ iae.initCause (x);
+ throw iae;
+ }
+ }
+
+ private static boolean matches (Object o, String clazz)
+ {
+ try
+ {
+ Class c = Class.forName (clazz);
+ return c.isAssignableFrom (o.getClass ());
+ }
+ catch (Exception x)
+ {
+ // Can't match.
+ return false;
+ }
+ }
+}
diff --git a/gnu/java/security/key/KeyPairGeneratorFactory.java b/gnu/java/security/key/KeyPairGeneratorFactory.java
new file mode 100644
index 000000000..edcc186e2
--- /dev/null
+++ b/gnu/java/security/key/KeyPairGeneratorFactory.java
@@ -0,0 +1,148 @@
+/* KeyPairGeneratorFactory.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSKeyPairGenerator;
+import gnu.java.security.key.rsa.RSAKeyPairGenerator;
+
+import java.lang.reflect.Constructor;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>A Factory to instantiate asymmetric keypair generators.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class KeyPairGeneratorFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private KeyPairGeneratorFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a keypair generator given its name.</p>
+ *
+ * @param name the case-insensitive key generator name.
+ * @return an instance of the keypair generator, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairGenerator getInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ IKeyPairGenerator result = null;
+ if (name.equalsIgnoreCase(Registry.DSA_KPG)
+ || name.equals(Registry.DSS_KPG))
+ {
+ result = new DSSKeyPairGenerator();
+ }
+ else if (name.equalsIgnoreCase(Registry.RSA_KPG))
+ {
+ result = new RSAKeyPairGenerator();
+ }
+ else if (name.equalsIgnoreCase(Registry.DH_KPG))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.dh.GnuDHKeyPairGenerator");
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP_KPG))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.srp6.SRPKeyPairGenerator");
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of keypair generator names supported by this
+ * <i>Factory</i>. Those keypair generators may be used in conjunction with
+ * the digital signature schemes with appendix supported by this library.</p>
+ *
+ * @return a {@link Set} of keypair generator names (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.DSS_KPG);
+ hs.add(Registry.RSA_KPG);
+ hs.add(Registry.DH_KPG);
+ hs.add(Registry.SRP_KPG);
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ private static IKeyPairGenerator makeInstance (String clazz)
+ {
+ try
+ {
+ Class c = Class.forName (clazz);
+ Constructor ctor = c.getConstructor (new Class[0]);
+ return (IKeyPairGenerator) ctor.newInstance (new Object[0]);
+ }
+ catch (Exception x)
+ {
+ IllegalArgumentException iae =
+ new IllegalArgumentException ("strong crypto key pair generator not available: "
+ + clazz);
+ iae.initCause (x);
+ throw iae;
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/key/dss/DSSKey.java b/gnu/java/security/key/dss/DSSKey.java
new file mode 100644
index 000000000..c052d3fde
--- /dev/null
+++ b/gnu/java/security/key/dss/DSSKey.java
@@ -0,0 +1,173 @@
+/* DSSKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.Key;
+import java.security.interfaces.DSAKey;
+import java.security.interfaces.DSAParams;
+import java.security.spec.DSAParameterSpec;
+
+/**
+ * <p>A base asbtract class for both public and private DSS (Digital Signature
+ * Standard) keys. It encapsulates the three DSS numbers: <code>p</code>,
+ * <code>q</code> and <code>g</code>.</p>
+ *
+ * <p>According to the JDK, cryptographic <i>Keys</i> all have a <i>format</i>.
+ * The format used in this implementation is called <i>Raw</i>, and basically
+ * consists of the raw byte sequences of algorithm parameters. The exact order
+ * of the byte sequences and the implementation details are given in each of
+ * the relevant <code>getEncoded()</code> methods of each of the private and
+ * public keys.</p>
+ *
+ * @version $Revision: 1.1 $
+ * @see DSSPrivateKey#getEncoded
+ * @see DSSPublicKey#getEncoded
+ */
+public abstract class DSSKey implements Key, DSAKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * A prime modulus, where <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup></code>
+ * for <code>512 &lt;= L &lt;= 1024</code> and <code>L</code> a multiple of
+ * <code>64</code>.
+ */
+ protected final BigInteger p;
+
+ /**
+ * A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup> &lt; q
+ * &lt; 2<sup>160</sup></code>.
+ */
+ protected final BigInteger q;
+
+ /**
+ * <code>g = h<sup>(p-1)</sup>/q mod p</code>, where <code>h</code> is any
+ * integer with <code>1 &lt; h &lt; p - 1</code> such that <code>h<sup>
+ * (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order <code>q mod p
+ * </code>).
+ */
+ protected final BigInteger g;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial protected constructor.</p>
+ *
+ * @param p the DSS parameter <code>p</code>.
+ * @param q the DSS parameter <code>q</code>.
+ * @param g the DSS parameter <code>g</code>.
+ */
+ protected DSSKey(BigInteger p, BigInteger q, BigInteger g)
+ {
+ super();
+
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.DSAKey interface implementation ----------------
+
+ public DSAParams getParams()
+ {
+ return new DSAParameterSpec(p, q, g);
+ }
+
+ // java.security.Key interface implementation ------------------------------
+
+ public String getAlgorithm()
+ {
+ return Registry.DSS_KPG;
+ }
+
+ /** @deprecated see getEncoded(int). */
+ public byte[] getEncoded()
+ {
+ return getEncoded(IKeyPairCodec.RAW_FORMAT);
+ }
+
+ public String getFormat()
+ {
+ return null;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link DSAKey} and has the same DSS (Digital Signature Standard) parameter
+ * values as this one.</p>
+ *
+ * @param obj the other non-null DSS key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof DSAKey))
+ {
+ return false;
+ }
+ DSAKey that = (DSAKey) obj;
+ return p.equals(that.getParams().getP())
+ && q.equals(that.getParams().getQ())
+ && g.equals(that.getParams().getG());
+ }
+
+ // abstract methods to be implemented by subclasses ------------------------
+
+ public abstract byte[] getEncoded(int format);
+}
diff --git a/gnu/java/security/key/dss/DSSKeyPairGenerator.java b/gnu/java/security/key/dss/DSSKeyPairGenerator.java
new file mode 100644
index 000000000..3f9c80625
--- /dev/null
+++ b/gnu/java/security/key/dss/DSSKeyPairGenerator.java
@@ -0,0 +1,360 @@
+/* DSSKeyPairGenerator.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.key.IKeyPairGenerator;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.DSAParameterSpec;
+import java.util.Map;
+
+/**
+ * <p>A key-pair generator for asymetric keys to use in conjunction with the DSS
+ * (Digital Signature Standard).</p>
+ *
+ * References:<br>
+ * <a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature
+ * Standard (DSS)</a>, Federal Information Processing Standards Publication 186.
+ * National Institute of Standards and Technology.
+ */
+public class DSSKeyPairGenerator implements IKeyPairGenerator
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "dss";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The BigInteger constant 2. */
+ private static final BigInteger TWO = new BigInteger("2");
+
+ /** Property name of the length (Integer) of the modulus (p) of a DSS key. */
+ public static final String MODULUS_LENGTH = "gnu.crypto.dss.L";
+
+ /** Property name of the Boolean indicating wether or not to use defaults. */
+ public static final String USE_DEFAULTS = "gnu.crypto.dss.use.defaults";
+
+ /**
+ * Property name of an optional {@link SecureRandom} instance to use. The
+ * default is to use a classloader singleton from {@link PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dss.prng";
+
+ /**
+ * Property name of an optional {@link DSAParameterSpec} instance to use for
+ * this generator's <code>p</code>, <code>q</code>, and <code>g</code> values.
+ * The default is to generate these values or use pre-computed ones,
+ * depending on the value of the <code>USE_DEFAULTS</code> attribute.
+ */
+ public static final String DSS_PARAMETERS = "gnu.crypto.dss.params";
+
+ /** Default value for the modulus length. */
+ private static final int DEFAULT_MODULUS_LENGTH = 1024;
+
+ /** Initial SHS context. */
+ private static final int[] T_SHS = new int[] { 0x67452301, 0xEFCDAB89,
+ 0x98BADCFE, 0x10325476,
+ 0xC3D2E1F0 };
+
+ // from jdk1.3.1/docs/guide/security/CryptoSpec.html#AppB
+ public static final DSAParameterSpec KEY_PARAMS_512 = new DSAParameterSpec(
+ new BigInteger(
+ "fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae"
+ + "01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e17",
+ 16),
+ new BigInteger(
+ "962eddcc369cba8ebb260ee6b6a126d9346e38c5",
+ 16),
+ new BigInteger(
+ "678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e"
+ + "35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4",
+ 16));
+
+ public static final DSAParameterSpec KEY_PARAMS_768 = new DSAParameterSpec(
+ new BigInteger(
+ "e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5d8901419"
+ + "22d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a22219d470bce7d77"
+ + "7d4a21fbe9c270b57f607002f3cef8393694cf45ee3688c11a8c56ab127a3daf",
+ 16),
+ new BigInteger(
+ "9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511",
+ 16),
+ new BigInteger(
+ "30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7a31d23c4"
+ + "dbbcbe06174544401a5b2c020965d8c2bd2171d3668445771f74ba084d2029d8"
+ + "3c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a7064f316933a346d3f529252",
+ 16));
+
+ public static final DSAParameterSpec KEY_PARAMS_1024 = new DSAParameterSpec(
+ new BigInteger(
+ "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669"
+ + "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7"
+ + "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb"
+ + "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7",
+ 16),
+ new BigInteger(
+ "9760508f15230bccb292b982a2eb840bf0581cf5",
+ 16),
+ new BigInteger(
+ "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267"
+ + "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1"
+ + "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b"
+ + "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a",
+ 16));
+
+ private static final BigInteger TWO_POW_160 = TWO.pow(160);
+
+ /** The length of the modulus of DSS keys generated by this instance. */
+ private int L;
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ private BigInteger seed;
+
+ private BigInteger counter;
+
+ private BigInteger p;
+
+ private BigInteger q;
+
+ private BigInteger e;
+
+ private BigInteger g;
+
+ private BigInteger XKEY;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
+
+ public String name()
+ {
+ return Registry.DSS_KPG;
+ }
+
+ /**
+ * <p>Configures this instance.</p>
+ *
+ * @param attributes the map of name/value pairs to use.
+ * @exception IllegalArgumentException if the designated MODULUS_LENGTH
+ * value is not greater than 512, less than 1024 and not of the form
+ * <code>512 + 64j</code>.
+ */
+ public void setup(Map attributes)
+ {
+ // find out the modulus length
+ Integer l = (Integer) attributes.get(MODULUS_LENGTH);
+ L = (l == null ? DEFAULT_MODULUS_LENGTH : l.intValue());
+ if ((L % 64) != 0 || L < 512 || L > 1024)
+ throw new IllegalArgumentException(MODULUS_LENGTH);
+
+ // should we use the default pre-computed params?
+ Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
+ if (useDefaults == null)
+ {
+ useDefaults = Boolean.TRUE;
+ }
+
+ // are we given a set of DSA params or we shall use/generate our own?
+ DSAParameterSpec params = (DSAParameterSpec) attributes.get(DSS_PARAMETERS);
+ if (params != null)
+ {
+ p = params.getP();
+ q = params.getQ();
+ g = params.getG();
+ }
+ else if (useDefaults.equals(Boolean.TRUE))
+ {
+ switch (L)
+ {
+ case 512:
+ p = KEY_PARAMS_512.getP();
+ q = KEY_PARAMS_512.getQ();
+ g = KEY_PARAMS_512.getG();
+ break;
+ case 768:
+ p = KEY_PARAMS_768.getP();
+ q = KEY_PARAMS_768.getQ();
+ g = KEY_PARAMS_768.getG();
+ break;
+ case 1024:
+ p = KEY_PARAMS_1024.getP();
+ q = KEY_PARAMS_1024.getQ();
+ g = KEY_PARAMS_1024.getG();
+ break;
+ default:
+ p = null;
+ q = null;
+ g = null;
+ }
+ }
+ else
+ {
+ p = null;
+ q = null;
+ g = null;
+ }
+
+ // do we have a SecureRandom, or should we use our own?
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ // set the seed-key
+ byte[] kb = new byte[20]; // we need 160 bits of randomness
+ nextRandomBytes(kb);
+ XKEY = new BigInteger(1, kb).setBit(159).setBit(0);
+ }
+
+ public KeyPair generate()
+ {
+ if (p == null)
+ {
+ BigInteger[] params = new FIPS186(L, rnd).generateParameters();
+ seed = params[FIPS186.DSA_PARAMS_SEED];
+ counter = params[FIPS186.DSA_PARAMS_COUNTER];
+ q = params[FIPS186.DSA_PARAMS_Q];
+ p = params[FIPS186.DSA_PARAMS_P];
+ e = params[FIPS186.DSA_PARAMS_E];
+ g = params[FIPS186.DSA_PARAMS_G];
+ if (DEBUG && debuglevel > 0)
+ {
+ debug("seed: " + seed.toString(16));
+ debug("counter: " + counter.intValue());
+ debug("q: " + q.toString(16));
+ debug("p: " + p.toString(16));
+ debug("e: " + e.toString(16));
+ debug("g: " + g.toString(16));
+ }
+ }
+
+ BigInteger x = nextX();
+ BigInteger y = g.modPow(x, p);
+
+ PublicKey pubK = new DSSPublicKey(p, q, g, y);
+ PrivateKey secK = new DSSPrivateKey(p, q, g, x);
+
+ return new KeyPair(pubK, secK);
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>This method applies the following algorithm described in 3.1 of
+ * FIPS-186:</p>
+ *
+ * <ol>
+ * <li>XSEED = optional user input.</li>
+ * <li>XVAL = (XKEY + XSEED) mod 2<sup>b</sup>.</li>
+ * <li>x = G(t, XVAL) mod q.</li>
+ * <li>XKEY = (1 + XKEY + x) mod 2<sup>b</sup>.</li>
+ * </ol>
+ *
+ * <p>Where <code>b</code> is the length of a secret b-bit seed-key (XKEY).</p>
+ *
+ * <p>Note that in this implementation, XSEED, the optional user input, is
+ * always zero.</p>
+ */
+ private synchronized BigInteger nextX()
+ {
+ byte[] xk = XKEY.toByteArray();
+ byte[] in = new byte[64]; // 512-bit block for SHS
+ System.arraycopy(xk, 0, in, 0, xk.length);
+
+ int[] H = Sha160.G(T_SHS[0], T_SHS[1], T_SHS[2], T_SHS[3], T_SHS[4], in, 0);
+ byte[] h = new byte[20];
+ for (int i = 0, j = 0; i < 5; i++)
+ {
+ h[j++] = (byte) (H[i] >>> 24);
+ h[j++] = (byte) (H[i] >>> 16);
+ h[j++] = (byte) (H[i] >>> 8);
+ h[j++] = (byte) H[i];
+ }
+ BigInteger result = new BigInteger(1, h).mod(q);
+ XKEY = XKEY.add(result).add(BigInteger.ONE).mod(TWO_POW_160);
+
+ return result;
+ }
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+}
diff --git a/gnu/java/security/key/dss/DSSKeyPairRawCodec.java b/gnu/java/security/key/dss/DSSKeyPairRawCodec.java
new file mode 100644
index 000000000..86e5b0bef
--- /dev/null
+++ b/gnu/java/security/key/dss/DSSKeyPairRawCodec.java
@@ -0,0 +1,383 @@
+/* DSSKeyPairRawCodec.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>An object that implements the {@link IKeyPairCodec} operations for the
+ * <i>Raw</i> format to use with DSS keypairs.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSKeyPairRawCodec implements IKeyPairCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.keys.IKeyPairCodec interface implementation ------------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated DSS (Digital Signature
+ * Standard) public key according to the <i>Raw</i> format supported by
+ * this library.</p>
+ *
+ * <p>The <i>Raw</i> format for a DSA public key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_DSS_PUBLIC_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>p</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>p</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>q</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>q</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>g</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>g</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>y</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>y</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @throws IllegalArgumentException if the designated key is not a DSS
+ * (Digital Signature Standard) one.
+ * @see Registry#MAGIC_RAW_DSS_PUBLIC_KEY
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (!(key instanceof DSSPublicKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ DSSPublicKey dssKey = (DSSPublicKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // p
+ byte[] buffer = dssKey.getParams().getP().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // q
+ buffer = dssKey.getParams().getQ().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // g
+ buffer = dssKey.getParams().getG().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // y
+ buffer = dssKey.getY().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PublicKey decodePublicKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // p
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger p = new BigInteger(1, buffer);
+
+ // q
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger q = new BigInteger(1, buffer);
+
+ // g
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger g = new BigInteger(1, buffer);
+
+ // y
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger y = new BigInteger(1, buffer);
+
+ return new DSSPublicKey(p, q, g, y);
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated DSS (Digital Signature
+ * Standard) private key according to the <i>Raw</i> format supported by
+ * this library.</p>
+ *
+ * <p>The <i>Raw</i> format for a DSA private key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_DSS_PRIVATE_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>p</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>p</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>q</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>q</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>g</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>g</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>x</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>x</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @throws IllegalArgumentException if the designated key is not a DSS
+ * (Digital Signature Standard) one.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (!(key instanceof DSSPrivateKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ DSSPrivateKey dssKey = (DSSPrivateKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // p
+ byte[] buffer = dssKey.getParams().getP().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // q
+ buffer = dssKey.getParams().getQ().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // g
+ buffer = dssKey.getParams().getG().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // x
+ buffer = dssKey.getX().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PrivateKey decodePrivateKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // p
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger p = new BigInteger(1, buffer);
+
+ // q
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger q = new BigInteger(1, buffer);
+
+ // g
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger g = new BigInteger(1, buffer);
+
+ // x
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger x = new BigInteger(1, buffer);
+
+ return new DSSPrivateKey(p, q, g, x);
+ }
+}
diff --git a/gnu/java/security/key/dss/DSSPrivateKey.java b/gnu/java/security/key/dss/DSSPrivateKey.java
new file mode 100644
index 000000000..dc73c5e89
--- /dev/null
+++ b/gnu/java/security/key/dss/DSSPrivateKey.java
@@ -0,0 +1,179 @@
+/* DSSPrivateKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.interfaces.DSAPrivateKey;
+
+/**
+ * <p>An object that embodies a DSS (Digital Signature Standard) private key.</p>
+ *
+ * @version $Revision: 1.1 $
+ * @see #getEncoded
+ */
+public class DSSPrivateKey extends DSSKey implements PrivateKey, DSAPrivateKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A randomly or pseudorandomly generated integer with <code>0 &lt; x &lt;
+ * q</code>.</p>
+ */
+ private final BigInteger x;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor.</p>
+ *
+ * @param p the public modulus.
+ * @param q the public prime divisor of <code>p-1</code>.
+ * @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
+ * <sub>p</sub></code>.
+ * @param x the private key part.
+ */
+ public DSSPrivateKey(BigInteger p, BigInteger q, BigInteger g, BigInteger x)
+ {
+ super(p, q, g);
+
+ this.x = x;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A class method that takes the output of the <code>encodePrivateKey()</code>
+ * method of a DSS keypair codec object (an instance implementing
+ * {@link gnu.crypto.key.IKeyPairCodec} for DSS keys, and re-constructs an
+ * instance of this object.</p>
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough bytes,
+ * in <code>k</code>, to represent a valid encoding of an instance of
+ * this object.
+ * @exception IllegalArgumentException if the byte sequence does not
+ * represent a valid encoding of an instance of this object.
+ */
+ public static DSSPrivateKey valueOf(byte[] k)
+ {
+ // check magic...
+ // we should parse here enough bytes to know which codec to use, and
+ // direct the byte array to the appropriate codec. since we only have one
+ // codec, we could have immediately tried it; nevertheless since testing
+ // one byte is cheaper than instatiating a codec that will fail we test
+ // the first byte before we carry on.
+ if (k[0] == Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0])
+ {
+ // it's likely to be in raw format. get a raw codec and hand it over
+ IKeyPairCodec codec = new DSSKeyPairRawCodec();
+ return (DSSPrivateKey) codec.decodePrivateKey(k);
+ }
+ else
+ {
+ throw new IllegalArgumentException("magic");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.DSAPrivateKey interface implementation ---------
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this private key according to the
+ * designated format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @exception IllegalArgumentException if the format is not supported.
+ * @see DSSKeyPairRawCodec
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new DSSKeyPairRawCodec().encodePrivateKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("format");
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link DSAPrivateKey} and has the same DSS (Digital Signature Standard)
+ * parameter values as this one.</p>
+ *
+ * @param obj the other non-null DSS key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof DSAPrivateKey))
+ {
+ return false;
+ }
+ DSAPrivateKey that = (DSAPrivateKey) obj;
+ return super.equals(that) && x.equals(that.getX());
+ }
+}
diff --git a/gnu/java/security/key/dss/DSSPublicKey.java b/gnu/java/security/key/dss/DSSPublicKey.java
new file mode 100644
index 000000000..a76ce92b2
--- /dev/null
+++ b/gnu/java/security/key/dss/DSSPublicKey.java
@@ -0,0 +1,179 @@
+/* DSSPublicKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.interfaces.DSAPublicKey;
+
+/**
+ * <p>An object that embodies a DSS (Digital Signature Standard) public key.</p>
+ *
+ * @version $Revision: 1.1 $
+ * @see #getEncoded
+ */
+public class DSSPublicKey extends DSSKey implements PublicKey, DSAPublicKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * <code>y = g<sup>x</sup> mod p</code> where <code>x</code> is the private
+ * part of the DSA key.
+ */
+ private final BigInteger y;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor.</p>
+ *
+ * @param p the public modulus.
+ * @param q the public prime divisor of <code>p-1</code>.
+ * @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
+ * <sub>p</sub></code>.
+ * @param y the public key part.
+ */
+ public DSSPublicKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y)
+ {
+ super(p, q, g);
+
+ this.y = y;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A class method that takes the output of the <code>encodePublicKey()</code>
+ * method of a DSS keypair codec object (an instance implementing
+ * {@link gnu.crypto.key.IKeyPairCodec} for DSS keys, and re-constructs an
+ * instance of this object.</p>
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough bytes,
+ * in <code>k</code>, to represent a valid encoding of an instance of
+ * this object.
+ * @exception IllegalArgumentException if the byte sequence does not
+ * represent a valid encoding of an instance of this object.
+ */
+ public static DSSPublicKey valueOf(byte[] k)
+ {
+ // check magic...
+ // we should parse here enough bytes to know which codec to use, and
+ // direct the byte array to the appropriate codec. since we only have one
+ // codec, we could have immediately tried it; nevertheless since testing
+ // one byte is cheaper than instatiating a codec that will fail we test
+ // the first byte before we carry on.
+ if (k[0] == Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0])
+ {
+ // it's likely to be in raw format. get a raw codec and hand it over
+ IKeyPairCodec codec = new DSSKeyPairRawCodec();
+ return (DSSPublicKey) codec.decodePublicKey(k);
+ }
+ else
+ {
+ throw new IllegalArgumentException("magic");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.DSAPublicKey interface implementation ----------
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this public key according to the designated
+ * format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @exception IllegalArgumentException if the format is not supported.
+ * @see DSSKeyPairRawCodec
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new DSSKeyPairRawCodec().encodePublicKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("format");
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link DSAPublicKey} and has the same DSS (Digital Signature Standard)
+ * parameter values as this one.</p>
+ *
+ * @param obj the other non-null DSS key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof DSAPublicKey))
+ {
+ return false;
+ }
+ DSAPublicKey that = (DSAPublicKey) obj;
+ return super.equals(that) && y.equals(that.getY());
+ }
+}
diff --git a/gnu/java/security/key/dss/FIPS186.java b/gnu/java/security/key/dss/FIPS186.java
new file mode 100644
index 000000000..796f24bd3
--- /dev/null
+++ b/gnu/java/security/key/dss/FIPS186.java
@@ -0,0 +1,286 @@
+/* FIPS186.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.util.Prime2;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * <p>An implementation of the DSA parameters generation as described in
+ * FIPS-186.</p>
+ *
+ * References:<br>
+ * <a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature
+ * Standard (DSS)</a>, Federal Information Processing Standards Publication 186.
+ * National Institute of Standards and Technology.
+ *
+ * @version $Revision: 1.1 $
+ */
+public class FIPS186
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int DSA_PARAMS_SEED = 0;
+
+ public static final int DSA_PARAMS_COUNTER = 1;
+
+ public static final int DSA_PARAMS_Q = 2;
+
+ public static final int DSA_PARAMS_P = 3;
+
+ public static final int DSA_PARAMS_E = 4;
+
+ public static final int DSA_PARAMS_G = 5;
+
+ /** The BigInteger constant 2. */
+ private static final BigInteger TWO = new BigInteger("2");
+
+ private static final BigInteger TWO_POW_160 = TWO.pow(160);
+
+ /** The SHA instance to use. */
+ private Sha160 sha = new Sha160();
+
+ /** The length of the modulus of DSS keys generated by this instance. */
+ private int L;
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public FIPS186(int L, SecureRandom rnd)
+ {
+ super();
+
+ this.L = L;
+ this.rnd = rnd;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * This method generates the DSS <code>p</code>, <code>q</code>, and
+ * <code>g</code> parameters only when <code>L</code> (the modulus length)
+ * is not one of the following: <code>512</code>, <code>768</code> and
+ * <code>1024</code>. For those values of <code>L</code>, this implementation
+ * uses pre-computed values of <code>p</code>, <code>q</code>, and
+ * <code>g</code> given in the document <i>CryptoSpec</i> included in the
+ * security guide documentation of the standard JDK distribution.<p>
+ *
+ * The DSS requires two primes , <code>p</code> and <code>q</code>,
+ * satisfying the following three conditions:
+ *
+ * <ul>
+ * <li><code>2<sup>159</sup> &lt; q &lt; 2<sup>160</sup></code></li>
+ * <li><code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup></code> for a
+ * specified <code>L</code>, where <code>L = 512 + 64j</code> for some
+ * <code>0 &lt;= j &lt;= 8</code></li>
+ * <li>q divides p - 1.</li>
+ * </ul>
+ *
+ * The algorithm used to find these primes is as described in FIPS-186,
+ * section 2.2: GENERATION OF PRIMES. This prime generation scheme starts by
+ * using the {@link gnu.crypto.hash.Sha160} and a user supplied <i>SEED</i>
+ * to construct a prime, <code>q</code>, in the range 2<sup>159</sup> &lt; q
+ * &lt; 2<sup>160</sup>. Once this is accomplished, the same <i>SEED</i>
+ * value is used to construct an <code>X</code> in the range <code>2<sup>L-1
+ * </sup> &lt; X &lt; 2<sup>L</sup>. The prime, <code>p</code>, is then
+ * formed by rounding <code>X</code> to a number congruent to <code>1 mod
+ * 2q</code>. In this implementation we use the same <i>SEED</i> value given
+ * in FIPS-186, Appendix 5.
+ */
+ public BigInteger[] generateParameters()
+ {
+ int counter, offset;
+ BigInteger SEED, alpha, U, q, OFFSET, SEED_PLUS_OFFSET, W, X, p, c, g;
+ byte[] a, u;
+ byte[] kb = new byte[20]; // to hold 160 bits of randomness
+
+ // Let L-1 = n*160 + b, where b and n are integers and 0 <= b < 160.
+ int b = (L - 1) % 160;
+ int n = (L - 1 - b) / 160;
+ BigInteger[] V = new BigInteger[n + 1];
+ algorithm: while (true)
+ {
+ step1: while (true)
+ {
+ // 1. Choose an arbitrary sequence of at least 160 bits and
+ // call it SEED.
+ nextRandomBytes(kb);
+ SEED = new BigInteger(1, kb).setBit(159).setBit(0);
+ // Let g be the length of SEED in bits. here always 160
+ // 2. Compute: U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]
+ alpha = SEED.add(BigInteger.ONE).mod(TWO_POW_160);
+ synchronized (sha)
+ {
+ a = SEED.toByteArray();
+ sha.update(a, 0, a.length);
+ a = sha.digest();
+ u = alpha.toByteArray();
+ sha.update(u, 0, u.length);
+ u = sha.digest();
+ }
+ for (int i = 0; i < a.length; i++)
+ {
+ a[i] ^= u[i];
+ }
+ U = new BigInteger(1, a);
+ // 3. Form q from U by setting the most significant bit (the
+ // 2**159 bit) and the least significant bit to 1. In terms of
+ // boolean operations, q = U OR 2**159 OR 1. Note that
+ // 2**159 < q < 2**160.
+ q = U.setBit(159).setBit(0);
+ // 4. Use a robust primality testing algorithm to test whether
+ // q is prime(1). A robust primality test is one where the
+ // probability of a non-prime number passing the test is at
+ // most 1/2**80.
+ // 5. If q is not prime, go to step 1.
+ if (Prime2.isProbablePrime(q))
+ {
+ break step1;
+ }
+ } // step1
+
+ // 6. Let counter = 0 and offset = 2.
+ counter = 0;
+ offset = 2;
+ step7: while (true)
+ {
+ OFFSET = BigInteger.valueOf(offset & 0xFFFFFFFFL);
+ SEED_PLUS_OFFSET = SEED.add(OFFSET);
+ // 7. For k = 0,...,n let V[k] = SHA[(SEED + offset + k) mod 2**g].
+ synchronized (sha)
+ {
+ for (int k = 0; k <= n; k++)
+ {
+ a = SEED_PLUS_OFFSET.add(
+ BigInteger.valueOf(k & 0xFFFFFFFFL)).mod(
+ TWO_POW_160).toByteArray();
+ sha.update(a, 0, a.length);
+ V[k] = new BigInteger(1, sha.digest());
+ }
+ }
+ // 8. Let W be the integer:
+ // V[0]+V[1]*2**160+...+V[n-1]*2**((n-1)*160)+(V[n]mod2**b)*2**(n*160)
+ // and let : X = W + 2**(L-1).
+ // Note that 0 <= W < 2**(L-1) and hence 2**(L-1) <= X < 2**L.
+ W = V[0];
+ for (int k = 1; k < n; k++)
+ {
+ W = W.add(V[k].multiply(TWO.pow(k * 160)));
+ }
+ W = W.add(V[n].mod(TWO.pow(b)).multiply(TWO.pow(n * 160)));
+ X = W.add(TWO.pow(L - 1));
+ // 9. Let c = X mod 2q and set p = X - (c - 1).
+ // Note that p is congruent to 1 mod 2q.
+ c = X.mod(TWO.multiply(q));
+ p = X.subtract(c.subtract(BigInteger.ONE));
+ // 10. If p < 2**(L-1), then go to step 13.
+ if (p.compareTo(TWO.pow(L - 1)) >= 0)
+ {
+ // 11. Perform a robust primality test on p.
+ // 12. If p passes the test performed in step 11, go to step 15.
+ if (Prime2.isProbablePrime(p))
+ {
+ break algorithm;
+ }
+ }
+ // 13. Let counter = counter + 1 and offset = offset + n + 1.
+ counter++;
+ offset += n + 1;
+ // 14. If counter >= 4096 go to step 1, otherwise go to step 7.
+ if (counter >= 4096)
+ {
+ continue algorithm;
+ }
+ } // step7
+ } // algorithm
+
+ // compute g. from FIPS-186, Appendix 4:
+ // 1. Generate p and q as specified in Appendix 2.
+ // 2. Let e = (p - 1) / q
+ BigInteger e = p.subtract(BigInteger.ONE).divide(q);
+ BigInteger h = TWO;
+ BigInteger p_minus_1 = p.subtract(BigInteger.ONE);
+ g = TWO;
+ // 3. Set h = any integer, where 1 < h < p - 1 and
+ // h differs from any value previously tried
+ for (; h.compareTo(p_minus_1) < 0; h = h.add(BigInteger.ONE))
+ {
+ // 4. Set g = h**e mod p
+ g = h.modPow(e, p);
+ // 5. If g = 1, go to step 3
+ if (!g.equals(BigInteger.ONE))
+ {
+ break;
+ }
+ }
+
+ return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g };
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ * Fills the designated byte array with random data.
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+}
diff --git a/gnu/java/security/key/rsa/GnuRSAKey.java b/gnu/java/security/key/rsa/GnuRSAKey.java
new file mode 100644
index 000000000..a92ef50a5
--- /dev/null
+++ b/gnu/java/security/key/rsa/GnuRSAKey.java
@@ -0,0 +1,171 @@
+/* GnuRSAKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.Key;
+import java.security.interfaces.RSAKey;
+
+/**
+ * <p>A base asbtract class for both public and private RSA keys.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public abstract class GnuRSAKey implements Key, RSAKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The public modulus of an RSA key pair. */
+ private final BigInteger n;
+
+ /** The public exponent of an RSA key pair. */
+ private final BigInteger e;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial protected constructor.</p>
+ *
+ * @param n the public modulus <code>n</code>.
+ * @param e the public exponent <code>e</code>.
+ */
+ // protected GnuRSAKey(BigInteger n) {
+ protected GnuRSAKey(final BigInteger n, final BigInteger e)
+ {
+ super();
+
+ this.n = n;
+ this.e = e;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.RSAKey interface implementation ----------------
+
+ public BigInteger getModulus()
+ {
+ return getN();
+ }
+
+ // java.security.Key interface implementation ------------------------------
+
+ public String getAlgorithm()
+ {
+ return Registry.RSA_KPG;
+ }
+
+ /** @deprecated see getEncoded(int). */
+ public byte[] getEncoded()
+ {
+ return getEncoded(IKeyPairCodec.RAW_FORMAT);
+ }
+
+ public String getFormat()
+ {
+ return null;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the modulus <code>n</code>.</p>
+ *
+ * @return the modulus <code>n</code>.
+ */
+ public BigInteger getN()
+ {
+ return n;
+ }
+
+ /**
+ * <p>Returns the public exponent <code>e</code>.</p>
+ *
+ * @return the public exponent <code>e</code>.
+ */
+ public BigInteger getPublicExponent()
+ {
+ return getE();
+ }
+
+ /**
+ * <p>Same as {@link #getPublicExponent()}.</p>
+ *
+ * @return the public exponent <code>e</code>.
+ */
+ public BigInteger getE()
+ {
+ return e;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link RSAKey} and has the same RSA parameter values as this one.</p>
+ *
+ * @param obj the other non-null RSA key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(final Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof RSAKey))
+ {
+ return false;
+ }
+ final RSAKey that = (RSAKey) obj;
+ return n.equals(that.getModulus());
+ }
+
+ // abstract methods to be implemented by subclasses ------------------------
+
+ public abstract byte[] getEncoded(int format);
+}
diff --git a/gnu/java/security/key/rsa/GnuRSAPrivateKey.java b/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
new file mode 100644
index 000000000..851ea271b
--- /dev/null
+++ b/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
@@ -0,0 +1,255 @@
+/* GnuRSAPrivateKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+
+/**
+ * <p>An object that embodies an RSA private key.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class GnuRSAPrivateKey extends GnuRSAKey implements PrivateKey,
+ RSAPrivateCrtKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The first prime divisor of the modulus. */
+ private final BigInteger p;
+
+ /** The second prime divisor of the modulus. */
+ private final BigInteger q;
+
+ /** The public exponent of an RSA key. */
+ // private final BigInteger e;
+ /** The private exponent of an RSA private key. */
+ private final BigInteger d;
+
+ /** The first factor's exponent. */
+ private final BigInteger dP;
+
+ /** The second factor's exponent. */
+ private final BigInteger dQ;
+
+ /** The CRT (Chinese Remainder Theorem) coefficient. */
+ private final BigInteger qInv;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor.</p>
+ *
+ * @param p the modulus first prime divisor.
+ * @param q the modulus second prime divisor.
+ * @param e the public exponent.
+ * @param d the private exponent.
+ */
+ public GnuRSAPrivateKey(final BigInteger p, final BigInteger q,
+ final BigInteger e, final BigInteger d)
+ {
+ // super(p.multiply(q));
+ super(p.multiply(q), e);
+
+ this.p = p;
+ this.q = q;
+ // this.e = e;
+ this.d = d;
+
+ // the exponents dP and dQ are positive integers less than p and q
+ // respectively satisfying
+ // e * dP = 1 (mod p-1);
+ // e * dQ = 1 (mod q-1),
+ dP = e.modInverse(p.subtract(BigInteger.ONE));
+ dQ = e.modInverse(q.subtract(BigInteger.ONE));
+ // and the CRT coefficient qInv is a positive integer less than p
+ // satisfying
+ // q * qInv = 1 (mod p).
+ qInv = q.modInverse(p);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A class method that takes the output of the <code>encodePrivateKey()</code>
+ * method of an RSA keypair codec object (an instance implementing
+ * {@link gnu.crypto.key.IKeyPairCodec} for RSA keys, and re-constructs an
+ * instance of this object.</p>
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an instance of this object.
+ * @throws IllegalArgumentException if the byte sequence does not represent a
+ * valid encoding of an instance of this object.
+ */
+ public static GnuRSAPrivateKey valueOf(final byte[] k)
+ {
+ // check magic...
+ // we should parse here enough bytes to know which codec to use, and
+ // direct the byte array to the appropriate codec. since we only have one
+ // codec, we could have immediately tried it; nevertheless since testing
+ // one byte is cheaper than instatiating a codec that will fail we test
+ // the first byte before we carry on.
+ if (k[0] == Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0])
+ {
+ // it's likely to be in raw format. get a raw codec and hand it over
+ final IKeyPairCodec codec = new RSAKeyPairRawCodec();
+ return (GnuRSAPrivateKey) codec.decodePrivateKey(k);
+ }
+ else
+ {
+ throw new IllegalArgumentException("magic");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.RSAPrivateCrtKey interface implementation ------
+
+ // public BigInteger getPublicExponent() {
+ // return e;
+ // }
+
+ public BigInteger getPrimeP()
+ {
+ return p;
+ }
+
+ public BigInteger getPrimeQ()
+ {
+ return q;
+ }
+
+ public BigInteger getPrimeExponentP()
+ {
+ return dP;
+ }
+
+ public BigInteger getPrimeExponentQ()
+ {
+ return dQ;
+ }
+
+ public BigInteger getCrtCoefficient()
+ {
+ return qInv;
+ }
+
+ // java.security.interfaces.RSAPrivateKey interface implementation ---------
+
+ public BigInteger getPrivateExponent()
+ {
+ return d;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this private key according to the
+ * designated format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @throws IllegalArgumentException if the format is not supported.
+ * @see gnu.crypto.key.rsa.RSAKeyPairRawCodec
+ */
+ public byte[] getEncoded(final int format)
+ {
+ final byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new RSAKeyPairRawCodec().encodePrivateKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("format");
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * this class and has the same RSA parameter values as this one.</p>
+ *
+ * @param obj the other non-null RSA key to compare to.
+ * @return <code>true</code> if the designated object is of the same type
+ * and value as this one.
+ */
+ public boolean equals(final Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj instanceof RSAPrivateKey)
+ {
+ final RSAPrivateKey that = (RSAPrivateKey) obj;
+ return super.equals(that) && d.equals(that.getPrivateExponent());
+ }
+ if (obj instanceof RSAPrivateCrtKey)
+ {
+ final RSAPrivateCrtKey that = (RSAPrivateCrtKey) obj;
+ return super.equals(that) && p.equals(that.getPrimeP())
+ && q.equals(that.getPrimeQ())
+ && dP.equals(that.getPrimeExponentP())
+ && dQ.equals(that.getPrimeExponentQ())
+ && qInv.equals(that.getCrtCoefficient());
+ }
+ return false;
+ }
+}
diff --git a/gnu/java/security/key/rsa/GnuRSAPublicKey.java b/gnu/java/security/key/rsa/GnuRSAPublicKey.java
new file mode 100644
index 000000000..0e5cdb4cf
--- /dev/null
+++ b/gnu/java/security/key/rsa/GnuRSAPublicKey.java
@@ -0,0 +1,179 @@
+/* GnuRSAPublicKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * <p>An object that encapsulates an RSA public key.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class GnuRSAPublicKey extends GnuRSAKey implements PublicKey,
+ RSAPublicKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The public exponent of an RSA public key. */
+ // private final BigInteger e;
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+ /**
+ * <p>Trivial constructor.</p>
+ *
+ * @param n the modulus.
+ * @param e the public exponent.
+ */
+ public GnuRSAPublicKey(final BigInteger n, final BigInteger e)
+ {
+ // super(n);
+ super(n, e);
+ //
+ // this.e = e;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A class method that takes the output of the <code>encodePublicKey()</code>
+ * method of an RSA keypair codec object (an instance implementing
+ * {@link gnu.crypto.key.IKeyPairCodec} for RSA keys, and re-constructs an
+ * instance of this object.</p>
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an instance of this object.
+ * @throws IllegalArgumentException if the byte sequence does not represent a
+ * valid encoding of an instance of this object.
+ */
+ public static GnuRSAPublicKey valueOf(final byte[] k)
+ {
+ // check magic...
+ // we should parse here enough bytes to know which codec to use, and
+ // direct the byte array to the appropriate codec. since we only have one
+ // codec, we could have immediately tried it; nevertheless since testing
+ // one byte is cheaper than instatiating a codec that will fail we test
+ // the first byte before we carry on.
+ if (k[0] == Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0])
+ {
+ // it's likely to be in raw format. get a raw codec and hand it over
+ final IKeyPairCodec codec = new RSAKeyPairRawCodec();
+ return (GnuRSAPublicKey) codec.decodePublicKey(k);
+ }
+ else
+ {
+ throw new IllegalArgumentException("magic");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.RSAPublicKey interface implementation ----------
+
+ // public BigInteger getPublicExponent() {
+ // return e;
+ // }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this public key according to the designated
+ * format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @throws IllegalArgumentException if the format is not supported.
+ * @see RSAKeyPairRawCodec
+ */
+ public byte[] getEncoded(final int format)
+ {
+ final byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new RSAKeyPairRawCodec().encodePublicKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("format");
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * this class and has the same RSA parameter values as this one.</p>
+ *
+ * @param obj the other non-null RSA key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(final Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof RSAPublicKey))
+ {
+ return false;
+ }
+ final RSAPublicKey that = (RSAPublicKey) obj;
+ // return super.equals(that) && e.equals(that.getPublicExponent());
+ return super.equals(that)
+ && getPublicExponent().equals(that.getPublicExponent());
+ }
+}
diff --git a/gnu/java/security/key/rsa/RSAKeyPairGenerator.java b/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
new file mode 100644
index 000000000..a9738e751
--- /dev/null
+++ b/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
@@ -0,0 +1,236 @@
+/* RSAKeyPairGenerator.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairGenerator;
+import gnu.java.security.util.Prime2;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.RSAKeyGenParameterSpec;
+import java.util.Map;
+
+/**
+ * <p>A key-pair generator for asymetric keys to use in conjunction with the RSA
+ * scheme.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix</a>, part B. Primitive
+ * specification and supporting documentation. Jakob Jonsson and Burt Kaliski.
+ * </li>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac/">Handbook of Applied
+ * Cryptography</a>, Alfred J. Menezes, Paul C. van Oorschot and Scott A.
+ * Vanstone. Section 11.3 RSA and related signature schemes.</li>
+ * </ol>
+ */
+public class RSAKeyPairGenerator implements IKeyPairGenerator
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The BigInteger constant 1. */
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ /** The BigInteger constant 2. */
+ private static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ /** Property name of the length (Integer) of the modulus of an RSA key. */
+ public static final String MODULUS_LENGTH = "gnu.crypto.rsa.L";
+
+ /**
+ * Property name of an optional {@link SecureRandom} instance to use. The
+ * default is to use a classloader singleton from {@link PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.rsa.prng";
+
+ /**
+ * Property name of an optional {@link RSAKeyGenParameterSpec} instance to
+ * use for this generator's <code>n</code>, and <code>e</code> values. The
+ * default is to generate <code>n</code> and use a fixed value for
+ * <code>e</.code> (Fermat's F4 number).
+ */
+ public static final String RSA_PARAMETERS = "gnu.crypto.rsa.params";
+
+ /** Default value for the modulus length. */
+ private static final int DEFAULT_MODULUS_LENGTH = 1024;
+
+ /** The desired bit length of the modulus. */
+ private int L;
+
+ /**
+ * This implementation uses, by default, Fermat's F4 number as the public
+ * exponent.
+ */
+ private BigInteger e = BigInteger.valueOf(65537L);
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
+
+ public String name()
+ {
+ return Registry.RSA_KPG;
+ }
+
+ /**
+ * <p>Configures this instance.</p>
+ *
+ * @param attributes the map of name/value pairs to use.
+ * @exception IllegalArgumentException if the designated MODULUS_LENGTH
+ * value is less than 1024.
+ */
+ public void setup(Map attributes)
+ {
+ // do we have a SecureRandom, or should we use our own?
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ // are we given a set of RSA params or we shall use our own?
+ RSAKeyGenParameterSpec params = (RSAKeyGenParameterSpec) attributes.get(RSA_PARAMETERS);
+
+ // find out the modulus length
+ if (params != null)
+ {
+ L = params.getKeysize();
+ e = params.getPublicExponent();
+ }
+ else
+ {
+ Integer l = (Integer) attributes.get(MODULUS_LENGTH);
+ L = (l == null ? DEFAULT_MODULUS_LENGTH : l.intValue());
+ }
+
+ if (L < 1024)
+ {
+ throw new IllegalArgumentException(MODULUS_LENGTH);
+ }
+ }
+
+ /**
+ * <p>The algorithm used here is described in <i>nessie-pss-B.pdf</i>
+ * document which is part of the RSA-PSS submission to NESSIE.</p>
+ *
+ * @return an RSA keypair.
+ */
+ public KeyPair generate()
+ {
+ BigInteger p, q, n, d;
+
+ // 1. Generate a prime p in the interval [2**(M-1), 2**M - 1], where
+ // M = CEILING(L/2), and such that GCD(p, e) = 1
+ int M = (L + 1) / 2;
+ BigInteger lower = TWO.pow(M - 1);
+ BigInteger upper = TWO.pow(M).subtract(ONE);
+ byte[] kb = new byte[(M + 7) / 8]; // enough bytes to frame M bits
+ step1: while (true)
+ {
+ nextRandomBytes(kb);
+ p = new BigInteger(1, kb).setBit(0);
+ if (p.compareTo(lower) >= 0 && p.compareTo(upper) <= 0
+ && Prime2.isProbablePrime(p) && p.gcd(e).equals(ONE))
+ {
+ break step1;
+ }
+ }
+
+ // 2. Generate a prime q such that the product of p and q is an L-bit
+ // number, and such that GCD(q, e) = 1
+ step2: while (true)
+ {
+ nextRandomBytes(kb);
+ q = new BigInteger(1, kb).setBit(0);
+ n = p.multiply(q);
+ if (n.bitLength() == L && Prime2.isProbablePrime(q)
+ && q.gcd(e).equals(ONE))
+ {
+ break step2;
+ }
+
+ // TODO: test for p != q
+ }
+
+ // TODO: ensure p < q
+
+ // 3. Put n = pq. The public key is (n, e).
+ // 4. Compute the parameters necessary for the private key K (see
+ // Section 2.2).
+ BigInteger phi = p.subtract(ONE).multiply(q.subtract(ONE));
+ d = e.modInverse(phi);
+
+ // 5. Output the public key and the private key.
+ PublicKey pubK = new GnuRSAPublicKey(n, e);
+ PrivateKey secK = new GnuRSAPrivateKey(p, q, e, d);
+
+ return new KeyPair(pubK, secK);
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+}
diff --git a/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java b/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java
new file mode 100644
index 000000000..fb7cea99e
--- /dev/null
+++ b/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java
@@ -0,0 +1,332 @@
+/* RSAKeyPairRawCodec.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>An object that implements the {@link IKeyPairCodec} interface for the
+ * <i>Raw</i> format to use with RSA keypairs.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RSAKeyPairRawCodec implements IKeyPairCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.key.IKeyPairCodec interface implementation -------------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated RSA public key according to
+ * the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for an RSA public key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_RSA_PUBLIC_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>n</code> (the modulus) in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>n</code>,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>e</code> (the public exponent) in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>e</code>.</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @exception IllegalArgumentException if the designated key is not an RSA
+ * one.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (!(key instanceof GnuRSAPublicKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ GnuRSAPublicKey rsaKey = (GnuRSAPublicKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // n
+ byte[] buffer = rsaKey.getModulus().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // e
+ buffer = rsaKey.getPublicExponent().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PublicKey decodePublicKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // n
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger n = new BigInteger(1, buffer);
+
+ // e
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger e = new BigInteger(1, buffer);
+
+ return new GnuRSAPublicKey(n, e);
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated RSA private key according to
+ * the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for an RSA private key, in this implementation,
+ * is a byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_RSA_PRIVATE_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>p</code> (the first prime factor of the modulus) in internet
+ * order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>p</code>,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>q</code> (the second prime factor of the modulus) in internet
+ * order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>q</code>,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>e</code> (the public exponent) in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>e</code>,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>d</code> (the private exponent) in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>d</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (!(key instanceof GnuRSAPrivateKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ GnuRSAPrivateKey rsaKey = (GnuRSAPrivateKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // p
+ byte[] buffer = rsaKey.getPrimeP().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // q
+ buffer = rsaKey.getPrimeQ().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // e
+ buffer = rsaKey.getPublicExponent().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // d
+ buffer = rsaKey.getPrivateExponent().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PrivateKey decodePrivateKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // p
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger p = new BigInteger(1, buffer);
+
+ // q
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger q = new BigInteger(1, buffer);
+
+ // e
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger e = new BigInteger(1, buffer);
+
+ // d
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger d = new BigInteger(1, buffer);
+
+ return new GnuRSAPrivateKey(p, q, e, d);
+ }
+}
diff --git a/gnu/java/security/prng/BasePRNG.java b/gnu/java/security/prng/BasePRNG.java
new file mode 100644
index 000000000..13aa33650
--- /dev/null
+++ b/gnu/java/security/prng/BasePRNG.java
@@ -0,0 +1,195 @@
+/* BasePRNG.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import java.util.Map;
+
+/**
+ * <p>An abstract class to facilitate implementing PRNG algorithms.</p>
+ */
+public abstract class BasePRNG implements IRandom
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of the PRNG algorithm. */
+ protected String name;
+
+ /** Indicate if this instance has already been initialised or not. */
+ protected boolean initialised;
+
+ /** A temporary buffer to serve random bytes. */
+ protected byte[] buffer;
+
+ /** The index into buffer of where the next byte will come from. */
+ protected int ndx;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name of this instance.
+ */
+ protected BasePRNG(String name)
+ {
+ super();
+
+ this.name = name;
+ initialised = false;
+ buffer = new byte[0];
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IRandom interface implementation ----------------------------------------
+
+ public String name()
+ {
+ return name;
+ }
+
+ public void init(Map attributes)
+ {
+ this.setup(attributes);
+
+ ndx = 0;
+ initialised = true;
+ }
+
+ public byte nextByte() throws IllegalStateException, LimitReachedException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException();
+ }
+ return nextByteInternal();
+ }
+
+ public void nextBytes(byte[] out) throws IllegalStateException,
+ LimitReachedException
+ {
+ nextBytes(out, 0, out.length);
+ }
+
+ public void nextBytes(byte[] out, int offset, int length)
+ throws IllegalStateException, LimitReachedException
+ {
+ if (!initialised)
+ throw new IllegalStateException("not initialized");
+
+ if (length == 0)
+ return;
+
+ if (offset < 0 || length < 0 || offset + length > out.length)
+ throw new ArrayIndexOutOfBoundsException("offset=" + offset + " length="
+ + length + " limit="
+ + out.length);
+
+ if (ndx >= buffer.length)
+ {
+ fillBlock();
+ ndx = 0;
+ }
+ int count = 0;
+ while (count < length)
+ {
+ int amount = Math.min(buffer.length - ndx, length - count);
+ System.arraycopy(buffer, ndx, out, offset + count, amount);
+ count += amount;
+ ndx += amount;
+ if (ndx >= buffer.length)
+ {
+ fillBlock();
+ ndx = 0;
+ }
+ }
+ }
+
+ public void addRandomByte(byte b)
+ {
+ throw new UnsupportedOperationException("random state is non-modifiable");
+ }
+
+ public void addRandomBytes(byte[] buffer)
+ {
+ addRandomBytes(buffer, 0, buffer.length);
+ }
+
+ public void addRandomBytes(byte[] buffer, int offset, int length)
+ {
+ throw new UnsupportedOperationException("random state is non-modifiable");
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public boolean isInitialised()
+ {
+ return initialised;
+ }
+
+ private byte nextByteInternal() throws LimitReachedException
+ {
+ if (ndx >= buffer.length)
+ {
+ this.fillBlock();
+ ndx = 0;
+ }
+
+ return buffer[ndx++];
+ }
+
+ // abstract methods to implement by subclasses -----------------------------
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+
+ public abstract void setup(Map attributes);
+
+ public abstract void fillBlock() throws LimitReachedException;
+}
diff --git a/gnu/java/security/prng/EntropySource.java b/gnu/java/security/prng/EntropySource.java
new file mode 100644
index 000000000..260c668f8
--- /dev/null
+++ b/gnu/java/security/prng/EntropySource.java
@@ -0,0 +1,62 @@
+/* EntropySource.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+/**
+ * A generic interface for adding random bytes to an entropy pool.
+ */
+public interface EntropySource
+{
+
+ /**
+ * Returns the estimated quality of this source. This value should be
+ * between 0 and 100 (the running quality is computed as a percentage,
+ * 100 percent being perfect-quality).
+ *
+ * @return The quality.
+ */
+ double quality();
+
+ /**
+ * Returns a new buffer with the next random bytes to add.
+ *
+ * @return The next random bytes.
+ */
+ byte[] nextBytes();
+} \ No newline at end of file
diff --git a/gnu/java/security/prng/IRandom.java b/gnu/java/security/prng/IRandom.java
new file mode 100644
index 000000000..2c89e7ad5
--- /dev/null
+++ b/gnu/java/security/prng/IRandom.java
@@ -0,0 +1,180 @@
+/* IRandom.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import java.util.Map;
+
+/**
+ * <p>The basic visible methods of any pseudo-random number generator.</p>
+ *
+ * <p>The [HAC] defines a PRNG (as implemented in this library) as follows:</p>
+ *
+ * <ul>
+ * <li>"5.6 Definition: A pseudorandom bit generator (PRBG) is said to pass
+ * the <em>next-bit test</em> if there is no polynomial-time algorithm which,
+ * on input of the first <code>L</code> bits of an output sequence <code>S</code>,
+ * can predict the <code>(L+1)</code>st bit of <code>S</code> with a
+ * probability significantly grater than <code>1/2</code>."</li>
+ *
+ * <li>"5.8 Definition: A PRBG that passes the <em>next-bit test</em>
+ * (possibly under some plausible but unproved mathematical assumption such
+ * as the intractability of factoring integers) is called a
+ * <em>cryptographically secure pseudorandom bit generator</em> (CSPRBG)."</li>
+ * </ul>
+ *
+ * <p><b>IMPLEMENTATION NOTE</b>: Although all the concrete classes in this
+ * package implement the {@link Cloneable} interface, it is important to note
+ * here that such an operation, for those algorithms that use an underlting
+ * symmetric key block cipher, <b>DOES NOT</b> clone any session key material
+ * that may have been used in initialising the source PRNG (the instance to be
+ * cloned). Instead a clone of an already initialised PRNG, that uses and
+ * underlying symmetric key block cipher, is another instance with a clone of
+ * the same cipher that operates with the <b>same block size</b> but without any
+ * knowledge of neither key material nor key size.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
+ * Applied Cryptography.<br>
+ * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
+ * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
+ * </ol>
+ */
+public interface IRandom extends Cloneable
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of this instance.</p>
+ *
+ * @return the canonical name of this instance. */
+ String name();
+
+ /**
+ * <p>Initialises the pseudo-random number generator scheme with the
+ * appropriate attributes.</p>
+ *
+ * @param attributes a set of name-value pairs that describe the desired
+ * future instance behaviour.
+ * @exception IllegalArgumentException if at least one of the defined name/
+ * value pairs contains invalid data.
+ */
+ void init(Map attributes);
+
+ /**
+ * <p>Returns the next 8 bits of random data generated from this instance.</p>
+ *
+ * @return the next 8 bits of random data generated from this instance.
+ * @exception IllegalStateException if the instance is not yet initialised.
+ * @exception LimitReachedException if this instance has reached its
+ * theoretical limit for generating non-repetitive pseudo-random data.
+ */
+ byte nextByte() throws IllegalStateException, LimitReachedException;
+
+ /**
+ * <p>Fills the designated byte array, starting from byte at index
+ * <code>offset</code>, for a maximum of <code>length</code> bytes with the
+ * output of this generator instance.
+ *
+ * @param out the placeholder to contain the generated random bytes.
+ * @param offset the starting index in <i>out</i> to consider. This method
+ * does nothing if this parameter is not within <code>0</code> and
+ * <code>out.length</code>.
+ * @param length the maximum number of required random bytes. This method
+ * does nothing if this parameter is less than <code>1</code>.
+ * @exception IllegalStateException if the instance is not yet initialised.
+ * @exception LimitReachedException if this instance has reached its
+ * theoretical limit for generating non-repetitive pseudo-random data.
+ */
+ void nextBytes(byte[] out, int offset, int length)
+ throws IllegalStateException, LimitReachedException;
+
+ /**
+ * <p>Supplement, or possibly replace, the random state of this PRNG with
+ * a random byte.</p>
+ *
+ * <p>Implementations are not required to implement this method in any
+ * meaningful way; this may be a no-operation, and implementations may
+ * throw an {@link UnsupportedOperationException}.</p>
+ *
+ * @param b The byte to add.
+ */
+ void addRandomByte(byte b);
+
+ /**
+ * <p>Supplement, or possibly replace, the random state of this PRNG with
+ * a sequence of new random bytes.</p>
+ *
+ * <p>Implementations are not required to implement this method in any
+ * meaningful way; this may be a no-operation, and implementations may
+ * throw an {@link UnsupportedOperationException}.</p>
+ *
+ * @param in The buffer of new random bytes to add.
+ */
+ void addRandomBytes(byte[] in);
+
+ /**
+ * <p>Supplement, or possibly replace, the random state of this PRNG with
+ * a sequence of new random bytes.</p>
+ *
+ * <p>Implementations are not required to implement this method in any
+ * meaningful way; this may be a no-operation, and implementations may
+ * throw an {@link UnsupportedOperationException}.</p>
+ *
+ * @param in The buffer of new random bytes to add.
+ * @param offset The offset from whence to begin reading random bytes.
+ * @param length The number of random bytes to add.
+ * @exception IndexOutOfBoundsException If <i>offset</i>, <i>length</i>,
+ * or <i>offset</i>+<i>length</i> is out of bounds.
+ */
+ void addRandomBytes(byte[] in, int offset, int length);
+
+ /**
+ * <p>Returns a clone copy of this instance.</p>
+ *
+ * @return a clone copy of this instance.
+ */
+ Object clone() throws CloneNotSupportedException;
+} \ No newline at end of file
diff --git a/gnu/java/security/prng/LimitReachedException.java b/gnu/java/security/prng/LimitReachedException.java
new file mode 100644
index 000000000..2fd8bfa7f
--- /dev/null
+++ b/gnu/java/security/prng/LimitReachedException.java
@@ -0,0 +1,69 @@
+/* LimitReachedException.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+/**
+ * A checked exception that indicates that a pseudo random number generated has
+ * reached its theoretical limit in generating random bytes.
+ */
+public class LimitReachedException extends Exception
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public LimitReachedException()
+ {
+ super();
+ }
+
+ public LimitReachedException(String msg)
+ {
+ super(msg);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instant methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/java/security/prng/MDGenerator.java b/gnu/java/security/prng/MDGenerator.java
new file mode 100644
index 000000000..b43ca33a6
--- /dev/null
+++ b/gnu/java/security/prng/MDGenerator.java
@@ -0,0 +1,124 @@
+/* MDGenerator.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+
+import java.util.Map;
+
+/**
+ * <p>A simple pseudo-random number generator that relies on a hash algorithm,
+ * that (a) starts its operation by hashing a <code>seed</code>, and then (b)
+ * continuously re-hashing its output. If no hash algorithm name is specified
+ * in the {@link Map} of attributes used to initialise the instance then the
+ * SHA-160 algorithm is used as the underlying hash function. Also, if no
+ * <code>seed</code> is given, an empty octet sequence is used.</p>
+ */
+public class MDGenerator extends BasePRNG implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Property name of underlying hash algorithm for this generator. */
+ public static final String MD_NAME = "gnu.crypto.prng.md.hash.name";
+
+ /** Property name of seed material. */
+ public static final String SEEED = "gnu.crypto.prng.md.seed";
+
+ /** The underlying hash instance. */
+ private IMessageDigest md;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public MDGenerator()
+ {
+ super(Registry.MD_PRNG);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in BaseRandom ------------------------
+
+ public void setup(Map attributes)
+ {
+ // find out which hash to use
+ String underlyingMD = (String) attributes.get(MD_NAME);
+ if (underlyingMD == null)
+ {
+ if (md == null)
+ { // happy birthday
+ // ensure we have a reliable implementation of this hash
+ md = HashFactory.getInstance(Registry.SHA160_HASH);
+ }
+ else
+ { // a clone. reset it for reuse
+ md.reset();
+ }
+ }
+ else
+ { // ensure we have a reliable implementation of this hash
+ md = HashFactory.getInstance(underlyingMD);
+ }
+
+ // get the seeed
+ byte[] seed = (byte[]) attributes.get(SEEED);
+ if (seed == null)
+ {
+ seed = new byte[0];
+ }
+
+ md.update(seed, 0, seed.length);
+ }
+
+ public void fillBlock() throws LimitReachedException
+ {
+ IMessageDigest mdc = (IMessageDigest) md.clone();
+ buffer = mdc.digest();
+ md.update(buffer, 0, buffer.length);
+ }
+}
diff --git a/gnu/java/security/prng/PRNGFactory.java b/gnu/java/security/prng/PRNGFactory.java
new file mode 100644
index 000000000..8b5141456
--- /dev/null
+++ b/gnu/java/security/prng/PRNGFactory.java
@@ -0,0 +1,109 @@
+/* PRNGFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import gnu.java.security.Registry;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <p>A Factory to instantiate pseudo random number generators.</p>
+ */
+public class PRNGFactory implements Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce <i>Singleton</i> pattern. */
+ protected PRNGFactory()
+ {
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a padding algorithm given its name.</p>
+ *
+ * @param prng the case-insensitive name of the PRNG.
+ * @return an instance of the pseudo-random number generator.
+ * @exception InternalError if the implementation does not pass its self-
+ * test.
+ */
+ public static final IRandom getInstance(String prng)
+ {
+ if (prng == null)
+ {
+ return null;
+ }
+
+ prng = prng.trim();
+ IRandom result = null;
+ if (prng.equalsIgnoreCase(MD_PRNG))
+ {
+ result = new MDGenerator();
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of names of padding algorithms supported by this
+ * <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of pseudo-random number generator algorithm names
+ * (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(MD_PRNG);
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/prng/RandomEvent.java b/gnu/java/security/prng/RandomEvent.java
new file mode 100644
index 000000000..c07062125
--- /dev/null
+++ b/gnu/java/security/prng/RandomEvent.java
@@ -0,0 +1,82 @@
+/* RandomEvent.java -- an event with random data.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import java.util.EventObject;
+
+/**
+ * An interface for entropy accumulators that will be notified of random
+ * events.
+ */
+public class RandomEvent extends EventObject
+{
+
+ private final byte sourceNumber;
+
+ private final byte poolNumber;
+
+ private final byte[] data;
+
+ public RandomEvent(Object source, byte sourceNumber, byte poolNumber,
+ byte[] data)
+ {
+ super(source);
+ this.sourceNumber = sourceNumber;
+ this.poolNumber = poolNumber;
+ if (data.length == 0 || data.length > 32)
+ throw new IllegalArgumentException(
+ "random events take between 1 and 32 bytes of data");
+ this.data = (byte[]) data.clone();
+ }
+
+ public byte getSourceNumber()
+ {
+ return sourceNumber;
+ }
+
+ public byte getPoolNumber()
+ {
+ return poolNumber;
+ }
+
+ public byte[] getData()
+ {
+ return data;
+ }
+} \ No newline at end of file
diff --git a/gnu/java/security/prng/RandomEventListener.java b/gnu/java/security/prng/RandomEventListener.java
new file mode 100644
index 000000000..1dc14619f
--- /dev/null
+++ b/gnu/java/security/prng/RandomEventListener.java
@@ -0,0 +1,50 @@
+/* RandomEventListener.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import java.util.EventListener;
+
+/**
+ * An interface for entropy accumulators that will be notified of random
+ * events.
+ */
+public interface RandomEventListener extends EventListener
+{
+ void addRandomEvent(RandomEvent event);
+} \ No newline at end of file
diff --git a/gnu/java/security/provider/Gnu.java b/gnu/java/security/provider/Gnu.java
index e553bbcbd..849015214 100644
--- a/gnu/java/security/provider/Gnu.java
+++ b/gnu/java/security/provider/Gnu.java
@@ -97,11 +97,25 @@ public final class Gnu extends Provider
put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "SHA1withRSA");
put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
+ put("Signature.DSS/RAW", gnu.java.security.jce.sig.DSSRawSignatureSpi.class.getName());
+ put("Signature.DSS/RAW KeySize", "1024");
+ put("Signature.DSS/RAW ImplementedIn", "Software");
+ put("Signature.RSA-PSS/RAW", gnu.java.security.jce.sig.RSAPSSRawSignatureSpi.class.getName());
+ put("Signature.RSA-PSS/RAW KeySize", "1024");
+ put("Signature.RSA-PSS/RAW ImplementedIn", "Software");
+
// Key Pair Generator
put("KeyPairGenerator.DSA",
gnu.java.security.provider.DSAKeyPairGenerator.class.getName());
put("KeyPairGenerator.DiffieHellman", DiffieHellmanKeyPairGeneratorImpl.class.getName ());
+ put("KeyPairGenerator.DSS", gnu.java.security.jce.sig.DSSKeyPairGeneratorSpi.class.getName());
+ put("KeyPairGenerator.DSS KeySize", "1024");
+ put("KeyPairGenerator.DSS ImplementedIn", "Software");
+ put("KeyPairGenerator.RSA", gnu.java.security.jce.sig.RSAKeyPairGeneratorSpi.class.getName());
+ put("KeyPairGenerator.RSA KeySize", "1024");
+ put("KeyPairGenerator.RSA ImplementedIn", "Software");
+
put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
@@ -128,13 +142,57 @@ public final class Gnu extends Provider
put("Alg.Alias.KeyFactory.DH", "DiffieHellman");
// Message Digests
- put("MessageDigest.SHA", gnu.java.security.provider.SHA.class.getName());
- put("MessageDigest.MD5", gnu.java.security.provider.MD5.class.getName());
+// put("MessageDigest.SHA", gnu.java.security.provider.SHA.class.getName());
+// put("MessageDigest.MD5", gnu.java.security.provider.MD5.class.getName());
// Format "Alias", "Actual Name"
- put("Alg.Alias.MessageDigest.SHA1", "SHA");
- put("Alg.Alias.MessageDigest.SHA-1", "SHA");
- put("Alg.Alias.MessageDigest.SHA-160", "SHA");
+// put("Alg.Alias.MessageDigest.SHA1", "SHA");
+// put("Alg.Alias.MessageDigest.SHA-1", "SHA");
+// put("Alg.Alias.MessageDigest.SHA-160", "SHA");
+
+ put("MessageDigest.HAVAL", gnu.java.security.jce.hash.HavalSpi.class.getName());
+ put("MessageDigest.HAVAL ImplementedIn", "Software");
+ put("MessageDigest.MD2", gnu.java.security.jce.hash.MD2Spi.class.getName());
+ put("MessageDigest.MD2 ImplementedIn", "Software");
+ put("MessageDigest.MD4", gnu.java.security.jce.hash.MD4Spi.class.getName());
+ put("MessageDigest.MD4 ImplementedIn", "Software");
+ put("MessageDigest.MD5", gnu.java.security.jce.hash.MD5Spi.class.getName());
+ put("MessageDigest.MD5 ImplementedIn", "Software");
+ put("MessageDigest.RIPEMD128", gnu.java.security.jce.hash.RipeMD128Spi.class.getName());
+ put("MessageDigest.RIPEMD128 ImplementedIn", "Software");
+ put("MessageDigest.RIPEMD160", gnu.java.security.jce.hash.RipeMD160Spi.class.getName());
+ put("MessageDigest.RIPEMD160 ImplementedIn", "Software");
+ put("MessageDigest.SHA-160", gnu.java.security.jce.hash.Sha160Spi.class.getName());
+ put("MessageDigest.SHA-160 ImplementedIn", "Software");
+ put("MessageDigest.SHA-256", gnu.java.security.jce.hash.Sha256Spi.class.getName());
+ put("MessageDigest.SHA-256 ImplementedIn", "Software");
+ put("MessageDigest.SHA-384", gnu.java.security.jce.hash.Sha384Spi.class.getName());
+ put("MessageDigest.SHA-384 ImplementedIn", "Software");
+ put("MessageDigest.SHA-512", gnu.java.security.jce.hash.Sha512Spi.class.getName());
+ put("MessageDigest.SHA-512 ImplementedIn", "Software");
+ put("MessageDigest.TIGER", gnu.java.security.jce.hash.TigerSpi.class.getName());
+ put("MessageDigest.TIGER ImplementedIn", "Software");
+ put("MessageDigest.WHIRLPOOL", gnu.java.security.jce.hash.WhirlpoolSpi.class.getName());
+ put("MessageDigest.WHIRLPOOL ImplementedIn", "Software");
+
+ put("Alg.Alias.MessageDigest.SHS", "SHA-160");
+ put("Alg.Alias.MessageDigest.SHA", "SHA-160");
+ put("Alg.Alias.MessageDigest.SHA1", "SHA-160");
+ put("Alg.Alias.MessageDigest.SHA-1", "SHA-160");
+ put("Alg.Alias.MessageDigest.SHA2-256", "SHA-256");
+ put("Alg.Alias.MessageDigest.SHA2-384", "SHA-384");
+ put("Alg.Alias.MessageDigest.SHA2-512", "SHA-512");
+ put("Alg.Alias.MessageDigest.SHA256", "SHA-256");
+ put("Alg.Alias.MessageDigest.SHA384", "SHA-384");
+ put("Alg.Alias.MessageDigest.SHA512", "SHA-512");
+ put("Alg.Alias.MessageDigest.RIPEMD-160", "RIPEMD160");
+ put("Alg.Alias.MessageDigest.RIPEMD-128", "RIPEMD128");
+ put("Alg.Alias.MessageDigest.OID.1.2.840.11359.2.2", "MD2");
+ put("Alg.Alias.MessageDigest.1.2.840.11359.2.2", "MD2");
+ put("Alg.Alias.MessageDigest.OID.1.2.840.11359.2.5", "MD5");
+ put("Alg.Alias.MessageDigest.1.2.840.11359.2.5", "MD5");
+ put("Alg.Alias.MessageDigest.OID.1.3.14.3.2.26", "SHA1");
+ put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA1");
// Algorithm Parameters
put("AlgorithmParameters.DSA",
@@ -153,6 +211,41 @@ public final class Gnu extends Provider
put("SecureRandom.SHA1PRNG",
gnu.java.security.provider.SHA1PRNG.class.getName());
+ put("SecureRandom.MD2PRNG", gnu.java.security.jce.prng.MD2RandomSpi.class.getName());
+ put("SecureRandom.MD2PRNG ImplementedIn", "Software");
+ put("SecureRandom.MD4PRNG", gnu.java.security.jce.prng.MD4RandomSpi.class.getName());
+ put("SecureRandom.MD4PRNG ImplementedIn", "Software");
+ put("SecureRandom.MD5PRNG", gnu.java.security.jce.prng.MD5RandomSpi.class.getName());
+ put("SecureRandom.MD5PRNG ImplementedIn", "Software");
+ put("SecureRandom.RIPEMD128PRNG", gnu.java.security.jce.prng.RipeMD128RandomSpi.class.getName());
+ put("SecureRandom.RIPEMD128PRNG ImplementedIn", "Software");
+ put("SecureRandom.RIPEMD160PRNG", gnu.java.security.jce.prng.RipeMD160RandomSpi.class.getName());
+ put("SecureRandom.RIPEMD160PRNG ImplementedIn", "Software");
+ put("SecureRandom.SHA-160PRNG", gnu.java.security.jce.prng.Sha160RandomSpi.class.getName());
+ put("SecureRandom.SHA-160PRNG ImplementedIn", "Software");
+ put("SecureRandom.SHA-256PRNG", gnu.java.security.jce.prng.Sha256RandomSpi.class.getName());
+ put("SecureRandom.SHA-256PRNG ImplementedIn", "Software");
+ put("SecureRandom.SHA-384PRNG", gnu.java.security.jce.prng.Sha384RandomSpi.class.getName());
+ put("SecureRandom.SHA-384PRNG ImplementedIn", "Software");
+ put("SecureRandom.SHA-512PRNG", gnu.java.security.jce.prng.Sha512RandomSpi.class.getName());
+ put("SecureRandom.SHA-512PRNG ImplementedIn", "Software");
+ put("SecureRandom.TIGERPRNG", gnu.java.security.jce.prng.TigerRandomSpi.class.getName());
+ put("SecureRandom.TIGERPRNG ImplementedIn", "Software");
+ put("SecureRandom.HAVALPRNG", gnu.java.security.jce.prng.HavalRandomSpi.class.getName());
+ put("SecureRandom.HAVALPRNG ImplementedIn", "Software");
+ put("SecureRandom.WHIRLPOOLPRNG", gnu.java.security.jce.prng.WhirlpoolRandomSpi.class.getName());
+ put("SecureRandom.WHIRLPOOLPRNG ImplementedIn", "Software");
+
+ put("Alg.Alias.SecureRandom.SHA-1PRNG", "SHA-160PRNG");
+ put("Alg.Alias.SecureRandom.SHA1PRNG", "SHA-160PRNG");
+ put("Alg.Alias.SecureRandom.SHAPRNG", "SHA-160PRNG");
+ put("Alg.Alias.SecureRandom.SHA-256PRNG", "SHA-256PRNG");
+ put("Alg.Alias.SecureRandom.SHA-2-1PRNG", "SHA-256PRNG");
+ put("Alg.Alias.SecureRandom.SHA-384PRNG", "SHA-384PRNG");
+ put("Alg.Alias.SecureRandom.SHA-2-2PRNG", "SHA-384PRNG");
+ put("Alg.Alias.SecureRandom.SHA-512PRNG", "SHA-512PRNG");
+ put("Alg.Alias.SecureRandom.SHA-2-3PRNG", "SHA-512PRNG");
+
// CertificateFactory
put("CertificateFactory.X509", X509CertificateFactory.class.getName());
@@ -166,14 +259,6 @@ public final class Gnu extends Provider
// CertStore
put("CertStore.Collection", CollectionCertStoreImpl.class.getName());
- // KeyAgreement
- put("KeyAgreement.DiffieHellman", gnu.javax.crypto.DiffieHellmanImpl.class.getName());
- put("Alg.Alias.KeyAgreement.DH", "DiffieHellman");
-
- // Cipher
- put("Cipher.RSAES-PKCS1-v1_5", gnu.javax.crypto.RSACipherImpl.class.getName());
- put("Alg.Alias.Cipher.RSA", "RSAES-PKCS1-v1_5");
-
return null;
}
});
diff --git a/gnu/java/security/sig/BaseSignature.java b/gnu/java/security/sig/BaseSignature.java
new file mode 100644
index 000000000..f82346feb
--- /dev/null
+++ b/gnu/java/security/sig/BaseSignature.java
@@ -0,0 +1,247 @@
+/* BaseSignature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig;
+
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * <p>A base abstract class to facilitate implementations of concrete
+ * Signatures.</p>
+ */
+public abstract class BaseSignature implements ISignature
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name of this signature scheme. */
+ protected String schemeName;
+
+ /** The underlying message digest instance for this signature scheme. */
+ protected IMessageDigest md;
+
+ /** The public key to use when verifying signatures. */
+ protected PublicKey publicKey;
+
+ /** The private key to use when generating signatures (signing). */
+ protected PrivateKey privateKey;
+
+ /** The optional {@link Random} instance to use. */
+ private Random rnd;
+
+ /** The optional {@link IRandom} instance to use. */
+ private IRandom irnd;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor.</p>
+ *
+ * @param schemeName the name of this signature scheme.
+ * @param md the underlying instance of the message digest algorithm.
+ */
+ protected BaseSignature(String schemeName, IMessageDigest md)
+ {
+ super();
+
+ this.schemeName = schemeName;
+ this.md = md;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.sig.ISignature interface implementation ----------------------
+
+ public String name()
+ {
+ return schemeName;
+ }
+
+ public void setupVerify(Map attributes) throws IllegalArgumentException
+ {
+ setup(attributes);
+
+ // do we have a public key?
+ PublicKey key = (PublicKey) attributes.get(VERIFIER_KEY);
+ if (key != null)
+ {
+ setupForVerification(key);
+ }
+ }
+
+ public void setupSign(Map attributes) throws IllegalArgumentException
+ {
+ setup(attributes);
+
+ // do we have a private key?
+ PrivateKey key = (PrivateKey) attributes.get(SIGNER_KEY);
+ if (key != null)
+ {
+ setupForSigning(key);
+ }
+ }
+
+ public void update(byte b)
+ {
+ if (md == null)
+ {
+ throw new IllegalStateException();
+ }
+ md.update(b);
+ }
+
+ public void update(byte[] b, int off, int len)
+ {
+ if (md == null)
+ {
+ throw new IllegalStateException();
+ }
+ md.update(b, off, len);
+ }
+
+ public Object sign()
+ {
+ if (md == null || privateKey == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ return generateSignature();
+ }
+
+ public boolean verify(Object sig)
+ {
+ if (md == null || publicKey == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ return verifySignature(sig);
+ }
+
+ // abstract methods to be implemented by concrete subclasses ---------------
+
+ public abstract Object clone();
+
+ protected abstract void setupForVerification(PublicKey key)
+ throws IllegalArgumentException;
+
+ protected abstract void setupForSigning(PrivateKey key)
+ throws IllegalArgumentException;
+
+ protected abstract Object generateSignature() throws IllegalStateException;
+
+ protected abstract boolean verifySignature(Object signature)
+ throws IllegalStateException;
+
+ // Other instance methods --------------------------------------------------
+
+ /** Initialises the internal fields of this instance. */
+ protected void init()
+ {
+ md.reset();
+ rnd = null;
+ irnd = null;
+ publicKey = null;
+ privateKey = null;
+ }
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ protected void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else if (irnd != null)
+ {
+ try
+ {
+ irnd.nextBytes(buffer, 0, buffer.length);
+ }
+ catch (IllegalStateException x)
+ {
+ throw new RuntimeException("nextRandomBytes(): "
+ + String.valueOf(x));
+ }
+ catch (LimitReachedException x)
+ {
+ throw new RuntimeException("nextRandomBytes(): "
+ + String.valueOf(x));
+ }
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+
+ private void setup(Map attributes)
+ {
+ init();
+
+ // do we have a Random or SecureRandom, or should we use our own?
+ Object obj = attributes.get(SOURCE_OF_RANDOMNESS);
+ if (obj instanceof Random)
+ {
+ rnd = (Random) obj;
+ }
+ else if (obj instanceof IRandom)
+ {
+ irnd = (IRandom) obj;
+ }
+ }
+}
diff --git a/gnu/java/security/sig/ISignature.java b/gnu/java/security/sig/ISignature.java
new file mode 100644
index 000000000..77653ee37
--- /dev/null
+++ b/gnu/java/security/sig/ISignature.java
@@ -0,0 +1,169 @@
+/* ISignature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig;
+
+import java.util.Map;
+
+/**
+ * <p>The visible methods of every signature-with-appendix scheme.</p>
+ *
+ * <p>The Handbook of Applied Cryptography (HAC), by A. Menezes &amp; al. states:
+ * "Digital signature schemes which require the message as input to the
+ * verification algorithm are called <i>digital signature schemes with
+ * appendix</i>. ... They rely on cryptographic hash functions rather than
+ * customised redundancy functions, and are less prone to existential forgery
+ * attacks."</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac/">Handbook of Applied
+ * Cryptography</a>, Alfred J. Menezes, Paul C. van Oorschot and Scott A.
+ * Vanstone. Section 11.2.2 Digital signature schemes with appendix.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface ISignature extends Cloneable
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** Property name of the verifier's public key. */
+ public static final String VERIFIER_KEY = "gnu.crypto.sig.public.key";
+
+ /** Property name of the signer's private key. */
+ public static final String SIGNER_KEY = "gnu.crypto.sig.private.key";
+
+ /**
+ * Property name of an optional {@link java.security.SecureRandom},
+ * {@link java.util.Random}, or {@link gnu.crypto.prng.IRandom} instance to
+ * use. The default is to use a classloader singleton from
+ * {@link gnu.crypto.util.PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.sig.prng";
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of this signature scheme.</p>
+ *
+ * @return the canonical name of this instance.
+ */
+ String name();
+
+ /**
+ * <p>Initialises this instance for signature verification.</p>
+ *
+ * @param attributes the attributes to use for setting up this instance.
+ * @throws IllegalArgumentException if the designated public key is not
+ * appropriate for this signature scheme.
+ * @see #SOURCE_OF_RANDOMNESS
+ * @see #VERIFIER_KEY
+ */
+ void setupVerify(Map attributes) throws IllegalArgumentException;
+
+ /**
+ * <p>Initialises this instance for signature generation.</p>
+ *
+ * @param attributes the attributes to use for setting up this instance.
+ * @throws IllegalArgumentException if the designated private key is not
+ * appropriate for this signature scheme.
+ * @see #SOURCE_OF_RANDOMNESS
+ * @see #SIGNER_KEY
+ */
+ void setupSign(Map attributes) throws IllegalArgumentException;
+
+ /**
+ * <p>Digests one byte of a message for signing or verification purposes.</p>
+ *
+ * @param b the message byte to digest.
+ * @throws IllegalStateException if this instance was not setup for
+ * signature generation/verification.
+ */
+ void update(byte b) throws IllegalStateException;
+
+ /**
+ * <p>Digests a sequence of bytes from a message for signing or verification
+ * purposes.</p>
+ *
+ * @param buffer the byte sequence to consider.
+ * @param offset the byte poisition in <code>buffer</code> of the first byte
+ * to consider.
+ * @param length the number of bytes in <code>buffer</code> starting from the
+ * byte at index <code>offset</code> to digest.
+ * @throws IllegalStateException if this instance was not setup for
+ * signature generation/verification.
+ */
+ void update(byte[] buffer, int offset, int length)
+ throws IllegalStateException;
+
+ /**
+ * <p>Terminates a signature generation phase by digesting and processing the
+ * context of the underlying message digest algorithm instance.</p>
+ *
+ * @return a {@link Object} representing the native output of the signature
+ * scheme implementation.
+ * @throws IllegalStateException if this instance was not setup for
+ * signature generation.
+ */
+ Object sign() throws IllegalStateException;
+
+ /**
+ * <p>Terminates a signature verification phase by digesting and processing
+ * the context of the underlying message digest algorithm instance.</p>
+ *
+ * @param signature a native signature object previously generated by an
+ * invocation of the <code>sign()</code> method.
+ * @return <code>true</code> iff the outpout of the verification phase
+ * confirms that the designated signature object has been generated using the
+ * corresponding public key of the recepient.
+ * @throws IllegalStateException if this instance was not setup for
+ * signature verification.
+ */
+ boolean verify(Object signature) throws IllegalStateException;
+
+ /**
+ * <p>Returns a clone copy of this instance.</p>
+ *
+ * @return a clone copy of this instance.
+ */
+ Object clone();
+}
diff --git a/gnu/java/security/sig/ISignatureCodec.java b/gnu/java/security/sig/ISignatureCodec.java
new file mode 100644
index 000000000..119eca5fd
--- /dev/null
+++ b/gnu/java/security/sig/ISignatureCodec.java
@@ -0,0 +1,68 @@
+/* ISignatureCodec.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The visible methods of an object that knows how to encode and decode
+ * cryptographic signatures. Codecs are useful for (a) externalising signature
+ * output data for storage and on-the-wire transmission, as well as (b) re-
+ * creating their internal Java representation from external sources.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface ISignatureCodec
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** Constant identifying the <i>Raw</i> encoding format. */
+ int RAW_FORMAT = Registry.RAW_ENCODING_ID;
+
+ // Method(s)
+ // -------------------------------------------------------------------------
+
+ int getFormatID();
+
+ byte[] encodeSignature(Object signature);
+
+ Object decodeSignature(byte[] input);
+}
diff --git a/gnu/java/security/sig/SignatureFactory.java b/gnu/java/security/sig/SignatureFactory.java
new file mode 100644
index 000000000..9bac354d7
--- /dev/null
+++ b/gnu/java/security/sig/SignatureFactory.java
@@ -0,0 +1,122 @@
+/* SignatureFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.dss.DSSSignature;
+import gnu.java.security.sig.rsa.RSAPSSSignature;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5Signature;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>A Factory to instantiate signature-with-appendix handlers.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class SignatureFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private SignatureFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a signature-with-appendix scheme given its name.</p>
+ *
+ * @param ssa the case-insensitive signature-with-appendix scheme name.
+ * @return an instance of the scheme, or <code>null</code> if none found.
+ */
+ public static final ISignature getInstance(String ssa)
+ {
+ if (ssa == null)
+ {
+ return null;
+ }
+
+ ssa = ssa.trim();
+ ISignature result = null;
+ if (ssa.equalsIgnoreCase(Registry.DSA_SIG) || ssa.equals(Registry.DSS_SIG))
+ {
+ result = new DSSSignature();
+ }
+ else if (ssa.equalsIgnoreCase(Registry.RSA_PSS_SIG))
+ {
+ result = new RSAPSSSignature();
+ }
+ else if (ssa.equalsIgnoreCase(Registry.RSA_PKCS1_V1_5_SIG))
+ {
+ result = new RSAPKCS1V1_5Signature();
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of signature-with-appendix scheme names supported
+ * by this <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of signature-with-appendix scheme names (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.DSS_SIG);
+ hs.add(Registry.RSA_PSS_SIG);
+ hs.add(Registry.RSA_PKCS1_V1_5_SIG);
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/java/security/sig/dss/DSSSignature.java b/gnu/java/security/sig/dss/DSSSignature.java
new file mode 100644
index 000000000..6bedfaefa
--- /dev/null
+++ b/gnu/java/security/sig/dss/DSSSignature.java
@@ -0,0 +1,347 @@
+/* DSSSignature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.sig.BaseSignature;
+import gnu.java.security.sig.ISignature;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * <p>The DSS (Digital Signature Standard) algorithm makes use of the following
+ * parameters:</p>
+ *
+ * <ol>
+ * <li>p: A prime modulus, where <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup>
+ * </code> for <code>512 &lt;= L &lt;= 1024</code> and <code>L</code> a
+ * multiple of <code>64</code>.</li>
+ * <li>q: A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup>
+ * &lt; q &lt; 2<sup>160</sup></code>.</li>
+ * <li>g: Where <code>g = h<sup>(p-1)</sup>/q mod p</code>, where
+ * <code>h</code> is any integer with <code>1 &lt; h &lt; p - 1</code> such
+ * that <code>h<sup> (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order
+ * <code>q mod p</code>).</li>
+ * <li>x: A randomly or pseudorandomly generated integer with <code>0 &lt; x
+ * &lt; q</code>.</li>
+ * <li>y: <code>y = g<sup>x</sup> mod p</code>.</li>
+ * <li>k: A randomly or pseudorandomly generated integer with <code>0 &lt; k
+ * &lt; q</code>.</li>
+ * </ol>
+ *
+ * <p>The integers <code>p</code>, <code>q</code>, and <code>g</code> can be
+ * public and can be common to a group of users. A user's private and public
+ * keys are <code>x</code> and <code>y</code>, respectively. They are normally
+ * fixed for a period of time. Parameters <code>x</code> and <code>k</code> are
+ * used for signature generation only, and must be kept secret. Parameter
+ * <code>k</code> must be regenerated for each signature.</p>
+ *
+ * <p>The signature of a message <code>M</code> is the pair of numbers <code>r</code>
+ * and <code>s</code> computed according to the equations below:</p>
+ *
+ * <ul>
+ * <li><code>r = (g<sup>k</sup> mod p) mod q</code> and</li>
+ * <li><code>s = (k<sup>-1</sup>(SHA(M) + xr)) mod q</code>.</li>
+ * </ul>
+ *
+ * <p>In the above, <code>k<sup>-1</sup></code> is the multiplicative inverse of
+ * <code>k</code>, <code>mod q</code>; i.e., <code>(k<sup>-1</sup> k) mod q = 1
+ * </code> and <code>0 &lt; k-1 &lt; q</code>. The value of <code>SHA(M)</code>
+ * is a 160-bit string output by the Secure Hash Algorithm specified in FIPS 180.
+ * For use in computing <code>s</code>, this string must be converted to an
+ * integer.</p>
+ *
+ * <p>As an option, one may wish to check if <code>r == 0</code> or <code>s == 0
+ * </code>. If either <code>r == 0</code> or <code>s == 0</code>, a new value
+ * of <code>k</code> should be generated and the signature should be
+ * recalculated (it is extremely unlikely that <code>r == 0</code> or <code>s ==
+ * 0</code> if signatures are generated properly).</p>
+ *
+ * <p>The signature is transmitted along with the message to the verifier.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital
+ * Signature Standard (DSS)</a>, Federal Information Processing Standards
+ * Publication 186. National Institute of Standards and Technology.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSSignature extends BaseSignature
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public DSSSignature()
+ {
+ super(Registry.DSS_SIG, new Sha160());
+ }
+
+ /** Private constructor for cloning purposes. */
+ private DSSSignature(DSSSignature that)
+ {
+ this();
+
+ this.publicKey = that.publicKey;
+ this.privateKey = that.privateKey;
+ this.md = (IMessageDigest) that.md.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h)
+ {
+ final DSSSignature sig = new DSSSignature();
+ final Map attributes = new HashMap();
+ attributes.put(ISignature.SIGNER_KEY, k);
+ sig.setupSign(attributes);
+
+ return sig.computeRS(h);
+ }
+
+ public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h,
+ Random rnd)
+ {
+ final DSSSignature sig = new DSSSignature();
+ final Map attributes = new HashMap();
+ attributes.put(ISignature.SIGNER_KEY, k);
+ if (rnd != null)
+ {
+ attributes.put(ISignature.SOURCE_OF_RANDOMNESS, rnd);
+ }
+ sig.setupSign(attributes);
+
+ return sig.computeRS(h);
+ }
+
+ public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h,
+ IRandom irnd)
+ {
+ final DSSSignature sig = new DSSSignature();
+ final Map attributes = new HashMap();
+ attributes.put(ISignature.SIGNER_KEY, k);
+ if (irnd != null)
+ {
+ attributes.put(ISignature.SOURCE_OF_RANDOMNESS, irnd);
+ }
+ sig.setupSign(attributes);
+
+ return sig.computeRS(h);
+ }
+
+ public static final boolean verify(final DSAPublicKey k, final byte[] h,
+ final BigInteger[] rs)
+ {
+ final DSSSignature sig = new DSSSignature();
+ final Map attributes = new HashMap();
+ attributes.put(ISignature.VERIFIER_KEY, k);
+ sig.setupVerify(attributes);
+
+ return sig.checkRS(rs, h);
+ }
+
+ // Implementation of abstract methods in superclass
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new DSSSignature(this);
+ }
+
+ protected void setupForVerification(PublicKey k)
+ throws IllegalArgumentException
+ {
+ if (!(k instanceof DSAPublicKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ this.publicKey = k;
+ }
+
+ protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
+ {
+ if (!(k instanceof DSAPrivateKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ this.privateKey = k;
+ }
+
+ protected Object generateSignature() throws IllegalStateException
+ {
+ // BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP();
+ // BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ();
+ // BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG();
+ // BigInteger x = ((DSAPrivateKey) privateKey).getX();
+ // BigInteger m = new BigInteger(1, md.digest());
+ // BigInteger k, r, s;
+ //
+ // byte[] kb = new byte[20]; // we'll use 159 bits only
+ // while (true) {
+ // this.nextRandomBytes(kb);
+ // k = new BigInteger(1, kb);
+ // k.clearBit(159);
+ // r = g.modPow(k, p).mod(q);
+ // if (r.equals(BigInteger.ZERO)) {
+ // continue;
+ // }
+ // s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
+ // if (s.equals(BigInteger.ZERO)) {
+ // continue;
+ // }
+ // break;
+ // }
+ final BigInteger[] rs = computeRS(md.digest());
+
+ // return encodeSignature(r, s);
+ return encodeSignature(rs[0], rs[1]);
+ }
+
+ protected boolean verifySignature(Object sig) throws IllegalStateException
+ {
+ final BigInteger[] rs = decodeSignature(sig);
+ // BigInteger r = rs[0];
+ // BigInteger s = rs[1];
+ //
+ // BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
+ // BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
+ // BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
+ // BigInteger y = ((DSAPublicKey) publicKey).getY();
+ // BigInteger w = s.modInverse(q);
+ //
+ // byte bytes[] = md.digest();
+ // BigInteger u1 = w.multiply(new BigInteger(1, bytes)).mod(q);
+ // BigInteger u2 = r.multiply(w).mod(q);
+ //
+ // BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
+ // return v.equals(r);
+ return checkRS(rs, md.digest());
+ }
+
+ // Other instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns the output of a signature generation phase.<p>
+ *
+ * @return an object encapsulating the DSS signature pair <code>r</code> and
+ * <code>s</code>.
+ */
+ private Object encodeSignature(BigInteger r, BigInteger s)
+ {
+ return new BigInteger[] { r, s };
+ }
+
+ /**
+ * Returns the output of a previously generated signature object as a pair
+ * of {@link java.math.BigInteger}.<p>
+ *
+ * @return the DSS signature pair <code>r</code> and <code>s</code>.
+ */
+ private BigInteger[] decodeSignature(Object signature)
+ {
+ return (BigInteger[]) signature;
+ }
+
+ private BigInteger[] computeRS(final byte[] digestBytes)
+ {
+ final BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP();
+ final BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ();
+ final BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG();
+ final BigInteger x = ((DSAPrivateKey) privateKey).getX();
+ final BigInteger m = new BigInteger(1, digestBytes);
+ BigInteger k, r, s;
+
+ final byte[] kb = new byte[20]; // we'll use 159 bits only
+ while (true)
+ {
+ this.nextRandomBytes(kb);
+ k = new BigInteger(1, kb);
+ k.clearBit(159);
+ r = g.modPow(k, p).mod(q);
+ if (r.equals(BigInteger.ZERO))
+ {
+ continue;
+ }
+ s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
+ if (s.equals(BigInteger.ZERO))
+ {
+ continue;
+ }
+ break;
+ }
+
+ return new BigInteger[] { r, s };
+ }
+
+ private boolean checkRS(final BigInteger[] rs, final byte[] digestBytes)
+ {
+ final BigInteger r = rs[0];
+ final BigInteger s = rs[1];
+
+ final BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
+ final BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
+ final BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
+ final BigInteger y = ((DSAPublicKey) publicKey).getY();
+ final BigInteger w = s.modInverse(q);
+
+ final BigInteger u1 = w.multiply(new BigInteger(1, digestBytes)).mod(q);
+ final BigInteger u2 = r.multiply(w).mod(q);
+
+ final BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
+ return v.equals(r);
+ }
+}
diff --git a/gnu/java/security/sig/dss/DSSSignatureRawCodec.java b/gnu/java/security/sig/dss/DSSSignatureRawCodec.java
new file mode 100644
index 000000000..02f6b1ddc
--- /dev/null
+++ b/gnu/java/security/sig/dss/DSSSignatureRawCodec.java
@@ -0,0 +1,191 @@
+/* DSSSignatureRawCodec.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.ISignatureCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+
+/**
+ * <p>An object that implements the {@link ISignatureCodec} operations for the
+ * <i>Raw</i> format to use with DSS signatures.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSSignatureRawCodec implements ISignatureCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.sig.ISignatureCodec interface implementation -----------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated DSS (Digital Signature
+ * Standard) signature object according to the <i>Raw</i> format supported by
+ * this library.</p>
+ *
+ * <p>The <i>Raw</i> format for a DSA signature, in this implementation, is a
+ * byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_DSS_SIGNATURE},</li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the DSS parameter
+ * <code>r</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSS parameter <code>r</code>,</li>
+ * <li>4-byte count of following bytes representing the DSS parameter
+ * <code>s</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSS parameter <code>s</code>.</li>
+ * </ol>
+ *
+ * @param signature the signature to encode, consisting of the two DSS
+ * parameters <code>r</code> and <code>s</code> as a {@link java.math.BigInteger}
+ * array.
+ * @return the <i>Raw</i> format encoding of the designated signature.
+ * @exception IllegalArgumentException if the designated signature is not a
+ * DSS (Digital Signature Standard) one.
+ */
+ public byte[] encodeSignature(Object signature)
+ {
+ BigInteger r, s;
+ try
+ {
+ BigInteger[] sig = (BigInteger[]) signature;
+ r = sig[0];
+ s = sig[1];
+ }
+ catch (Exception x)
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[0]);
+ baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[1]);
+ baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[2]);
+ baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[3]);
+
+ // version
+ baos.write(0x01);
+
+ // r
+ byte[] buffer = r.toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // s
+ buffer = s.toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public Object decodeSignature(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_DSS_SIGNATURE[0]
+ || k[1] != Registry.MAGIC_RAW_DSS_SIGNATURE[1]
+ || k[2] != Registry.MAGIC_RAW_DSS_SIGNATURE[2]
+ || k[3] != Registry.MAGIC_RAW_DSS_SIGNATURE[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+
+ int i = 5;
+ int l;
+ byte[] buffer;
+
+ // r
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger r = new BigInteger(1, buffer);
+
+ // s
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger s = new BigInteger(1, buffer);
+
+ return new BigInteger[] { r, s };
+ }
+}
diff --git a/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java b/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java
new file mode 100644
index 000000000..d6bbfe56b
--- /dev/null
+++ b/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java
@@ -0,0 +1,305 @@
+/* EME_PKCS1_V1_5.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+import java.io.ByteArrayOutputStream;
+import java.security.SecureRandom;
+import java.security.interfaces.RSAKey;
+import java.util.Random;
+
+/**
+ * <p>An implementation of the EME-PKCS1-V1.5 encoding and decoding methods.</p>
+ *
+ * <p>EME-PKCS1-V1.5 is parameterised by the entity <code>k</code> which is the
+ * byte count of an RSA public shared modulus.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ */
+public class EME_PKCS1_V1_5
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private int k;
+
+ private ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ private EME_PKCS1_V1_5(final int k)
+ {
+ super();
+
+ this.k = k;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final EME_PKCS1_V1_5 getInstance(final int k)
+ {
+ if (k < 0)
+ {
+ throw new IllegalArgumentException("k must be a positive integer");
+ }
+ return new EME_PKCS1_V1_5(k);
+ }
+
+ public static final EME_PKCS1_V1_5 getInstance(final RSAKey key)
+ {
+ final int modBits = key.getModulus().bitLength();
+ final int k = (modBits + 7) / 8;
+ return EME_PKCS1_V1_5.getInstance(k);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Generates an octet string <code>PS</code> of length <code>k - mLen -
+ * 3</code> consisting of pseudo-randomly generated nonzero octets. The
+ * length of <code>PS</code> will be at least eight octets.</p>
+ *
+ * <p>The method then concatenates <code>PS</code>, the message <code>M</code>,
+ * and other padding to form an encoded message <code>EM</code> of length
+ * <code>k</code> octets as:</p>
+ *
+ * <pre>
+ * EM = 0x00 || 0x02 || PS || 0x00 || M.
+ * </pre>
+ *
+ * <p>This method uses a default PRNG to obtain the padding bytes.</p>
+ *
+ * @param M the message to encode.
+ * @return the encoded message <code>EM</code>.
+ */
+ public byte[] encode(final byte[] M)
+ {
+ // a. Generate an octet string PS of length k - mLen - 3 consisting
+ // of pseudo-randomly generated nonzero octets. The length of PS
+ // will be at least eight octets.
+ final byte[] PS = new byte[k - M.length - 3];
+
+ // FIXME. This should be configurable, somehow.
+ SecureRandom rnd = new SecureRandom ();
+ rnd.nextBytes(PS);
+ int i = 0;
+ for (; i < PS.length; i++)
+ {
+ if (PS[i] == 0)
+ PS[i] = 1;
+ }
+ // b. Concatenate PS, the message M, and other padding to form an
+ // encoded message EM of length k octets as
+ //
+ // EM = 0x00 || 0x02 || PS || 0x00 || M.
+ return assembleEM(PS, M);
+ }
+
+ /**
+ * <p>Similar to {@link #encode(byte[])} method, except that the source of
+ * randomness to use for obtaining the padding bytes (an instance of
+ * {@link IRandom}) is given as a parameter.</p>
+ *
+ * @param M the message to encode.
+ * @param irnd the {@link IRandom} instance to use as a source of randomness.
+ * @return the encoded message <code>EM</code>.
+ */
+ public byte[] encode(final byte[] M, final IRandom irnd)
+ {
+ final byte[] PS = new byte[k - M.length - 3];
+ try
+ {
+ irnd.nextBytes(PS, 0, PS.length);
+ int i = 0;
+ outer: while (true)
+ {
+ for (; i < PS.length; i++)
+ {
+ if (PS[i] == 0x00)
+ {
+ System.arraycopy(PS, i + 1, PS, i, PS.length - i - 1);
+ irnd.nextBytes(PS, PS.length - 1, 1);
+ continue outer;
+ }
+ }
+ break;
+ }
+ }
+ catch (IllegalStateException x)
+ {
+ throw new RuntimeException("encode(): " + String.valueOf(x));
+ }
+ catch (LimitReachedException x)
+ {
+ throw new RuntimeException("encode(): " + String.valueOf(x));
+ }
+
+ return assembleEM(PS, M);
+ }
+
+ /**
+ * <p>Similar to the {@link #encode(byte[], IRandom)} method, except that
+ * the source of randmoness is an instance of {@link Random}.
+ *
+ * @param M the message to encode.
+ * @param rnd the {@link Random} instance to use as a source of randomness.
+ * @return the encoded message <code>EM</code>.
+ */
+ public byte[] encode(final byte[] M, final Random rnd)
+ {
+ final byte[] PS = new byte[k - M.length - 3];
+ rnd.nextBytes(PS);
+ int i = 0;
+ outer: while (true)
+ {
+ for (; i < PS.length; i++)
+ {
+ if (PS[i] == 0x00)
+ {
+ System.arraycopy(PS, i + 1, PS, i, PS.length - i - 1);
+ PS[PS.length - 1] = (byte) rnd.nextInt();
+ continue outer;
+ }
+ }
+ break;
+ }
+
+ return assembleEM(PS, M);
+ }
+
+ /**
+ * <p>Separate the encoded message <code>EM</code> into an octet string
+ * <code>PS</code> consisting of nonzero octets and a message <code>M</code>
+ * as:</p>
+ *
+ * <pre>
+ * EM = 0x00 || 0x02 || PS || 0x00 || M.
+ * </pre>
+ *
+ * <p>If the first octet of <code>EM</code> does not have hexadecimal value
+ * <code>0x00</code>, if the second octet of <code>EM</code> does not have
+ * hexadecimal value <code>0x02</code>, if there is no octet with hexadecimal
+ * value <code>0x00</code> to separate <code>PS</code> from <code>M</code>,
+ * or if the length of <code>PS</code> is less than <code>8</code> octets,
+ * output "decryption error" and stop.</p>
+
+ * @param EM the designated encoded message.
+ * @return the decoded message <code>M</code> framed in the designated
+ * <code>EM</code> value.
+ * @throws IllegalArgumentException if the length of the designated entity
+ * <code>EM</code> is different than <code>k</code> (the length in bytes of
+ * the public shared modulus), or if any of the conditions described above
+ * is detected.
+ */
+ public byte[] decode(final byte[] EM)
+ {
+ // Separate the encoded message EM into an
+ // octet string PS consisting of nonzero octets and a message M as
+ //
+ // EM = 0x00 || 0x02 || PS || 0x00 || M.
+ //
+ // If the first octet of EM does not have hexadecimal value 0x00, if
+ // the second octet of EM does not have hexadecimal value 0x02, if
+ // there is no octet with hexadecimal value 0x00 to separate PS from
+ // M, or if the length of PS is less than 8 octets, output
+ // "decryption error" and stop. (See the note below.)
+ final int emLen = EM.length;
+ if (emLen != k)
+ {
+ throw new IllegalArgumentException("decryption error");
+ }
+ if (EM[0] != 0x00)
+ {
+ throw new IllegalArgumentException("decryption error");
+ }
+ if (EM[1] != 0x02)
+ {
+ throw new IllegalArgumentException("decryption error");
+ }
+ int i = 2;
+ for (; i < emLen; i++)
+ {
+ if (EM[i] == 0x00)
+ {
+ break;
+ }
+ }
+ if (i >= emLen || i < 11)
+ {
+ throw new IllegalArgumentException("decryption error");
+ }
+ i++;
+ final byte[] result = new byte[emLen - i];
+ System.arraycopy(EM, i, result, 0, result.length);
+ return result;
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ private byte[] assembleEM(final byte[] PS, final byte[] M)
+ {
+ // b. Concatenate PS, the message M, and other padding to form an
+ // encoded message EM of length k octets as
+ //
+ // EM = 0x00 || 0x02 || PS || 0x00 || M.
+ baos.reset();
+ baos.write(0x00);
+ baos.write(0x02);
+ baos.write(PS, 0, PS.length);
+ baos.write(0x00);
+ baos.write(M, 0, M.length);
+ final byte[] result = baos.toByteArray();
+ baos.reset();
+
+ return result;
+
+ }
+}
diff --git a/gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java b/gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java
new file mode 100644
index 000000000..d8e7f2a48
--- /dev/null
+++ b/gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java
@@ -0,0 +1,299 @@
+/* EMSA_PKCS1_V1_5.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * <p>An implementation of the EMSA-PKCS1-V1.5 encoding scheme.</p>
+ *
+ * <p>EMSA-PKCS1-V1.5 is parameterised by the choice of hash function Hash and
+ * hLen which denotes the length in octets of the hash function output.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class EMSA_PKCS1_V1_5 implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /* Notes.
+ 1. For the six hash functions mentioned in Appendix B.1, the DER encoding
+ T of the DigestInfo value is equal to the following:
+
+ MD2: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10 || H
+ MD5: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H
+ SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H
+ SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H
+ SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H
+ SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H
+ */
+ private static final byte[] MD2_PREFIX = { (byte) 0x30, (byte) 0x20,
+ (byte) 0x30, (byte) 0x0c,
+ (byte) 0x06, (byte) 0x08,
+ (byte) 0x2a, (byte) 0x86,
+ (byte) 0x48, (byte) 0x86,
+ (byte) 0xf7, (byte) 0x0d,
+ (byte) 0x02, (byte) 0x02,
+ (byte) 0x05, (byte) 0x00,
+ (byte) 0x04, (byte) 0x10 };
+
+ private static final byte[] MD5_PREFIX = { (byte) 0x30, (byte) 0x20,
+ (byte) 0x30, (byte) 0x0c,
+ (byte) 0x06, (byte) 0x08,
+ (byte) 0x2a, (byte) 0x86,
+ (byte) 0x48, (byte) 0x86,
+ (byte) 0xf7, (byte) 0x0d,
+ (byte) 0x02, (byte) 0x05,
+ (byte) 0x05, (byte) 0x00,
+ (byte) 0x04, (byte) 0x10 };
+
+ private static final byte[] SHA160_PREFIX = { (byte) 0x30, (byte) 0x21,
+ (byte) 0x30, (byte) 0x09,
+ (byte) 0x06, (byte) 0x05,
+ (byte) 0x2b, (byte) 0x0e,
+ (byte) 0x03, (byte) 0x02,
+ (byte) 0x1a, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04,
+ (byte) 0x14 };
+
+ private static final byte[] SHA256_PREFIX = { (byte) 0x30, (byte) 0x31,
+ (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09,
+ (byte) 0x60, (byte) 0x86,
+ (byte) 0x48, (byte) 0x01,
+ (byte) 0x65, (byte) 0x03,
+ (byte) 0x04, (byte) 0x02,
+ (byte) 0x01, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04,
+ (byte) 0x20 };
+
+ private static final byte[] SHA384_PREFIX = { (byte) 0x30, (byte) 0x41,
+ (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09,
+ (byte) 0x60, (byte) 0x86,
+ (byte) 0x48, (byte) 0x01,
+ (byte) 0x65, (byte) 0x03,
+ (byte) 0x04, (byte) 0x02,
+ (byte) 0x02, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04,
+ (byte) 0x30 };
+
+ private static final byte[] SHA512_PREFIX = { (byte) 0x30, (byte) 0x51,
+ (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09,
+ (byte) 0x60, (byte) 0x86,
+ (byte) 0x48, (byte) 0x01,
+ (byte) 0x65, (byte) 0x03,
+ (byte) 0x04, (byte) 0x02,
+ (byte) 0x03, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04,
+ (byte) 0x40 };
+
+ /** The underlying hash function to use with this instance. */
+ private IMessageDigest hash;
+
+ /** The output size of the hash function in octets. */
+ private int hLen; // TODO: field not used!!! investigate
+
+ /** The DER part of DigestInfo not containing the hash value itself. */
+ private byte[] prefix;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial private constructor to enforce use through Factory method.</p>
+ *
+ * @param hash the message digest instance to use with this scheme instance.
+ */
+ private EMSA_PKCS1_V1_5(final IMessageDigest hash)
+ {
+ super();
+
+ this.hash = hash;
+ hLen = hash.hashSize();
+ final String name = hash.name();
+ if (name.equals(Registry.MD2_HASH))
+ {
+ prefix = MD2_PREFIX;
+ }
+ else if (name.equals(Registry.MD5_HASH))
+ {
+ prefix = MD5_PREFIX;
+ }
+ else if (name.equals(Registry.SHA160_HASH))
+ {
+ prefix = SHA160_PREFIX;
+ }
+ else if (name.equals(Registry.SHA256_HASH))
+ {
+ prefix = SHA256_PREFIX;
+ }
+ else if (name.equals(Registry.SHA384_HASH))
+ {
+ prefix = SHA384_PREFIX;
+ }
+ else if (name.equals(Registry.SHA512_HASH))
+ {
+ prefix = SHA512_PREFIX;
+ }
+ else
+ {
+ throw new UnsupportedOperationException(); // should not happen
+ }
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of this object given a designated name of a hash
+ * function.</p>
+ *
+ * @param mdName the canonical name of a hash function.
+ * @return an instance of this object configured for use with the designated
+ * options.
+ * @throws UnsupportedOperationException if the hash function is not
+ * implemented or does not have an ID listed in RFC-3447.
+ */
+ public static final EMSA_PKCS1_V1_5 getInstance(final String mdName)
+ {
+ final IMessageDigest hash = HashFactory.getInstance(mdName);
+ final String name = hash.name();
+ if (!(name.equals(Registry.MD2_HASH) || name.equals(Registry.MD5_HASH)
+ || name.equals(Registry.SHA160_HASH)
+ || name.equals(Registry.SHA256_HASH)
+ || name.equals(Registry.SHA384_HASH) || name.equals(Registry.SHA512_HASH)))
+ {
+ throw new UnsupportedOperationException("hash with no ID");
+ }
+ return new EMSA_PKCS1_V1_5(hash);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Cloneable interface implementation --------------------------------------
+
+ public Object clone()
+ {
+ return getInstance(hash.name());
+ }
+
+ // own methods -------------------------------------------------------------
+
+ /**
+ * <p>Frames the hash of a message, along with an ID of the hash function in
+ * a DER sequence according to the specifications of EMSA-PKCS1-V1.5 as
+ * described in RFC-3447 (see class documentation).</p>
+ *
+ * @param mHash the byte sequence resulting from applying the message digest
+ * algorithm Hash to the message <i>M</i>.
+ * @param emLen intended length in octets of the encoded message, at least
+ * <code>tLen + 11</code>, where <code>tLen</code> is the octet length of the
+ * DER encoding <code>T</code> of a certain value computed during the
+ * encoding operation.
+ * @return encoded message, an octet string of length <code>emLen</code>.
+ * @throws IllegalArgumentException if the message is too long, or if the
+ * intended encoded message length is too short.
+ */
+ public byte[] encode(final byte[] mHash, final int emLen)
+ {
+ // 1. Apply the hash function to the message M to produce a hash value
+ // H: H = Hash(M).
+ // If the hash function outputs "message too long," output "message
+ // too long" and stop.
+ // 2. Encode the algorithm ID for the hash function and the hash value
+ // into an ASN.1 value of type DigestInfo (see Appendix A.2.4) with
+ // the Distinguished Encoding Rules (DER), where the type DigestInfo
+ // has the syntax
+ // DigestInfo ::= SEQUENCE {
+ // digestAlgorithm AlgorithmIdentifier,
+ // digest OCTET STRING
+ // }
+ // The first field identifies the hash function and the second contains
+ // the hash value. Let T be the DER encoding of the DigestInfo value
+ // (see the notes below) and let tLen be the length in octets of T.
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ baos.write(prefix, 0, prefix.length);
+ baos.write(mHash, 0, mHash.length);
+ final byte[] T = baos.toByteArray();
+ final int tLen = T.length;
+ // 3. If emLen < tLen + 11, output "intended encoded message length too
+ // short" and stop.
+ if (emLen < tLen + 11)
+ {
+ throw new IllegalArgumentException("emLen too short");
+ }
+ // 4. Generate an octet string PS consisting of emLen - tLen - 3 octets
+ // with hexadecimal value 0xff. The length of PS will be at least 8
+ // octets.
+ final byte[] PS = new byte[emLen - tLen - 3];
+ for (int i = 0; i < PS.length; i++)
+ {
+ PS[i] = (byte) 0xFF;
+ }
+ // 5. Concatenate PS, the DER encoding T, and other padding to form the
+ // encoded message EM as: EM = 0x00 || 0x01 || PS || 0x00 || T.
+ baos.reset();
+ baos.write(0x00);
+ baos.write(0x01);
+ baos.write(PS, 0, PS.length);
+ baos.write(0x00);
+ baos.write(T, 0, tLen);
+ final byte[] result = baos.toByteArray();
+ baos.reset();
+ // 6. Output EM.
+ return result;
+ }
+}
diff --git a/gnu/java/security/sig/rsa/EMSA_PSS.java b/gnu/java/security/sig/rsa/EMSA_PSS.java
new file mode 100644
index 000000000..d11a861b5
--- /dev/null
+++ b/gnu/java/security/sig/rsa/EMSA_PSS.java
@@ -0,0 +1,432 @@
+/* EMSA_PSS.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * <p>An implementation of the EMSA-PSS encoding/decoding scheme.</p>
+ *
+ * <p>EMSA-PSS coincides with EMSA4 in IEEE P1363a D5 except that EMSA-PSS acts
+ * on octet strings and not on bit strings. In particular, the bit lengths of
+ * the hash and the salt must be multiples of 8 in EMSA-PSS. Moreover, EMSA4
+ * outputs an integer of a desired bit length rather than an octet string.</p>
+ *
+ * <p>EMSA-PSS is parameterized by the choice of hash function Hash and mask
+ * generation function MGF. In this submission, MGF is based on a Hash
+ * definition that coincides with the corresponding definitions in IEEE Std
+ * 1363-2000, PKCS #1 v2.0, and the draft ANSI X9.44. In PKCS #1 v2.0 and the
+ * draft ANSI X9.44, the recommended hash function is SHA-1, while IEEE Std
+ * 1363-2000 recommends SHA-1 and RIPEMD-160.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class EMSA_PSS implements Cloneable
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "emsa-pss";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The underlying hash function to use with this instance. */
+ private IMessageDigest hash;
+
+ /** The output size of the hash function in octets. */
+ private int hLen;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial private constructor to enforce use through Factory method.</p>
+ *
+ * @param hash the message digest instance to use with this scheme instance.
+ */
+ private EMSA_PSS(IMessageDigest hash)
+ {
+ super();
+
+ this.hash = hash;
+ hLen = hash.hashSize();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of this object given a designated name of a hash
+ * function.</p>
+ *
+ * @param mdName the canonical name of a hash function.
+ * @return an instance of this object configured for use with the designated
+ * options.
+ */
+ public static EMSA_PSS getInstance(String mdName)
+ {
+ IMessageDigest hash = HashFactory.getInstance(mdName);
+ return new EMSA_PSS(hash);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Cloneable interface implementation --------------------------------------
+
+ public Object clone()
+ {
+ return getInstance(hash.name());
+ }
+
+ // own methods -------------------------------------------------------------
+
+ /**
+ * <p>The encoding operation EMSA-PSS-Encode computes the hash of a message
+ * <code>M</code> using a hash function and maps the result to an encoded
+ * message <code>EM</code> of a specified length using a mask generation
+ * function.</p>
+ *
+ * @param mHash the byte sequence resulting from applying the message digest
+ * algorithm Hash to the message <i>M</i>.
+ * @param emBits the maximal bit length of the integer OS2IP(EM), at least
+ * <code>8.hLen + 8.sLen + 9</code>.
+ * @param salt the salt to use when encoding the output.
+ * @return the encoded message <code>EM</code>, an octet string of length
+ * <code>emLen = CEILING(emBits / 8)</code>.
+ * @exception IllegalArgumentException if an exception occurs.
+ *
+ */
+ public byte[] encode(byte[] mHash, int emBits, byte[] salt)
+ {
+ int sLen = salt.length;
+
+ // 1. If the length of M is greater than the input limitation for the hash
+ // function (2**61 - 1 octets for SHA-1) then output "message too long"
+ // and stop.
+ // 2. Let mHash = Hash(M), an octet string of length hLen.
+ if (hLen != mHash.length)
+ {
+ throw new IllegalArgumentException("wrong hash");
+ }
+ // 3. If emBits < 8.hLen + 8.sLen + 9, output 'encoding error' and stop.
+ if (emBits < (8 * hLen + 8 * sLen + 9))
+ {
+ throw new IllegalArgumentException("encoding error");
+ }
+ int emLen = (emBits + 7) / 8;
+ // 4. Generate a random octet string salt of length sLen; if sLen = 0,
+ // then salt is the empty string.
+ // ...passed as argument to accomodate JCE
+ // 5. Let M0 = 00 00 00 00 00 00 00 00 || mHash || salt;
+ // M0 is an octet string of length 8 + hLen + sLen with eight initial zero
+ // octets.
+ // 6. Let H = Hash(M0), an octet string of length hLen.
+ byte[] H;
+ int i;
+ synchronized (hash)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ hash.update((byte) 0x00);
+ }
+ hash.update(mHash, 0, hLen);
+ hash.update(salt, 0, sLen);
+ H = hash.digest();
+ }
+ // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2
+ // zero octets. The length of PS may be 0.
+ // 8. Let DB = PS || 01 || salt.
+ byte[] DB = new byte[emLen - sLen - hLen - 2 + 1 + sLen];
+ DB[emLen - sLen - hLen - 2] = 0x01;
+ System.arraycopy(salt, 0, DB, emLen - sLen - hLen - 1, sLen);
+ // 9. Let dbMask = MGF(H, emLen - hLen - 1).
+ byte[] dbMask = MGF(H, emLen - hLen - 1);
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("dbMask (encode): " + Util.toString(dbMask));
+ debug("DB (encode): " + Util.toString(DB));
+ }
+ // 10. Let maskedDB = DB XOR dbMask.
+ for (i = 0; i < DB.length; i++)
+ {
+ DB[i] = (byte) (DB[i] ^ dbMask[i]);
+ }
+ // 11. Set the leftmost 8emLen - emBits bits of the leftmost octet in
+ // maskedDB to zero.
+ DB[0] &= (0xFF >>> (8 * emLen - emBits));
+ // 12. Let EM = maskedDB || H || bc, where bc is the single octet with
+ // hexadecimal value 0xBC.
+ byte[] result = new byte[emLen];
+ System.arraycopy(DB, 0, result, 0, emLen - hLen - 1);
+ System.arraycopy(H, 0, result, emLen - hLen - 1, hLen);
+ result[emLen - 1] = (byte) 0xBC;
+ // 13. Output EM.
+ return result;
+ }
+
+ /**
+ * <p>The decoding operation EMSA-PSS-Decode recovers the message hash from
+ * an encoded message <code>EM</code> and compares it to the hash of
+ * <code>M</code>.</p>
+ *
+ * @param mHash the byte sequence resulting from applying the message digest
+ * algorithm Hash to the message <i>M</i>.
+ * @param EM the <i>encoded message</i>, an octet string of length
+ * <code>emLen = CEILING(emBits/8).
+ * @param emBits the maximal bit length of the integer OS2IP(EM), at least
+ * <code>8.hLen + 8.sLen + 9</code>.
+ * @param sLen the length, in octets, of the expected salt.
+ * @return <code>true</code> if the result of the verification was
+ * <i>consistent</i> with the expected reseult; and <code>false</code> if the
+ * result was <i>inconsistent</i>.
+ * @exception IllegalArgumentException if an exception occurs.
+ */
+ public boolean decode(byte[] mHash, byte[] EM, int emBits, int sLen)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("mHash: " + Util.toString(mHash));
+ debug("EM: " + Util.toString(EM));
+ debug("emBits: " + String.valueOf(emBits));
+ debug("sLen: " + String.valueOf(sLen));
+ }
+ if (sLen < 0)
+ {
+ throw new IllegalArgumentException("sLen");
+ }
+
+ // 1. If the length of M is greater than the input limitation for the hash
+ // function (2**61 ? 1 octets for SHA-1) then output 'inconsistent' and
+ // stop.
+ // 2. Let mHash = Hash(M), an octet string of length hLen.
+ if (hLen != mHash.length)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("hLen != mHash.length; hLen: " + String.valueOf(hLen));
+ }
+ throw new IllegalArgumentException("wrong hash");
+ }
+ // 3. If emBits < 8.hLen + 8.sLen + 9, output 'decoding error' and stop.
+ if (emBits < (8 * hLen + 8 * sLen + 9))
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("emBits < (8hLen + 8sLen + 9); sLen: " + String.valueOf(sLen));
+ }
+ throw new IllegalArgumentException("decoding error");
+ }
+ int emLen = (emBits + 7) / 8;
+ // 4. If the rightmost octet of EM does not have hexadecimal value bc,
+ // output 'inconsistent' and stop.
+ if ((EM[EM.length - 1] & 0xFF) != 0xBC)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("EM does not end with 0xBC");
+ }
+ return false;
+ }
+ // 5. Let maskedDB be the leftmost emLen ? hLen ? 1 octets of EM, and let
+ // H be the next hLen octets.
+ // 6. If the leftmost 8.emLen ? emBits bits of the leftmost octet in
+ // maskedDB are not all equal to zero, output 'inconsistent' and stop.
+ if ((EM[0] & (0xFF << (8 - (8 * emLen - emBits)))) != 0)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("Leftmost 8emLen - emBits bits of EM are not 0s");
+ }
+ return false;
+ }
+ byte[] DB = new byte[emLen - hLen - 1];
+ byte[] H = new byte[hLen];
+ System.arraycopy(EM, 0, DB, 0, emLen - hLen - 1);
+ System.arraycopy(EM, emLen - hLen - 1, H, 0, hLen);
+ // 7. Let dbMask = MGF(H, emLen ? hLen ? 1).
+ byte[] dbMask = MGF(H, emLen - hLen - 1);
+ // 8. Let DB = maskedDB XOR dbMask.
+ int i;
+ for (i = 0; i < DB.length; i++)
+ {
+ DB[i] = (byte) (DB[i] ^ dbMask[i]);
+ }
+ // 9. Set the leftmost 8.emLen ? emBits bits of DB to zero.
+ DB[0] &= (0xFF >>> (8 * emLen - emBits));
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("dbMask (decode): " + Util.toString(dbMask));
+ debug("DB (decode): " + Util.toString(DB));
+ }
+ // 10. If the emLen -hLen -sLen -2 leftmost octets of DB are not zero or
+ // if the octet at position emLen -hLen -sLen -1 is not equal to 0x01,
+ // output 'inconsistent' and stop.
+ // IMPORTANT (rsn): this is an error in the specs, the index of the 0x01
+ // byte should be emLen -hLen -sLen -2 and not -1! authors have been
+ // advised
+ for (i = 0; i < (emLen - hLen - sLen - 2); i++)
+ {
+ if (DB[i] != 0)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("DB[" + String.valueOf(i) + "] != 0x00");
+ }
+ return false;
+ }
+ }
+ if (DB[i] != 0x01)
+ { // i == emLen -hLen -sLen -2
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("DB's byte at position (emLen -hLen -sLen -2); i.e. "
+ + String.valueOf(i) + " is not 0x01");
+ }
+ return false;
+ }
+ // 11. Let salt be the last sLen octets of DB.
+ byte[] salt = new byte[sLen];
+ System.arraycopy(DB, DB.length - sLen, salt, 0, sLen);
+ // 12. Let M0 = 00 00 00 00 00 00 00 00 || mHash || salt;
+ // M0 is an octet string of length 8 + hLen + sLen with eight initial
+ // zero octets.
+ // 13. Let H0 = Hash(M0), an octet string of length hLen.
+ byte[] H0;
+ synchronized (hash)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ hash.update((byte) 0x00);
+ }
+ hash.update(mHash, 0, hLen);
+ hash.update(salt, 0, sLen);
+ H0 = hash.digest();
+ }
+ // 14. If H = H0, output 'consistent.' Otherwise, output 'inconsistent.'
+ return Arrays.equals(H, H0);
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ * <p>A mask generation function takes an octet string of variable length
+ * and a desired output length as input, and outputs an octet string of the
+ * desired length. There may be restrictions on the length of the input and
+ * output octet strings, but such bounds are generally very large. Mask
+ * generation functions are deterministic; the octet string output is
+ * completely determined by the input octet string. The output of a mask
+ * generation function should be pseudorandom, that is, it should be
+ * infeasible to predict, given one part of the output but not the input,
+ * another part of the output. The provable security of RSA-PSS relies on
+ * the random nature of the output of the mask generation function, which in
+ * turn relies on the random nature of the underlying hash function.</p>
+ *
+ * @param Z a seed.
+ * @param l the desired output length in octets.
+ * @return the mask.
+ * @exception IllegalArgumentException if the desired output length is too
+ * long.
+ */
+ private byte[] MGF(byte[] Z, int l)
+ {
+ // 1. If l > (2**32).hLen, output 'mask too long' and stop.
+ if (l < 1 || (l & 0xFFFFFFFFL) > ((hLen & 0xFFFFFFFFL) << 32L))
+ {
+ throw new IllegalArgumentException("mask too long");
+ }
+ // 2. Let T be the empty octet string.
+ byte[] result = new byte[l];
+ // 3. For i = 0 to CEILING(l/hLen) ? 1, do
+ int limit = ((l + hLen - 1) / hLen) - 1;
+ IMessageDigest hashZ = null;
+ hashZ = (IMessageDigest) hash.clone();
+ hashZ.digest();
+ hashZ.update(Z, 0, Z.length);
+ IMessageDigest hashZC = null;
+ byte[] t;
+ int sofar = 0;
+ int length;
+ for (int i = 0; i < limit; i++)
+ {
+ // 3.1 Convert i to an octet string C of length 4 with the primitive
+ // I2OSP: C = I2OSP(i, 4).
+ // 3.2 Concatenate the hash of the seed Z and C to the octet string T:
+ // T = T || Hash(Z || C)
+ hashZC = (IMessageDigest) hashZ.clone();
+ hashZC.update((byte) (i >>> 24));
+ hashZC.update((byte) (i >>> 16));
+ hashZC.update((byte) (i >>> 8));
+ hashZC.update((byte) i);
+ t = hashZC.digest();
+ length = l - sofar;
+ length = (length > hLen ? hLen : length);
+ System.arraycopy(t, 0, result, sofar, length);
+ sofar += length;
+ }
+ // 4. Output the leading l octets of T as the octet string mask.
+ return result;
+ }
+}
diff --git a/gnu/java/security/sig/rsa/RSA.java b/gnu/java/security/sig/rsa/RSA.java
new file mode 100644
index 000000000..4ef7232f1
--- /dev/null
+++ b/gnu/java/security/sig/rsa/RSA.java
@@ -0,0 +1,355 @@
+/* RSA.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Properties;
+import gnu.java.security.key.rsa.GnuRSAKey;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * <p>Utility methods related to the RSA algorithm.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ *
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ *
+ * <li><a href="http://crypto.stanford.edu/~dabo/abstracts/ssl-timing.html">
+ * Remote timing attacks are practical</a><br>
+ * D. Boneh and D. Brumley.</li>
+ * </ol>
+ */
+public class RSA
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final BigInteger ZERO = BigInteger.ZERO;
+
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial private constructor to enforce Singleton pattern. */
+ private RSA()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Signature and verification methods --------------------------------------
+
+ /**
+ * <p>An implementation of the <b>RSASP</b> method: Assuming that the
+ * designated RSA private key is a valid one, this method computes a
+ * <i>signature representative</i> for a designated <i>message
+ * representative</i> signed by the holder of the designated RSA private
+ * key.<p>
+ *
+ * @param K the RSA private key.
+ * @param m the <i>message representative</i>: an integer between
+ * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
+ * <i>modulus</i>.
+ * @return the <i>signature representative</i>, an integer between
+ * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
+ * <i>modulus</i>.
+ * @throws ClassCastException if <code>K</code> is not an RSA one.
+ * @throws IllegalArgumentException if <code>m</code> (the <i>message
+ * representative</i>) is out of range.
+ */
+ public static final BigInteger sign(final PrivateKey K, final BigInteger m)
+ {
+ try
+ {
+ return RSADP((RSAPrivateKey) K, m);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new IllegalArgumentException(
+ "message representative out of range");
+ }
+ }
+
+ /**
+ * <p>An implementation of the <b>RSAVP</b> method: Assuming that the
+ * designated RSA public key is a valid one, this method computes a
+ * <i>message representative</i> for the designated <i>signature
+ * representative</i> generated by an RSA private key, for a message
+ * intended for the holder of the designated RSA public key.</p>
+ *
+ * @param K the RSA public key.
+ * @param s the <i>signature representative</i>, an integer between
+ * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
+ * <i>modulus</i>.
+ * @return a <i>message representative</i>: an integer between <code>0</code>
+ * and <code>n - 1</code>, where <code>n</code> is the RSA <i>modulus</i>.
+ * @throws ClassCastException if <code>K</code> is not an RSA one.
+ * @throws IllegalArgumentException if <code>s</code> (the <i>signature
+ * representative</i>) is out of range.
+ */
+ public static final BigInteger verify(final PublicKey K, final BigInteger s)
+ {
+ try
+ {
+ return RSAEP((RSAPublicKey) K, s);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new IllegalArgumentException(
+ "signature representative out of range");
+ }
+ }
+
+ // Encryption and decryption methods ---------------------------------------
+
+ /**
+ * <p>An implementation of the <code>RSAEP</code> algorithm.</p>
+ *
+ * @param K the recipient's RSA public key.
+ * @param m the message representative as an MPI.
+ * @return the resulting MPI --an MPI between <code>0</code> and
+ * <code>n - 1</code> (<code>n</code> being the public shared modulus)-- that
+ * will eventually be padded with an appropriate framing/padding scheme.
+ * @throws ClassCastException if <code>K</code> is not an RSA one.
+ * @throws IllegalArgumentException if <code>m</code>, the message
+ * representative is not between <code>0</code> and <code>n - 1</code>
+ * (<code>n</code> being the public shared modulus).
+ */
+ public static final BigInteger encrypt(final PublicKey K, final BigInteger m)
+ {
+ try
+ {
+ return RSAEP((RSAPublicKey) K, m);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new IllegalArgumentException(
+ "message representative out of range");
+ }
+ }
+
+ /**
+ * <p>An implementation of the <code>RSADP</code> algorithm.</p>
+ *
+ * @param K the recipient's RSA private key.
+ * @param c the ciphertext representative as an MPI.
+ * @return the message representative, an MPI between <code>0</code> and
+ * <code>n - 1</code> (<code>n</code> being the shared public modulus).
+ * @throws ClassCastException if <code>K</code> is not an RSA one.
+ * @throws IllegalArgumentException if <code>c</code>, the ciphertext
+ * representative is not between <code>0</code> and <code>n - 1</code>
+ * (<code>n</code> being the shared public modulus).
+ */
+ public static final BigInteger decrypt(final PrivateKey K, final BigInteger c)
+ {
+ try
+ {
+ return RSADP((RSAPrivateKey) K, c);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new IllegalArgumentException(
+ "ciphertext representative out of range");
+ }
+ }
+
+ // Conversion methods ------------------------------------------------------
+
+ /**
+ * <p>Converts a <i>multi-precision integer</i> (MPI) <code>s</code> into an
+ * octet sequence of length <code>k</code>.</p>
+ *
+ * @param s the multi-precision integer to convert.
+ * @param k the length of the output.
+ * @return the result of the transform.
+ * @exception IllegalArgumentException if the length in octets of meaningful
+ * bytes of <code>s</code> is greater than <code>k</code>.
+ */
+ public static final byte[] I2OSP(final BigInteger s, final int k)
+ {
+ byte[] result = s.toByteArray();
+ if (result.length < k)
+ {
+ final byte[] newResult = new byte[k];
+ System.arraycopy(result, 0, newResult, k - result.length, result.length);
+ result = newResult;
+ }
+ else if (result.length > k)
+ { // leftmost extra bytes should all be 0
+ final int limit = result.length - k;
+ for (int i = 0; i < limit; i++)
+ {
+ if (result[i] != 0x00)
+ {
+ throw new IllegalArgumentException("integer too large");
+ }
+ }
+ final byte[] newResult = new byte[k];
+ System.arraycopy(result, limit, newResult, 0, k);
+ result = newResult;
+ }
+ return result;
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ private static final BigInteger RSAEP(final RSAPublicKey K, final BigInteger m)
+ {
+ // 1. If the representative m is not between 0 and n - 1, output
+ // "representative out of range" and stop.
+ final BigInteger n = K.getModulus();
+ if (m.compareTo(ZERO) < 0 || m.compareTo(n.subtract(ONE)) > 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ // 2. Let c = m^e mod n.
+ final BigInteger e = K.getPublicExponent();
+ final BigInteger result = m.modPow(e, n);
+ // 3. Output c.
+ return result;
+ }
+
+ private static final BigInteger RSADP(final RSAPrivateKey K, BigInteger c)
+ {
+ // 1. If the representative c is not between 0 and n - 1, output
+ // "representative out of range" and stop.
+ final BigInteger n = K.getModulus();
+ if (c.compareTo(ZERO) < 0 || c.compareTo(n.subtract(ONE)) > 0)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ // 2. The representative m is computed as follows.
+ BigInteger result;
+ if (!(K instanceof RSAPrivateCrtKey))
+ {
+ // a. If the first form (n, d) of K is used, let m = c^d mod n.
+ final BigInteger d = K.getPrivateExponent();
+ result = c.modPow(d, n);
+ }
+ else
+ {
+ // from [3] p.13 --see class docs:
+ // The RSA blinding operation calculates x = (r^e) * g mod n before
+ // decryption, where r is random, e is the RSA encryption exponent, and
+ // g is the ciphertext to be decrypted. x is then decrypted as normal,
+ // followed by division by r, i.e. (x^e) / r mod n. Since r is random,
+ // x is random and timing the decryption should not reveal information
+ // about the key. Note that r should be a new random number for every
+ // decryption.
+ final boolean rsaBlinding = Properties.doRSABlinding();
+ BigInteger r = null;
+ BigInteger e = null;
+ if (rsaBlinding)
+ { // pre-decryption
+ r = newR(n);
+ e = ((RSAPrivateCrtKey) K).getPublicExponent();
+ final BigInteger x = r.modPow(e, n).multiply(c).mod(n);
+ c = x;
+ }
+
+ // b. If the second form (p, q, dP, dQ, qInv) and (r_i, d_i, t_i)
+ // of K is used, proceed as follows:
+ final BigInteger p = ((RSAPrivateCrtKey) K).getPrimeP();
+ final BigInteger q = ((RSAPrivateCrtKey) K).getPrimeQ();
+ final BigInteger dP = ((RSAPrivateCrtKey) K).getPrimeExponentP();
+ final BigInteger dQ = ((RSAPrivateCrtKey) K).getPrimeExponentQ();
+ final BigInteger qInv = ((RSAPrivateCrtKey) K).getCrtCoefficient();
+
+ // i. Let m_1 = c^dP mod p and m_2 = c^dQ mod q.
+ final BigInteger m_1 = c.modPow(dP, p);
+ final BigInteger m_2 = c.modPow(dQ, q);
+ // ii. If u > 2, let m_i = c^(d_i) mod r_i, i = 3, ..., u.
+ // iii. Let h = (m_1 - m_2) * qInv mod p.
+ final BigInteger h = m_1.subtract(m_2).multiply(qInv).mod(p);
+ // iv. Let m = m_2 + q * h.
+ result = m_2.add(q.multiply(h));
+
+ if (rsaBlinding)
+ { // post-decryption
+ result = result.multiply(r.modInverse(n)).mod(n);
+ }
+ }
+
+ // 3. Output m
+ return result;
+ }
+
+ /**
+ * <p>Returns a random MPI with a random bit-length of the form <code>8b</code>,
+ * where <code>b</code> is in the range <code>[32..64]</code>.</p>
+ *
+ * @return a random MPI whose length in bytes is between 32 and 64 inclusive.
+ */
+ private static final BigInteger newR(final BigInteger N)
+ {
+ final int upper = (N.bitLength() + 7) / 8;
+ final int lower = upper / 2;
+ final byte[] bl = new byte[1];
+ SecureRandom rnd = new SecureRandom ();
+ int b;
+ do
+ {
+ rnd.nextBytes(bl);
+ b = bl[0] & 0xFF;
+ }
+ while (b < lower || b > upper);
+ final byte[] buffer = new byte[b]; // 256-bit MPI
+ rnd.nextBytes(buffer);
+ return new BigInteger(1, buffer);
+ }
+}
diff --git a/gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java b/gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java
new file mode 100644
index 000000000..b859fc358
--- /dev/null
+++ b/gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java
@@ -0,0 +1,242 @@
+/* RSAPKCS1V1_5Signature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.sig.BaseSignature;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+
+/**
+ * <p>The RSA-PKCS1-V1.5 signature scheme is a digital signature scheme with
+ * appendix (SSA) combining the RSA algorithm with the EMSA-PKCS1-v1_5 encoding
+ * method.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ *
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RSAPKCS1V1_5Signature extends BaseSignature
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The underlying EMSA-PKCS1-v1.5 instance for this object. */
+ private EMSA_PKCS1_V1_5 pkcs1;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Default 0-arguments constructor. Uses SHA-1 as the default hash.
+ */
+ public RSAPKCS1V1_5Signature()
+ {
+ this(Registry.SHA160_HASH);
+ }
+
+ /**
+ * <p>Constructs an instance of this object using the designated message
+ * digest algorithm as its underlying hash function.</p>
+ *
+ * @param mdName the canonical name of the underlying hash function.
+ */
+ public RSAPKCS1V1_5Signature(final String mdName)
+ {
+ super(Registry.RSA_PKCS1_V1_5_SIG, HashFactory.getInstance(mdName));
+
+ pkcs1 = EMSA_PKCS1_V1_5.getInstance(mdName);
+ }
+
+ /** Private constructor for cloning purposes. */
+ private RSAPKCS1V1_5Signature(final RSAPKCS1V1_5Signature that)
+ {
+ this(that.md.name());
+
+ this.publicKey = that.publicKey;
+ this.privateKey = that.privateKey;
+ this.md = (IMessageDigest) that.md.clone();
+ this.pkcs1 = (EMSA_PKCS1_V1_5) that.pkcs1.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in superclass ------------------------
+
+ public Object clone()
+ {
+ return new RSAPKCS1V1_5Signature(this);
+ }
+
+ protected void setupForVerification(final PublicKey k)
+ throws IllegalArgumentException
+ {
+ if (!(k instanceof RSAPublicKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ publicKey = k;
+ }
+
+ protected void setupForSigning(final PrivateKey k)
+ throws IllegalArgumentException
+ {
+ if (!(k instanceof RSAPrivateKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ privateKey = k;
+ }
+
+ protected Object generateSignature() throws IllegalStateException
+ {
+ // 1. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
+ // operation (Section 9.2) to the message M to produce an encoded
+ // message EM of length k octets:
+ //
+ // EM = EMSA-PKCS1-V1_5-ENCODE (M, k).
+ //
+ // If the encoding operation outputs "message too long," output
+ // "message too long" and stop. If the encoding operation outputs
+ // "intended encoded message length too short," output "RSA modulus
+ // too short" and stop.
+ final int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
+ final int k = (modBits + 7) / 8;
+ final byte[] EM = pkcs1.encode(md.digest(), k);
+
+ // 2. RSA signature:
+ // a. Convert the encoded message EM to an integer message epresentative
+ // m (see Section 4.2): m = OS2IP (EM).
+ final BigInteger m = new BigInteger(1, EM);
+ // b. Apply the RSASP1 signature primitive (Section 5.2.1) to the RSA
+ // private key K and the message representative m to produce an
+ // integer signature representative s: s = RSASP1 (K, m).
+ final BigInteger s = RSA.sign(privateKey, m);
+ // c. Convert the signature representative s to a signature S of length
+ // k octets (see Section 4.1): S = I2OSP (s, k).
+ // 3. Output the signature S.
+ return RSA.I2OSP(s, k);
+ }
+
+ protected boolean verifySignature(final Object sig)
+ throws IllegalStateException
+ {
+ if (publicKey == null)
+ {
+ throw new IllegalStateException();
+ }
+ final byte[] S = (byte[]) sig;
+ // 1. Length checking: If the length of the signature S is not k octets,
+ // output "invalid signature" and stop.
+ final int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
+ final int k = (modBits + 7) / 8;
+ if (S.length != k)
+ {
+ return false;
+ }
+ // 2. RSA verification:
+ // a. Convert the signature S to an integer signature representative
+ // s (see Section 4.2): s = OS2IP (S).
+ final BigInteger s = new BigInteger(1, S);
+ // b. Apply the RSAVP1 verification primitive (Section 5.2.2) to the
+ // RSA public key (n, e) and the signature representative s to
+ // produce an integer message representative m:
+ // m = RSAVP1 ((n, e), s).
+ // If RSAVP1 outputs "signature representative out of range,"
+ // output "invalid signature" and stop.
+ final BigInteger m;
+ try
+ {
+ m = RSA.verify(publicKey, s);
+ }
+ catch (IllegalArgumentException x)
+ {
+ return false;
+ }
+ // c. Convert the message representative m to an encoded message EM
+ // of length k octets (see Section 4.1): EM = I2OSP (m, k).
+ // If I2OSP outputs "integer too large," output "invalid signature"
+ // and stop.
+ final byte[] EM;
+ try
+ {
+ EM = RSA.I2OSP(m, k);
+ }
+ catch (IllegalArgumentException x)
+ {
+ return false;
+ }
+ // 3. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
+ // operation (Section 9.2) to the message M to produce a second
+ // encoded message EM' of length k octets:
+ // EM' = EMSA-PKCS1-V1_5-ENCODE (M, k).
+ // If the encoding operation outputs "message too long," output
+ // "message too long" and stop. If the encoding operation outputs
+ // "intended encoded message length too short," output "RSA modulus
+ // too short" and stop.
+ final byte[] EMp = pkcs1.encode(md.digest(), k);
+ // 4. Compare the encoded message EM and the second encoded message EM'.
+ // If they are the same, output "valid signature"; otherwise, output
+ // "invalid signature."
+ return Arrays.equals(EM, EMp);
+ }
+}
diff --git a/gnu/java/security/sig/rsa/RSAPSSSignature.java b/gnu/java/security/sig/rsa/RSAPSSSignature.java
new file mode 100644
index 000000000..3458d11da
--- /dev/null
+++ b/gnu/java/security/sig/rsa/RSAPSSSignature.java
@@ -0,0 +1,343 @@
+/* RSAPSSSignature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.sig.BaseSignature;
+import gnu.java.security.util.Util;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * <p>The RSA-PSS signature scheme is a public-key encryption scheme combining
+ * the RSA algorithm with the Probabilistic Signature Scheme (PSS) encoding
+ * method.</p>
+ *
+ * <p>The inventors of RSA are Ronald L. Rivest, Adi Shamir, and Leonard Adleman,
+ * while the inventors of the PSS encoding method are Mihir Bellare and Phillip
+ * Rogaway. During efforts to adopt RSA-PSS into the P1363a standards effort,
+ * certain adaptations to the original version of RSA-PSS were made by Mihir
+ * Bellare and Phillip Rogaway and also by Burt Kaliski (the editor of IEEE
+ * P1363a) to facilitate implementation and integration into existing protocols.</p>
+ *
+ * <p>References:</pr>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RSAPSSSignature extends BaseSignature
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "rsa-pss";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 1;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The underlying EMSA-PSS instance for this object. */
+ private EMSA_PSS pss;
+
+ /** The desired length in octets of the EMSA-PSS salt. */
+ private int sLen;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Default 0-arguments constructor. Uses SHA-1 as the default hash and a
+ * 0-octet <i>salt</i>.
+ */
+ public RSAPSSSignature()
+ {
+ this(Registry.SHA160_HASH, 0);
+ }
+
+ /**
+ * <p>Constructs an instance of this object using the designated message
+ * digest algorithm as its underlying hash function, and having 0-octet
+ * <i>salt</i>.</p>
+ *
+ * @param mdName the canonical name of the underlying hash function.
+ */
+ public RSAPSSSignature(String mdName)
+ {
+ this(mdName, 0);
+ }
+
+ /**
+ * <p>Constructs an instance of this object using the designated message
+ * digest algorithm as its underlying hash function.</p>
+ *
+ * @param mdName the canonical name of the underlying hash function.
+ * @param sLen the desired length in octets of the salt to use for encoding /
+ * decoding signatures.
+ */
+ public RSAPSSSignature(String mdName, int sLen)
+ {
+ super(Registry.RSA_PSS_SIG, HashFactory.getInstance(mdName));
+
+ pss = EMSA_PSS.getInstance(mdName);
+ this.sLen = sLen;
+ }
+
+ /** Private constructor for cloning purposes. */
+ private RSAPSSSignature(RSAPSSSignature that)
+ {
+ this(that.md.name(), that.sLen);
+
+ this.publicKey = that.publicKey;
+ this.privateKey = that.privateKey;
+ this.md = (IMessageDigest) that.md.clone();
+ this.pss = (EMSA_PSS) that.pss.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in superclass ------------------------
+
+ public Object clone()
+ {
+ return new RSAPSSSignature(this);
+ }
+
+ protected void setupForVerification(PublicKey k)
+ throws IllegalArgumentException
+ {
+ if (!(k instanceof RSAPublicKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ publicKey = (RSAPublicKey) k;
+ }
+
+ protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
+ {
+ if (!(k instanceof RSAPrivateKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ privateKey = (RSAPrivateKey) k;
+ }
+
+ protected Object generateSignature() throws IllegalStateException
+ {
+ // 1. Apply the EMSA-PSS encoding operation to the message M to produce an
+ // encoded message EM of length CEILING((modBits ? 1)/8) octets such
+ // that the bit length of the integer OS2IP(EM) is at most modBits ? 1:
+ // EM = EMSA-PSS-Encode(M,modBits ? 1).
+ // Note that the octet length of EM will be one less than k if
+ // modBits ? 1 is divisible by 8. If the encoding operation outputs
+ // 'message too long' or 'encoding error,' then output 'message too
+ // long' or 'encoding error' and stop.
+ int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
+ byte[] salt = new byte[sLen];
+ this.nextRandomBytes(salt);
+ byte[] EM = pss.encode(md.digest(), modBits - 1, salt);
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("EM (sign): " + Util.toString(EM));
+ }
+ // 2. Convert the encoded message EM to an integer message representative
+ // m (see Section 1.2.2): m = OS2IP(EM).
+ BigInteger m = new BigInteger(1, EM);
+ // 3. Apply the RSASP signature primitive to the public key K and the
+ // message representative m to produce an integer signature
+ // representative s: s = RSASP(K,m).
+ BigInteger s = RSA.sign(privateKey, m);
+ // 4. Convert the signature representative s to a signature S of length k
+ // octets (see Section 1.2.1): S = I2OSP(s, k).
+ // 5. Output the signature S.
+ int k = (modBits + 7) / 8;
+ // return encodeSignature(s, k);
+ return RSA.I2OSP(s, k);
+ }
+
+ protected boolean verifySignature(Object sig) throws IllegalStateException
+ {
+ if (publicKey == null)
+ {
+ throw new IllegalStateException();
+ }
+ // byte[] S = decodeSignature(sig);
+ byte[] S = (byte[]) sig;
+ // 1. If the length of the signature S is not k octets, output 'signature
+ // invalid' and stop.
+ int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
+ int k = (modBits + 7) / 8;
+ if (S.length != k)
+ {
+ return false;
+ }
+ // 2. Convert the signature S to an integer signature representative s:
+ // s = OS2IP(S).
+ BigInteger s = new BigInteger(1, S);
+ // 3. Apply the RSAVP verification primitive to the public key (n, e) and
+ // the signature representative s to produce an integer message
+ // representative m: m = RSAVP((n, e), s).
+ // If RSAVP outputs 'signature representative out of range,' then
+ // output 'signature invalid' and stop.
+ BigInteger m = null;
+ try
+ {
+ m = RSA.verify(publicKey, s);
+ }
+ catch (IllegalArgumentException x)
+ {
+ return false;
+ }
+ // 4. Convert the message representative m to an encoded message EM of
+ // length emLen = CEILING((modBits - 1)/8) octets, where modBits is
+ // equal to the bit length of the modulus: EM = I2OSP(m, emLen).
+ // Note that emLen will be one less than k if modBits - 1 is divisible
+ // by 8. If I2OSP outputs 'integer too large,' then output 'signature
+ // invalid' and stop.
+ int emBits = modBits - 1;
+ int emLen = (emBits + 7) / 8;
+ byte[] EM = m.toByteArray();
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("EM (verify): " + Util.toString(EM));
+ }
+ if (EM.length > emLen)
+ {
+ return false;
+ }
+ else if (EM.length < emLen)
+ {
+ byte[] newEM = new byte[emLen];
+ System.arraycopy(EM, 0, newEM, emLen - EM.length, EM.length);
+ EM = newEM;
+ }
+ // 5. Apply the EMSA-PSS decoding operation to the message M and the
+ // encoded message EM: Result = EMSA-PSS-Decode(M, EM, emBits). If
+ // Result = 'consistent,' output 'signature verified.' Otherwise,
+ // output 'signature invalid.'
+ byte[] mHash = md.digest();
+ boolean result = false;
+ try
+ {
+ result = pss.decode(mHash, EM, emBits, sLen);
+ }
+ catch (IllegalArgumentException x)
+ {
+ result = false;
+ }
+ return result;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * Converts the <i>signature representative</i> <code>s</code> to a signature
+ * <code>S</code> of length <code>k</code> octets; i.e.
+ * <code>S = I2OSP(s, k)</code>, where <code>k = CEILING(modBits/8)</code>.
+ *
+ * @param s the <i>signature representative</i>.
+ * @param k the length of the output.
+ * @return the signature as an octet sequence.
+ * @exception IllegalArgumentException if the length in octets of meaningful
+ * bytes of <code>s</code> is greater than <code>k</code>, implying that
+ * <code>s</code> is not less than the RSA <i>modulus</i>.
+ */
+ // private Object encodeSignature(BigInteger s, int k) {
+ // if (DEBUG && debuglevel > 8) {
+ // debug("s.bitLength(): "+String.valueOf(s.bitLength()));
+ // debug("k: "+String.valueOf(k));
+ // }
+ // byte[] result = s.toByteArray();
+ // if (DEBUG && debuglevel > 8) {
+ // debug("s: "+Util.toString(result));
+ // debug("s (bytes): "+String.valueOf(result.length));
+ // }
+ // if (result.length < k) {
+ // byte[] newResult = new byte[k];
+ // System.arraycopy(result, 0, newResult, k-result.length, result.length);
+ // result = newResult;
+ // } else if (result.length > k) { // leftmost extra bytes should all be 0
+ // int limit = result.length - k;
+ // for (int i = 0; i < limit; i++) {
+ // if (result[i] != 0x00) {
+ // throw new IllegalArgumentException("integer too large");
+ // }
+ // }
+ // byte[] newResult = new byte[k];
+ // System.arraycopy(result, limit, newResult, 0, k);
+ // result = newResult;
+ // }
+ // return result;
+ // }
+ /**
+ * Returns the output of a previously generated signature object as an octet
+ * sequence.<p>
+ *
+ * @return the octet sequence <code>S</code>.
+ */
+ // private byte[] decodeSignature(Object signature) {
+ // return (byte[]) signature;
+ // }
+}
diff --git a/gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java b/gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java
new file mode 100644
index 000000000..64a972ca3
--- /dev/null
+++ b/gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java
@@ -0,0 +1,159 @@
+/* RSAPSSSignatureRawCodec.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.ISignatureCodec;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * <p>An object that implements the {@link gnu.crypto.sig.ISignatureCodec}
+ * operations for the <i>Raw</i> format to use with RSA-PSS signatures.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RSAPSSSignatureRawCodec implements ISignatureCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.keys.IKeyPairCodec interface implementation
+ // -------------------------------------------------------------------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated RSA-PSS signature object
+ * according to the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for an RSA-PSS signature, in this implementation,
+ * is a byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_RSA_PSS_SIGNATURE},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the RSA-PSS signature
+ * bytes in internet order,</li>
+ * <li>the RSA-PSS signature bytes in internet order.</li>
+ * </ol>
+ *
+ * @param signature the signature to encode, consisting of the output of the
+ * <code>sign()</code> method of a {@link RSAPSSSignature} instance --a byte
+ * array.
+ * @return the <i>Raw</i> format encoding of the designated signature.
+ * @exception IllegalArgumentException if the designated signature is not an
+ * RSA-PSS one.
+ */
+ public byte[] encodeSignature(Object signature)
+ {
+ byte[] buffer;
+ try
+ {
+ buffer = (byte[]) signature;
+ }
+ catch (Exception x)
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[0]);
+ baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]);
+ baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]);
+ baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3]);
+
+ // version
+ baos.write(0x01);
+
+ // signature bytes
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public Object decodeSignature(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[0]
+ || k[1] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]
+ || k[2] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]
+ || k[3] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+
+ int i = 5;
+ int l;
+
+ // signature bytes
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ byte[] result = new byte[l];
+ System.arraycopy(k, i, result, 0, l);
+
+ return result;
+ }
+}
diff --git a/gnu/java/security/util/Base64.java b/gnu/java/security/util/Base64.java
new file mode 100644
index 000000000..f9998c38f
--- /dev/null
+++ b/gnu/java/security/util/Base64.java
@@ -0,0 +1,396 @@
+/* Base64.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Most of this implementation is from Robert Harder's public domain Base64
+ * code (version 1.4.1 available from &lt;http://iharder.net/xmlizable>).
+ */
+public class Base64
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "Base64";
+
+ private static final boolean DEBUG = true;
+
+ private static final int debuglevel = 9;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Maximum line length (76) of Base64 output. */
+ private static final int MAX_LINE_LENGTH = 76;
+
+ /** The new line character (\n) as one byte. */
+ private static final byte NEW_LINE = (byte) '\n';
+
+ /** The equals sign (=) as a byte. */
+ private static final byte EQUALS_SIGN = (byte) '=';
+
+ private static final byte WHITE_SPACE_ENC = -5; // white space in encoding
+
+ private static final byte EQUALS_SIGN_ENC = -1; // equals sign in encoding
+
+ /** The 64 valid Base64 values. */
+ private static final byte[] ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C',
+ (byte) 'D', (byte) 'E', (byte) 'F',
+ (byte) 'G', (byte) 'H', (byte) 'I',
+ (byte) 'J', (byte) 'K', (byte) 'L',
+ (byte) 'M', (byte) 'N', (byte) 'O',
+ (byte) 'P', (byte) 'Q', (byte) 'R',
+ (byte) 'S', (byte) 'T', (byte) 'U',
+ (byte) 'V', (byte) 'W', (byte) 'X',
+ (byte) 'Y', (byte) 'Z', (byte) 'a',
+ (byte) 'b', (byte) 'c', (byte) 'd',
+ (byte) 'e', (byte) 'f', (byte) 'g',
+ (byte) 'h', (byte) 'i', (byte) 'j',
+ (byte) 'k', (byte) 'l', (byte) 'm',
+ (byte) 'n', (byte) 'o', (byte) 'p',
+ (byte) 'q', (byte) 'r', (byte) 's',
+ (byte) 't', (byte) 'u', (byte) 'v',
+ (byte) 'w', (byte) 'x', (byte) 'y',
+ (byte) 'z', (byte) '0', (byte) '1',
+ (byte) '2', (byte) '3', (byte) '4',
+ (byte) '5', (byte) '6', (byte) '7',
+ (byte) '8', (byte) '9', (byte) '+',
+ (byte) '/' };
+
+ /**
+ * Translates a Base64 value to either its 6-bit reconstruction value or a
+ * negative number indicating some other meaning.
+ */
+ private static final byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
+ -5, -5, // Whitespace: Tab and Linefeed
+ -9, -9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9, -9, -9, -9, -9, -9, -9, -9, -9,
+ -9, -9, -9, -9, // Decimal 14 - 26
+ -9, -9, -9, -9, -9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9, -9, -9, -9, -9, -9, -9, -9, -9,
+ -9, // Decimal 33 - 42
+ 62, // Plus sign at decimal 43
+ -9, -9, -9, // Decimal 44 - 46
+ 63, // Slash at decimal 47
+ 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, // Numbers zero through nine
+ -9, -9, -9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9, -9, -9, // Decimal 62 - 64
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, // Letters 'A' through 'N'
+ 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, // Letters 'O' through 'Z'
+ -9, -9, -9, -9, -9, -9, // Decimal 91 - 96
+ 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, // Letters 'a' through 'm'
+ 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, // Letters 'n' through 'z'
+ -9, -9, -9, -9 // Decimal 123 - 126
+ };
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial private ctor to enfore Singleton pattern. */
+ private Base64()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Encodes a byte array into Base64 notation. Equivalent to calling
+ * <code>encode(source, 0, source.length)</code>.
+ *
+ * @param src the data to convert.
+ */
+ public static final String encode(final byte[] src)
+ {
+ return encode(src, 0, src.length, true);
+ }
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ *
+ * @param src the data to convert.
+ * @param off offset in array where conversion should begin.
+ * @param len length of data to convert.
+ * @param breakLines break lines at 80 characters or less.
+ */
+ public static final String encode(final byte[] src, final int off,
+ final int len, final boolean breakLines)
+ {
+ final int len43 = len * 4 / 3;
+ final byte[] outBuff = new byte[len43 // Main 4:3
+ + ((len % 3) > 0 ? 4 : 0) // Account for padding
+ + (breakLines ? (len43 / MAX_LINE_LENGTH)
+ : 0)]; // New lines
+ int d = 0;
+ int e = 0;
+ final int len2 = len - 2;
+ int lineLength = 0;
+ for (; d < len2; d += 3, e += 4)
+ {
+ encode3to4(src, d + off, 3, outBuff, e);
+ lineLength += 4;
+ if (breakLines && lineLength == MAX_LINE_LENGTH)
+ {
+ outBuff[e + 4] = NEW_LINE;
+ e++;
+ lineLength = 0;
+ }
+ }
+
+ if (d < len)
+ { // padding needed
+ encode3to4(src, d + off, len - d, outBuff, e);
+ e += 4;
+ }
+
+ return new String(outBuff, 0, e);
+ }
+
+ /**
+ * Decodes data from Base64 notation.
+ *
+ * @param s the string to decode.
+ * @return the decoded data.
+ */
+ public static final byte[] decode(final String s)
+ throws UnsupportedEncodingException
+ {
+ final byte[] bytes;
+ bytes = s.getBytes("US-ASCII");
+ return decode(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Decodes Base64 content in byte array format and returns the decoded byte
+ * array.
+ *
+ * @param src the Base64 encoded data.
+ * @param off the offset of where to begin decoding.
+ * @param len the length of characters to decode.
+ * @return the decoded data.
+ * @throws IllegalArgumentException if <code>src</code> contains an illegal
+ * Base-64 character.
+ */
+ public static byte[] decode(final byte[] src, final int off, final int len)
+ {
+ final int len34 = len * 3 / 4;
+ final byte[] outBuff = new byte[len34]; // Upper limit on size of output
+ int outBuffPosn = 0;
+ final byte[] b4 = new byte[4];
+ int b4Posn = 0;
+ int i;
+ byte sbiCrop, sbiDecode;
+ for (i = off; i < off + len; i++)
+ {
+ sbiCrop = (byte) (src[i] & 0x7F); // Only the low seven bits
+ sbiDecode = DECODABET[sbiCrop];
+ if (sbiDecode >= WHITE_SPACE_ENC)
+ { // White space, Equals sign or better
+ if (sbiDecode >= EQUALS_SIGN_ENC)
+ {
+ b4[b4Posn++] = sbiCrop;
+ if (b4Posn > 3)
+ {
+ outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
+ b4Posn = 0;
+ // If that was the equals sign, break out of 'for' loop
+ if (sbiCrop == EQUALS_SIGN)
+ break;
+ } // end if: quartet built
+ } // end if: equals sign or better
+ }
+ else
+ {
+ throw new IllegalArgumentException("Illegal BASE-64 character at #"
+ + i + ": " + src[i]
+ + "(decimal)");
+ }
+ }
+
+ final byte[] result = new byte[outBuffPosn];
+ System.arraycopy(outBuff, 0, result, 0, outBuffPosn);
+ return result;
+ }
+
+ /**
+ * <p>Encodes up to three bytes of the array <code>src</code> and writes
+ * the resulting four Base64 bytes to <code>dest</code>. The source and
+ * destination arrays can be manipulated anywhere along their length by
+ * specifying <code>sOffset</code> and <code>dOffset</code>.</p>
+ *
+ * <p>This method does not check to make sure the arrays are large enough to
+ * accomodate <code>sOffset + 3</code> for the <code>src</code> array or
+ * <code>dOffset + 4</code> for the <code>dest</code> array. The actual
+ * number of significant bytes in the input array is given by
+ * <code>numBytes</code>.</p>
+ *
+ * @param src the array to convert.
+ * @param sOffset the index where conversion begins.
+ * @param numBytes the number of significant bytes in your array.
+ * @param dest the array to hold the conversion.
+ * @param dOffset the index where output will be put.
+ * @return the <code>destination</code> array.
+ */
+ private static final byte[] encode3to4(final byte[] src, final int sOffset,
+ final int numBytes, final byte[] dest,
+ final int dOffset)
+ {
+ // 1 2 3
+ // 01234567890123456789012345678901 Bit position
+ // --------000000001111111122222222 Array position from threeBytes
+ // --------| || || || | Six bit groups to index ALPHABET
+ // >>18 >>12 >> 6 >> 0 Right shift necessary
+ // 0x3F 0x3F 0x3F Additional AND
+
+ // Create buffer with zero-padding if there are only one or two
+ // significant bytes passed in the array.
+ // We have to shift left 24 in order to flush out the 1's that appear
+ // when Java treats a value as negative that is cast from a byte to an int.
+ final int inBuff = (numBytes > 0 ? ((src[sOffset] << 24) >>> 8) : 0)
+ | (numBytes > 1 ? ((src[sOffset + 1] << 24) >>> 16) : 0)
+ | (numBytes > 2 ? ((src[sOffset + 2] << 24) >>> 24) : 0);
+ switch (numBytes)
+ {
+ case 3:
+ dest[dOffset] = ALPHABET[(inBuff >>> 18)];
+ dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
+ dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F];
+ dest[dOffset + 3] = ALPHABET[(inBuff) & 0x3F];
+ break;
+ case 2:
+ dest[dOffset] = ALPHABET[(inBuff >>> 18)];
+ dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
+ dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F];
+ dest[dOffset + 3] = EQUALS_SIGN;
+ break;
+ case 1:
+ dest[dOffset] = ALPHABET[(inBuff >>> 18)];
+ dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
+ dest[dOffset + 2] = EQUALS_SIGN;
+ dest[dOffset + 3] = EQUALS_SIGN;
+ break;
+ }
+ return dest;
+ }
+
+ /**
+ * <p>Decodes four bytes from array <code>src</code> and writes the
+ * resulting bytes (up to three of them) to <code>dest</code>.</p>
+ *
+ * <p>The source and destination arrays can be manipulated anywhere along
+ * their length by specifying <code>sOffset</code> and <code>dOffset</code>.
+ * </p>
+ *
+ * <p>This method does not check to make sure your arrays are large enough
+ * to accomodate <code>sOffset + 4</code> for the <code>src</code> array or
+ * <code>dOffset + 3</code> for the <code>dest</code> array. This method
+ * returns the actual number of bytes that were converted from the Base64
+ * encoding.</p>
+ *
+ * @param src the array to convert.
+ * @param sOffset the index where conversion begins.
+ * @param dest the array to hold the conversion.
+ * @param dOffset the index where output will be put.
+ * @return the number of decoded bytes converted.
+ */
+ private static final int decode4to3(final byte[] src, final int sOffset,
+ final byte[] dest, final int dOffset)
+ {
+ if (src[sOffset + 2] == EQUALS_SIGN)
+ { // Example: Dk==
+ final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
+ | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12);
+ dest[dOffset] = (byte) (outBuff >>> 16);
+ return 1;
+ }
+
+ if (src[sOffset + 3] == EQUALS_SIGN)
+ { // Example: DkL=
+ final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
+ | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
+ | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6);
+ dest[dOffset] = (byte) (outBuff >>> 16);
+ dest[dOffset + 1] = (byte) (outBuff >>> 8);
+ return 2;
+ }
+
+ try
+ { // Example: DkLE
+ final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
+ | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
+ | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6)
+ | ((DECODABET[src[sOffset + 3]] & 0xFF));
+ dest[dOffset] = (byte) (outBuff >> 16);
+ dest[dOffset + 1] = (byte) (outBuff >> 8);
+ dest[dOffset + 2] = (byte) outBuff;
+ return 3;
+ }
+ catch (Exception x)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("" + src[sOffset] + ": " + (DECODABET[src[sOffset]]));
+ debug("" + src[sOffset + 1] + ": " + (DECODABET[src[sOffset + 1]]));
+ debug("" + src[sOffset + 2] + ": " + (DECODABET[src[sOffset + 2]]));
+ debug("" + src[sOffset + 3] + ": " + (DECODABET[src[sOffset + 3]]));
+ }
+ return -1;
+ }
+ }
+}
diff --git a/gnu/java/security/util/ExpirableObject.java b/gnu/java/security/util/ExpirableObject.java
new file mode 100644
index 000000000..2d4452015
--- /dev/null
+++ b/gnu/java/security/util/ExpirableObject.java
@@ -0,0 +1,172 @@
+/* ExpirableObject.java -- an object that is automatically destroyed.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.security.auth.DestroyFailedException;
+import javax.security.auth.Destroyable;
+
+/**
+ * The base class for objects with sensitive data that are automatically
+ * destroyed after a timeout elapses. On creation, an object that extends
+ * this class will automatically be added to a {@link Timer} object that,
+ * once a timeout elapses, will automatically call the {@link
+ * Destroyable#destroy()} method.
+ *
+ * <p>Concrete subclasses must implement the {@link doDestroy()} method
+ * instead of {@link Destroyable#destroy()}; the behavior of that method
+ * should match exactly the behavior desired of <code>destroy()</code>.
+ *
+ * <p>Note that if a {@link DestroyFailedException} occurs when the timeout
+ * expires, it will not be reported.
+ *
+ * @see Destroyable
+ */
+public abstract class ExpirableObject implements Destroyable
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The default timeout, used in the default constructor.
+ */
+ public static final long DEFAULT_TIMEOUT = 3600000L;
+
+ /**
+ * The timer that expires instances.
+ */
+ private static final Timer EXPIRER = new Timer(true);
+
+ /**
+ * A reference to the task that will destroy this object when the timeout
+ * expires.
+ */
+ private final Destroyer destroyer;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Create a new expirable object that will expire after one hour.
+ */
+ protected ExpirableObject()
+ {
+ this(DEFAULT_TIMEOUT);
+ }
+
+ /**
+ * Create a new expirable object that will expire after the specified
+ * timeout.
+ *
+ * @param delay The delay before expiration.
+ * @throws IllegalArgumentException If <i>delay</i> is negative, or if
+ * <code>delay + System.currentTimeMillis()</code> is negative.
+ */
+ protected ExpirableObject(final long delay)
+ {
+ destroyer = new Destroyer(this);
+ EXPIRER.schedule(destroyer, delay);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Destroys this object. This method calls {@link doDestroy}, then, if
+ * no exception is thrown, cancels the task that would destroy this object
+ * when the timeout is reached.
+ *
+ * @throws DestroyFailedException If this operation fails.
+ */
+ public final void destroy() throws DestroyFailedException
+ {
+ doDestroy();
+ destroyer.cancel();
+ }
+
+ /**
+ * Subclasses must implement this method instead of the {@link
+ * Destroyable#destroy()} method.
+ *
+ * @throws DestroyFailedException If this operation fails.
+ */
+ protected abstract void doDestroy() throws DestroyFailedException;
+
+ // Inner classes.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The task that destroys the target when the timeout elapses.
+ */
+ private final class Destroyer extends TimerTask
+ {
+
+ // Fields.
+ // -----------------------------------------------------------------------
+
+ private final ExpirableObject target;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ Destroyer(final ExpirableObject target)
+ {
+ super();
+ this.target = target;
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public void run()
+ {
+ try
+ {
+ if (!target.isDestroyed())
+ target.doDestroy();
+ }
+ catch (DestroyFailedException dfe)
+ {
+ }
+ }
+ }
+}
diff --git a/gnu/java/security/util/Prime2.java b/gnu/java/security/util/Prime2.java
new file mode 100644
index 000000000..bf8df55ad
--- /dev/null
+++ b/gnu/java/security/util/Prime2.java
@@ -0,0 +1,632 @@
+/* Prime2.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import gnu.java.security.Properties;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.Random;
+import java.util.WeakHashMap;
+
+/**
+ * <p>A collection of prime number related utilities used in this library.</p>
+ */
+public class Prime2
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "prime";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_CERTAINTY = 20; // XXX is this a good value?
+
+ private static final BigInteger ZERO = BigInteger.ZERO;
+
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ private static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ /**
+ * The first SMALL_PRIME primes: Algorithm P, section 1.3.2, The Art of
+ * Computer Programming, Donald E. Knuth.
+ */
+ private static final int SMALL_PRIME_COUNT = 1000;
+
+ private static final BigInteger[] SMALL_PRIME = new BigInteger[SMALL_PRIME_COUNT];
+ static
+ {
+ long time = -System.currentTimeMillis();
+ SMALL_PRIME[0] = TWO;
+ int N = 3;
+ int J = 0;
+ int prime;
+ P2: while (true)
+ {
+ SMALL_PRIME[++J] = BigInteger.valueOf(N);
+ if (J >= 999)
+ {
+ break P2;
+ }
+ P4: while (true)
+ {
+ N += 2;
+ P6: for (int K = 1; true; K++)
+ {
+ prime = SMALL_PRIME[K].intValue();
+ if ((N % prime) == 0)
+ {
+ continue P4;
+ }
+ else if ((N / prime) <= prime)
+ {
+ continue P2;
+ }
+ }
+ }
+ }
+ time += System.currentTimeMillis();
+ if (DEBUG && debuglevel > 8)
+ {
+ StringBuffer sb;
+ for (int i = 0; i < (SMALL_PRIME_COUNT / 10); i++)
+ {
+ sb = new StringBuffer();
+ for (int j = 0; j < 10; j++)
+ {
+ sb.append(String.valueOf(SMALL_PRIME[i * 10 + j])).append(" ");
+ }
+ debug(sb.toString());
+ }
+ }
+ if (DEBUG && debuglevel > 4)
+ {
+ debug("Generating first " + String.valueOf(SMALL_PRIME_COUNT)
+ + " primes took: " + String.valueOf(time) + " ms.");
+ }
+ }
+
+ private static final Map knownPrimes = new WeakHashMap();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private Prime2()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trial division for the first 1000 small primes.</p>
+ *
+ * <p>Returns <code>true</code> if at least one small prime, among the first
+ * 1000 ones, was found to divide the designated number. Retuens <code>false</code>
+ * otherwise.</p>
+ *
+ * @param w the number to test.
+ * @return <code>true</code> if at least one small prime was found to divide
+ * the designated number.
+ */
+ public static boolean hasSmallPrimeDivisor(BigInteger w)
+ {
+ BigInteger prime;
+ for (int i = 0; i < SMALL_PRIME_COUNT; i++)
+ {
+ prime = SMALL_PRIME[i];
+ if (w.mod(prime).equals(ZERO))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(prime.toString(16) + " | " + w.toString(16) + "...");
+ }
+ return true;
+ }
+ }
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " has no small prime divisors...");
+ }
+ return false;
+ }
+
+ /**
+ * <p>Java port of Colin Plumb primality test (Euler Criterion)
+ * implementation for a base of 2 --from bnlib-1.1 release, function
+ * primeTest() in prime.c. this is his comments; (bn is our w).</p>
+ *
+ * <p>"Now, check that bn is prime. If it passes to the base 2, it's prime
+ * beyond all reasonable doubt, and everything else is just gravy, but it
+ * gives people warm fuzzies to do it.</p>
+ *
+ * <p>This starts with verifying Euler's criterion for a base of 2. This is
+ * the fastest pseudoprimality test that I know of, saving a modular squaring
+ * over a Fermat test, as well as being stronger. 7/8 of the time, it's as
+ * strong as a strong pseudoprimality test, too. (The exception being when
+ * <code>bn == 1 mod 8</code> and <code>2</code> is a quartic residue, i.e.
+ * <code>bn</code> is of the form <code>a^2 + (8*b)^2</code>.) The precise
+ * series of tricks used here is not documented anywhere, so here's an
+ * explanation. Euler's criterion states that if <code>p</code> is prime
+ * then <code>a^((p-1)/2)</code> is congruent to <code>Jacobi(a,p)</code>,
+ * modulo <code>p</code>. <code>Jacobi(a, p)</code> is a function which is
+ * <code>+1</code> if a is a square modulo <code>p</code>, and <code>-1</code>
+ * if it is not. For <code>a = 2</code>, this is particularly simple. It's
+ * <code>+1</code> if <code>p == +/-1 (mod 8)</code>, and <code>-1</code> if
+ * <code>m == +/-3 (mod 8)</code>. If <code>p == 3 (mod 4)</code>, then all
+ * a strong test does is compute <code>2^((p-1)/2)</code>. and see if it's
+ * <code>+1</code> or <code>-1</code>. (Euler's criterion says <i>which</i>
+ * it should be.) If <code>p == 5 (mod 8)</code>, then <code>2^((p-1)/2)</code>
+ * is <code>-1</code>, so the initial step in a strong test, looking at
+ * <code>2^((p-1)/4)</code>, is wasted --you're not going to find a
+ * <code>+/-1</code> before then if it <b>is</b> prime, and it shouldn't
+ * have either of those values if it isn't. So don't bother.</p>
+ *
+ * <p>The remaining case is <code>p == 1 (mod 8)</code>. In this case, we
+ * expect <code>2^((p-1)/2) == 1 (mod p)</code>, so we expect that the
+ * square root of this, <code>2^((p-1)/4)</code>, will be <code>+/-1 (mod p)
+ * </code>. Evaluating this saves us a modular squaring 1/4 of the time. If
+ * it's <code>-1</code>, a strong pseudoprimality test would call <code>p</code>
+ * prime as well. Only if the result is <code>+1</code>, indicating that
+ * <code>2</code> is not only a quadratic residue, but a quartic one as well,
+ * does a strong pseudoprimality test verify more things than this test does.
+ * Good enough.</p>
+ *
+ * <p>We could back that down another step, looking at <code>2^((p-1)/8)</code>
+ * if there was a cheap way to determine if <code>2</code> were expected to
+ * be a quartic residue or not. Dirichlet proved that <code>2</code> is a
+ * quadratic residue iff <code>p</code> is of the form <code>a^2 + (8*b^2)</code>.
+ * All primes <code>== 1 (mod 4)</code> can be expressed as <code>a^2 +
+ * (2*b)^2</code>, but I see no cheap way to evaluate this condition."</p>
+ *
+ * @param w the number to test.
+ * @return <code>true</code> iff the designated number passes Euler criterion
+ * as implemented by Colin Plumb in his <i>bnlib</i> version 1.1.
+ */
+
+ // FIXME this method incorrectly returns false for certain primes, notably
+ // 38737, 61681, 65537, 229153, and 274177.
+ public static boolean passEulerCriterion(final BigInteger w)
+ {
+ // first check if it's already a known prime
+ WeakReference obj = (WeakReference) knownPrimes.get(w);
+ if (obj != null && w.equals(obj.get()))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug("found in known primes");
+ }
+ return true;
+ }
+
+ BigInteger w_minus_one = w.subtract(ONE);
+ BigInteger e = w_minus_one;
+ // l is the 3 least-significant bits of e
+ int l = e.and(BigInteger.valueOf(7L)).intValue();
+ int j = 1; // Where to start in prime array for strong prime tests
+ BigInteger A;
+ int k;
+
+ if ((l & 7) != 0)
+ {
+ e = e.shiftRight(1);
+ A = TWO.modPow(e, w);
+ if ((l & 7) == 6)
+ { // bn == 7 mod 8, expect +1
+ if (A.bitCount() != 1)
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " fails Euler criterion #1...");
+ }
+ return false; // Not prime
+ }
+ k = 1;
+ }
+ else
+ { // bn == 3 or 5 mod 8, expect -1 == bn-1
+ A = A.add(ONE);
+ if (!A.equals(w))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " fails Euler criterion #2...");
+ }
+ return false; // Not prime
+ }
+ k = 1;
+ if ((l & 4) != 0)
+ { // bn == 5 mod 8, make odd for strong tests
+ e = e.shiftRight(1);
+ k = 2;
+ }
+ }
+ }
+ else
+ { // bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn
+ e = e.shiftRight(2);
+ A = TWO.modPow(e, w);
+ if (A.bitCount() == 1)
+ {
+ j = 0; // Re-do strong prime test to base 2
+ }
+ else
+ {
+ A = A.add(ONE);
+ if (!A.equals(w))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " fails Euler criterion #3...");
+ }
+ return false; // Not prime
+ }
+ }
+ // bnMakeOdd(n) = d * 2^s. Replaces n with d and returns s.
+ k = e.getLowestSetBit();
+ e = e.shiftRight(k);
+ k += 2;
+ }
+ // It's prime! Now go on to confirmation tests
+
+ // Now, e = (bn-1)/2^k is odd. k >= 1, and has a given value with
+ // probability 2^-k, so its expected value is 2. j = 1 in the usual case
+ // when the previous test was as good as a strong prime test, but 1/8 of
+ // the time, j = 0 because the strong prime test to the base 2 needs to
+ // be re-done.
+ //for (int i = j; i < SMALL_PRIME_COUNT; i++) {
+ for (int i = j; i < 13; i++)
+ { // try only the first 13 primes
+ A = SMALL_PRIME[i];
+ A = A.modPow(e, w);
+ if (A.bitCount() == 1)
+ {
+ continue; // Passed this test
+ }
+ l = k;
+ while (true)
+ {
+ // A = A.add(ONE);
+ // if (A.equals(w)) { // Was result bn-1?
+ if (A.equals(w_minus_one))
+ { // Was result bn-1?
+ break; // Prime
+ }
+ if (--l == 0)
+ { // Reached end, not -1? luck?
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " fails Euler criterion #4...");
+ }
+ return false; // Failed, not prime
+ }
+ // This portion is executed, on average, once
+ // A = A.subtract(ONE); // Put a back where it was
+ A = A.modPow(TWO, w);
+ if (A.bitCount() == 1)
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " fails Euler criterion #5...");
+ }
+ return false; // Failed, not prime
+ }
+ }
+ // It worked (to the base primes[i])
+ }
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " passes Euler criterion...");
+ }
+
+ // store it in the known primes weak hash-map
+ knownPrimes.put(w, new WeakReference(w));
+
+ return true;
+ }
+
+ /**
+ * <p>Checks Fermat's Little Theorem for base <i>b</i>; i.e.
+ * <code><i>b</i>**(w-1) == 1 (mod w)</code>.</p>
+ *
+ * @param w the number to test.
+ * @param t the number of random bases to test.
+ * @return <code>true</code> iff <code><i>b</i>**(w-1) == 1 (mod w)</code>,
+ * for some <i>b</i>.
+ */
+ public static boolean passFermatLittleTheorem(final BigInteger w, int t)
+ {
+ final BigInteger w_minus_one = w.subtract(ONE);
+ if (t <= 0)
+ {
+ t = 10; // XXX
+ }
+ if (!TWO.modPow(w_minus_one, w).equals(ONE))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " fails Fermat's little theorem for base 2");
+ }
+ return false;
+ }
+ for (int i = 0; i < t; i++)
+ {
+ byte[] buf = new byte[(w.bitLength() + 7) / 8 - 1];
+ BigInteger base = null;
+ do
+ {
+ new Random ().nextBytes(buf);
+ base = new BigInteger(1, buf);
+ }
+ while (base.compareTo(TWO) < 0 || base.compareTo(w_minus_one) > 0);
+ if (!base.modPow(w_minus_one, w).equals(ONE))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16)
+ + " fails Fermat's little theorem for base "
+ + base.toString(16));
+ }
+ return false;
+ }
+ }
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " passes Fermat's little theorem for " + t
+ + " bases...");
+ }
+ return true;
+ }
+
+ /**
+ * <p>Applies the Miller-Rabin strong probabilistic primality test.</p>
+ *
+ * <p>The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Note
+ * 4.57 states that for <code>q</code>, <code>n=18</code> is enough while
+ * for <code>p</code>, <code>n=6</code> (512 bits) or <code>n=3</cdoe> (1024
+ * bits) are enough to yield <i>robust</i> primality tests. The values used
+ * are from table 4.4 given in Note 4.49.</p>
+ *
+ * @param w the number to test.
+ * @return <code>true</code> iff the designated number passes the Miller-
+ * Rabin probabilistic primality test for a computed number of rounds.
+ */
+ public static boolean passMillerRabin(BigInteger n, int t)
+ {
+ int nbytes = (n.bitLength() + 7) / 8;
+ byte[] ab = new byte[nbytes];
+
+ // 1. Write n - 1 = 2^s * r.
+ BigInteger n_minus_1 = n.subtract(ONE);
+ BigInteger r = n_minus_1;
+ int s = 0;
+ while (!r.testBit(0))
+ {
+ r = r.shiftRight(1);
+ s++;
+ }
+
+ // 2. For i from 1 to t, do:
+ for (int i = 0; i < t; i++)
+ {
+
+ // 2.1 Choose a random integer a, 2 <= a <= n - 2.
+ BigInteger a;
+ do
+ {
+ new Random ().nextBytes(ab);
+ a = new BigInteger(1, ab);
+ }
+ while (a.compareTo(TWO) < 0 || a.compareTo(n) > 0);
+
+ // 2.2 Compute y = a^r mod n.
+ BigInteger y = a.modPow(r, n);
+
+ // If y != 1 and y != n - 1, then:
+ if (!y.equals(ONE) && !y.equals(n_minus_1))
+ {
+ for (int j = 1; j < s - 1 && !y.equals(n_minus_1); j++)
+ {
+ // Compute y = y^2 mod n.
+ y = y.modPow(TWO, n);
+
+ // If y = 1 return "composite"
+ if (y.equals(ONE))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(n.toString(16) + " fails Miller-Rabin test...");
+ }
+ return false;
+ }
+ }
+ // If y != n - 1 return "composite"
+ if (!y.equals(n_minus_1))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(n.toString(16) + " fails Miller-Rabin test...");
+ }
+ return false;
+ }
+ }
+ }
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(n.toString(16) + " passes Miller-Rabin test...");
+ }
+ return true;
+ }
+
+ public static boolean isProbablePrime(BigInteger w)
+ {
+ return isProbablePrime(w, DEFAULT_CERTAINTY);
+ }
+
+ /**
+ * <p>This implementation does not rely solely on the Miller-Rabin strong
+ * probabilistic primality test to claim the primality of the designated
+ * number. It instead, tries dividing the designated number by the first 1000
+ * small primes, and if no divisor was found, invokes a port of Colin Plumb's
+ * implementation of the Euler Criterion, then tries the Miller-Rabin test.</p>
+ *
+ * @param w the integer to test.
+ * @param certainty the certainty with which to compute the test.
+ * @param doMillerRabin if <code>true</code> and the designated integer was
+ * already found to be a probable prime, then also do a Miller-Rabin test.
+ * @return <code>true</code> iff the designated number has no small prime
+ * divisor passes the Euler criterion, and optionally a Miller-Rabin test.
+ */
+ public static boolean isProbablePrime(BigInteger w, int certainty)
+ {
+ // Nonnumbers are not prime.
+ if (w == null)
+ {
+ return false;
+ }
+
+ // eliminate trivial cases when w == 0 or 1
+ if (w.equals(ZERO) || w.equals(ONE))
+ {
+ return false;
+ }
+
+ // Test if w is a known small prime.
+ for (int i = 0; i < SMALL_PRIME_COUNT; i++)
+ {
+ if (w.equals(SMALL_PRIME[i]))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " is a small prime");
+ }
+ return true;
+ }
+ }
+
+ // trial division with first 1000 primes
+ if (hasSmallPrimeDivisor(w))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " has a small prime divisor. Rejected...");
+ }
+ return false;
+ }
+
+ // Do a check with Fermat's little theorem.
+ // if (passFermatLittleTheorem(w, certainty)) {
+ // if (DEBUG && debuglevel > 4) {
+ // debug(w.toString(16)+" passes Fermat's little theorem...");
+ // }
+ // } else {
+ // if (DEBUG && debuglevel > 4) {
+ // debug(w.toString(16)+" fails Fermat's little theorem. Rejected...");
+ // }
+ // return false;
+ // }
+
+ // Euler's criterion.
+ // if (passEulerCriterion(w)) {
+ // if (DEBUG && debuglevel > 4) {
+ // debug(w.toString(16)+" passes Euler's criterion...");
+ // }
+ // } else {
+ // if (DEBUG && debuglevel > 4) {
+ // debug(w.toString(16)+" fails Euler's criterion. Rejected...");
+ // }
+ // return false;
+ // }
+
+ // Miller-Rabin probabilistic primality test.
+ if (passMillerRabin(w, certainty))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " passes Miller-Rabin PPT...");
+ }
+ }
+ else
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " fails Miller-Rabin PPT. Rejected...");
+ }
+ return false;
+ }
+
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " is probable prime. Accepted...");
+ }
+
+ // now compare to JDK primality test
+ if (DEBUG && debuglevel > 0 && !w.isProbablePrime(certainty))
+ {
+ System.err.println("The gnu.crypto library and the JDK disagree on "
+ + "whether 0x" + w.toString(16)
+ + " is a probable prime or not.");
+ System.err.println("While this library claims it is, the JDK claims"
+ + " the opposite.");
+ System.err.println("Please contact the maintainer of this library, "
+ + "and provide this message for further investigation. TIA");
+ }
+
+ return true;
+ }
+}
diff --git a/gnu/java/security/util/Sequence.java b/gnu/java/security/util/Sequence.java
new file mode 100644
index 000000000..5edc7942e
--- /dev/null
+++ b/gnu/java/security/util/Sequence.java
@@ -0,0 +1,149 @@
+/* Sequence.java -- a sequence of integers.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.util.AbstractList;
+import java.util.LinkedList;
+
+/**
+ * A monotonic sequence of integers in the finite field 2<sup>32</sup>.
+ */
+public final class Sequence extends AbstractList
+{
+
+ // Field.
+ // ------------------------------------------------------------------------
+
+ private final Integer[] sequence;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a sequence of integers from 0 to <i>end</i>, with an increment
+ * of 1. If <i>end</i> is less than 0, then the sequence will wrap around
+ * through all positive integers then negative integers until the end
+ * value is reached. Naturally, this will result in an enormous object,
+ * so don't do this.
+ *
+ * @param end The ending value.
+ */
+ public Sequence(int end)
+ {
+ this(0, end, 1);
+ }
+
+ /**
+ * Create a sequence of integers from <i>start</i> to <i>end</i>, with an
+ * increment of 1. If <i>end</i> is less than <i>start</i>, then the sequence
+ * will wrap around until the end value is reached. Naturally, this will
+ * result in an enormous object, so don't do this.
+ *
+ * @param start The starting value.
+ * @param end The ending value.
+ */
+ public Sequence(int start, int end)
+ {
+ this(start, end, 1);
+ }
+
+ /**
+ * Create a sequence of integers from <i>start</i> to <i>end</i>, with an
+ * increment of <i>span</i>. If <i>end</i> is less than <i>start</i>, then
+ * the sequence will wrap around until the end value is reached. Naturally,
+ * this will result in an enormous object, so don't do this.
+ *
+ * <p><i>span</i> can be negative, resulting in a decresing sequence.
+ *
+ * <p>If <i>span</i> is 0, then the sequence will contain {<i>start</i>,
+ * <i>end</i>} if <i>start</i> != <i>end</i>, or just the singleton
+ * <i>start</i> if <i>start</i> == <i>end</i>.
+ *
+ * @param start The starting value.
+ * @param end The ending value.
+ * @param span The increment value.
+ */
+ public Sequence(int start, int end, int span)
+ {
+ if (span == 0)
+ {
+ if (start != end)
+ {
+ sequence = new Integer[] { new Integer(start), new Integer(end) };
+ }
+ else
+ {
+ sequence = new Integer[] { new Integer(start) };
+ }
+ }
+ else
+ {
+ LinkedList l = new LinkedList();
+ for (int i = start; i != end; i += span)
+ {
+ l.add(new Integer(i));
+ }
+ l.add(new Integer(end));
+ sequence = (Integer[]) l.toArray(new Integer[l.size()]);
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public Object get(int index)
+ {
+ if (index < 0 || index >= size())
+ {
+ throw new IndexOutOfBoundsException("index=" + index + ", size="
+ + size());
+ }
+ return sequence[index];
+ }
+
+ public int size()
+ {
+ return sequence.length;
+ }
+
+ public Object[] toArray()
+ {
+ return (Object[]) sequence.clone();
+ }
+}
diff --git a/gnu/java/security/util/SimpleList.java b/gnu/java/security/util/SimpleList.java
new file mode 100644
index 000000000..b2525c4b8
--- /dev/null
+++ b/gnu/java/security/util/SimpleList.java
@@ -0,0 +1,171 @@
+/* SimpleList.java -- simple way to make tuples.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A simple way to create immutable n-tuples. This class can be created with
+ * up to four elements specified via one of the constructors, or with a
+ * collection of arbitrary size.
+ */
+public final class SimpleList extends AbstractList
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ private final Object[] elements;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a singleton list.
+ *
+ * @param e1 The first element.
+ */
+ public SimpleList(final Object element)
+ {
+ elements = new Object[1];
+ elements[0] = element;
+ }
+
+ /**
+ * Create an ordered pair (2-tuple).
+ *
+ * @param e1 The first element.
+ * @param e2 The second element.
+ */
+ public SimpleList(final Object e1, final Object e2)
+ {
+ elements = new Object[2];
+ elements[0] = e1;
+ elements[1] = e2;
+ }
+
+ /**
+ * Create a 3-tuple.
+ *
+ * @param e1 The first element.
+ * @param e2 The second element.
+ * @param e3 The third element.
+ */
+ public SimpleList(final Object e1, final Object e2, final Object e3)
+ {
+ elements = new Object[3];
+ elements[0] = e1;
+ elements[1] = e2;
+ elements[2] = e3;
+ }
+
+ /**
+ * Create a 4-tuple.
+ *
+ * @param e1 The first element.
+ * @param e2 The second element.
+ * @param e3 The third element.
+ * @param e4 The fourth element.
+ */
+ public SimpleList(final Object e1, final Object e2, final Object e3,
+ final Object e4)
+ {
+ elements = new Object[4];
+ elements[0] = e1;
+ elements[1] = e2;
+ elements[2] = e3;
+ elements[3] = e4;
+ }
+
+ /**
+ * Create the empty list.
+ */
+ public SimpleList()
+ {
+ elements = null;
+ }
+
+ /**
+ * Create an n-tuple of arbitrary size. Even if the supplied collection has
+ * no natural order, the created n-tuple will have the order that the
+ * elements are returned by the collection's iterator.
+ *
+ * @param c The collection.
+ */
+ public SimpleList(Collection c)
+ {
+ elements = new Object[c.size()];
+ int i = 0;
+ for (Iterator it = c.iterator(); it.hasNext() && i < elements.length;)
+ {
+ elements[i++] = it.next();
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public int size()
+ {
+ if (elements == null)
+ return 0;
+ return elements.length;
+ }
+
+ public Object get(int index)
+ {
+ if (elements == null)
+ {
+ throw new IndexOutOfBoundsException("list is empty");
+ }
+ if (index < 0 || index >= elements.length)
+ {
+ throw new IndexOutOfBoundsException("index=" + index + ", size="
+ + size());
+ }
+ return elements[index];
+ }
+
+ public String toString()
+ {
+ return SimpleList.class.getName() + "(" + size() + ") " + super.toString();
+ }
+}
diff --git a/gnu/java/security/util/Util.java b/gnu/java/security/util/Util.java
new file mode 100644
index 000000000..53f8e3c2c
--- /dev/null
+++ b/gnu/java/security/util/Util.java
@@ -0,0 +1,692 @@
+/* Util.java -- various utility routines.
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.math.BigInteger;
+
+/**
+ * <p>A collection of utility methods used throughout this project.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Util
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Hex charset
+ private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
+
+ // Base-64 charset
+ private static final String BASE64_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
+
+ private static final char[] BASE64_CHARSET = BASE64_CHARS.toCharArray();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private Util()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns a string of hexadecimal digits from a byte array. Each byte is
+ * converted to 2 hex symbols; zero(es) included.</p>
+ *
+ * <p>This method calls the method with same name and three arguments as:</p>
+ *
+ * <pre>
+ * toString(ba, 0, ba.length);
+ * </pre>
+ *
+ * @param ba the byte array to convert.
+ * @return a string of hexadecimal characters (two for each byte)
+ * representing the designated input byte array.
+ */
+ public static String toString(byte[] ba)
+ {
+ return toString(ba, 0, ba.length);
+ }
+
+ /**
+ * <p>Returns a string of hexadecimal digits from a byte array, starting at
+ * <code>offset</code> and consisting of <code>length</code> bytes. Each byte
+ * is converted to 2 hex symbols; zero(es) included.</p>
+ *
+ * @param ba the byte array to convert.
+ * @param offset the index from which to start considering the bytes to
+ * convert.
+ * @param length the count of bytes, starting from the designated offset to
+ * convert.
+ * @return a string of hexadecimal characters (two for each byte)
+ * representing the designated input byte sub-array.
+ */
+ public static final String toString(byte[] ba, int offset, int length)
+ {
+ char[] buf = new char[length * 2];
+ for (int i = 0, j = 0, k; i < length;)
+ {
+ k = ba[offset + i++];
+ buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
+ buf[j++] = HEX_DIGITS[k & 0x0F];
+ }
+ return new String(buf);
+ }
+
+ /**
+ * <p>Returns a string of hexadecimal digits from a byte array. Each byte is
+ * converted to 2 hex symbols; zero(es) included. The argument is
+ * treated as a large little-endian integer and is returned as a
+ * large big-endian integer.</p>
+ *
+ * <p>This method calls the method with same name and three arguments as:</p>
+ *
+ * <pre>
+ * toReversedString(ba, 0, ba.length);
+ * </pre>
+ *
+ * @param ba the byte array to convert.
+ * @return a string of hexadecimal characters (two for each byte)
+ * representing the designated input byte array.
+ */
+ public static String toReversedString(byte[] ba)
+ {
+ return toReversedString(ba, 0, ba.length);
+ }
+
+ /**
+ * <p>Returns a string of hexadecimal digits from a byte array, starting at
+ * <code>offset</code> and consisting of <code>length</code> bytes. Each byte
+ * is converted to 2 hex symbols; zero(es) included.</p>
+ *
+ * <p>The byte array is treated as a large little-endian integer, and
+ * is returned as a large big-endian integer.</p>
+ *
+ * @param ba the byte array to convert.
+ * @param offset the index from which to start considering the bytes to
+ * convert.
+ * @param length the count of bytes, starting from the designated offset to
+ * convert.
+ * @return a string of hexadecimal characters (two for each byte)
+ * representing the designated input byte sub-array.
+ */
+ public static final String toReversedString(byte[] ba, int offset, int length)
+ {
+ char[] buf = new char[length * 2];
+ for (int i = offset + length - 1, j = 0, k; i >= offset;)
+ {
+ k = ba[offset + i--];
+ buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
+ buf[j++] = HEX_DIGITS[k & 0x0F];
+ }
+ return new String(buf);
+ }
+
+ /**
+ * <p>Returns a byte array from a string of hexadecimal digits.</p>
+ *
+ * @param s a string of hexadecimal ASCII characters
+ * @return the decoded byte array from the input hexadecimal string.
+ */
+ public static byte[] toBytesFromString(String s)
+ {
+ int limit = s.length();
+ byte[] result = new byte[((limit + 1) / 2)];
+ int i = 0, j = 0;
+ if ((limit % 2) == 1)
+ {
+ result[j++] = (byte) fromDigit(s.charAt(i++));
+ }
+ while (i < limit)
+ {
+ result[j] = (byte) (fromDigit(s.charAt(i++)) << 4);
+ result[j++] |= (byte) fromDigit(s.charAt(i++));
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns a byte array from a string of hexadecimal digits, interpreting
+ * them as a large big-endian integer and returning it as a large
+ * little-endian integer.</p>
+ *
+ * @param s a string of hexadecimal ASCII characters
+ * @return the decoded byte array from the input hexadecimal string.
+ */
+ public static byte[] toReversedBytesFromString(String s)
+ {
+ int limit = s.length();
+ byte[] result = new byte[((limit + 1) / 2)];
+ int i = 0;
+ if ((limit % 2) == 1)
+ {
+ result[i++] = (byte) fromDigit(s.charAt(--limit));
+ }
+ while (limit > 0)
+ {
+ result[i] = (byte) fromDigit(s.charAt(--limit));
+ result[i++] |= (byte) (fromDigit(s.charAt(--limit)) << 4);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns a number from <code>0</code> to <code>15</code> corresponding
+ * to the designated hexadecimal digit.</p>
+ *
+ * @param c a hexadecimal ASCII symbol.
+ */
+ public static int fromDigit(char c)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ return c - '0';
+ }
+ else if (c >= 'A' && c <= 'F')
+ {
+ return c - 'A' + 10;
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ return c - 'a' + 10;
+ }
+ else
+ throw new IllegalArgumentException("Invalid hexadecimal digit: " + c);
+ }
+
+ /**
+ * <p>Returns a string of 8 hexadecimal digits (most significant digit first)
+ * corresponding to the unsigned integer <code>n</code>.</p>
+ *
+ * @param n the unsigned integer to convert.
+ * @return a hexadecimal string 8-character long.
+ */
+ public static String toString(int n)
+ {
+ char[] buf = new char[8];
+ for (int i = 7; i >= 0; i--)
+ {
+ buf[i] = HEX_DIGITS[n & 0x0F];
+ n >>>= 4;
+ }
+ return new String(buf);
+ }
+
+ /**
+ * <p>Returns a string of hexadecimal digits from an integer array. Each int
+ * is converted to 4 hex symbols.</p>
+ */
+ public static String toString(int[] ia)
+ {
+ int length = ia.length;
+ char[] buf = new char[length * 8];
+ for (int i = 0, j = 0, k; i < length; i++)
+ {
+ k = ia[i];
+ buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 8) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
+ buf[j++] = HEX_DIGITS[k & 0x0F];
+ }
+ return new String(buf);
+ }
+
+ /**
+ * <p>Returns a string of 16 hexadecimal digits (most significant digit first)
+ * corresponding to the unsigned long <code>n</code>.</p>
+ *
+ * @param n the unsigned long to convert.
+ * @return a hexadecimal string 16-character long.
+ */
+ public static String toString(long n)
+ {
+ char[] b = new char[16];
+ for (int i = 15; i >= 0; i--)
+ {
+ b[i] = HEX_DIGITS[(int) (n & 0x0FL)];
+ n >>>= 4;
+ }
+ return new String(b);
+ }
+
+ /**
+ * <p>Similar to the <code>toString()</code> method except that the Unicode
+ * escape character is inserted before every pair of bytes. Useful to
+ * externalise byte arrays that will be constructed later from such strings;
+ * eg. s-box values.</p>
+ *
+ * @throws ArrayIndexOutOfBoundsException if the length is odd.
+ */
+ public static String toUnicodeString(byte[] ba)
+ {
+ return toUnicodeString(ba, 0, ba.length);
+ }
+
+ /**
+ * <p>Similar to the <code>toString()</code> method except that the Unicode
+ * escape character is inserted before every pair of bytes. Useful to
+ * externalise byte arrays that will be constructed later from such strings;
+ * eg. s-box values.</p>
+ *
+ * @throws ArrayIndexOutOfBoundsException if the length is odd.
+ */
+ public static final String toUnicodeString(byte[] ba, int offset, int length)
+ {
+ StringBuffer sb = new StringBuffer();
+ int i = 0;
+ int j = 0;
+ int k;
+ sb.append('\n').append("\"");
+ while (i < length)
+ {
+ sb.append("\\u");
+
+ k = ba[offset + i++];
+ sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]);
+ sb.append(HEX_DIGITS[k & 0x0F]);
+
+ k = ba[offset + i++];
+ sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]);
+ sb.append(HEX_DIGITS[k & 0x0F]);
+
+ if ((++j % 8) == 0)
+ {
+ sb.append("\"+").append('\n').append("\"");
+ }
+ }
+ sb.append("\"").append('\n');
+ return sb.toString();
+ }
+
+ /**
+ * <p>Similar to the <code>toString()</code> method except that the Unicode
+ * escape character is inserted before every pair of bytes. Useful to
+ * externalise integer arrays that will be constructed later from such
+ * strings; eg. s-box values.</p>
+ *
+ * @throws ArrayIndexOutOfBoundsException if the length is not a multiple of 4.
+ */
+ public static String toUnicodeString(int[] ia)
+ {
+ StringBuffer sb = new StringBuffer();
+ int i = 0;
+ int j = 0;
+ int k;
+ sb.append('\n').append("\"");
+ while (i < ia.length)
+ {
+ k = ia[i++];
+ sb.append("\\u");
+ sb.append(HEX_DIGITS[(k >>> 28) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 24) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 20) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 16) & 0x0F]);
+ sb.append("\\u");
+ sb.append(HEX_DIGITS[(k >>> 12) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 8) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]);
+ sb.append(HEX_DIGITS[k & 0x0F]);
+
+ if ((++j % 4) == 0)
+ {
+ sb.append("\"+").append('\n').append("\"");
+ }
+ }
+ sb.append("\"").append('\n');
+ return sb.toString();
+ }
+
+ public static byte[] toBytesFromUnicode(String s)
+ {
+ int limit = s.length() * 2;
+ byte[] result = new byte[limit];
+ char c;
+ for (int i = 0; i < limit; i++)
+ {
+ c = s.charAt(i >>> 1);
+ result[i] = (byte) (((i & 1) == 0) ? c >>> 8 : c);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Dumps a byte array as a string, in a format that is easy to read for
+ * debugging. The string <code>m</code> is prepended to the start of each
+ * line.</p>
+ *
+ * <p>If <code>offset</code> and <code>length</code> are omitted, the whole
+ * array is used. If <code>m</code> is omitted, nothing is prepended to each
+ * line.</p>
+ *
+ * @param data the byte array to be dumped.
+ * @param offset the offset within <i>data</i> to start from.
+ * @param length the number of bytes to dump.
+ * @param m a string to be prepended to each line.
+ * @return a string containing the result.
+ */
+ public static String dumpString(byte[] data, int offset, int length, String m)
+ {
+ if (data == null)
+ {
+ return m + "null\n";
+ }
+ StringBuffer sb = new StringBuffer(length * 3);
+ if (length > 32)
+ {
+ sb.append(m).append("Hexadecimal dump of ").append(length).append(
+ " bytes...\n");
+ }
+ // each line will list 32 bytes in 4 groups of 8 each
+ int end = offset + length;
+ String s;
+ int l = Integer.toString(length).length();
+ if (l < 4)
+ {
+ l = 4;
+ }
+ for (; offset < end; offset += 32)
+ {
+ if (length > 32)
+ {
+ s = " " + offset;
+ sb.append(m).append(s.substring(s.length() - l)).append(": ");
+ }
+ int i = 0;
+ for (; i < 32 && offset + i + 7 < end; i += 8)
+ {
+ sb.append(toString(data, offset + i, 8)).append(' ');
+ }
+ if (i < 32)
+ {
+ for (; i < 32 && offset + i < end; i++)
+ {
+ sb.append(byteToString(data[offset + i]));
+ }
+ }
+ sb.append('\n');
+ }
+ return sb.toString();
+ }
+
+ public static String dumpString(byte[] data)
+ {
+ return (data == null) ? "null\n" : dumpString(data, 0, data.length, "");
+ }
+
+ public static String dumpString(byte[] data, String m)
+ {
+ return (data == null) ? "null\n" : dumpString(data, 0, data.length, m);
+ }
+
+ public static String dumpString(byte[] data, int offset, int length)
+ {
+ return dumpString(data, offset, length, "");
+ }
+
+ /**
+ * <p>Returns a string of 2 hexadecimal digits (most significant digit first)
+ * corresponding to the lowest 8 bits of <code>n</code>.</p>
+ *
+ * @param n the byte value to convert.
+ * @return a string of 2 hex characters representing the input.
+ */
+ public static String byteToString(int n)
+ {
+ char[] buf = { HEX_DIGITS[(n >>> 4) & 0x0F], HEX_DIGITS[n & 0x0F] };
+ return new String(buf);
+ }
+
+ /**
+ * <p>Converts a designated byte array to a Base-64 representation, with the
+ * exceptions that (a) leading 0-byte(s) are ignored, and (b) the character
+ * '.' (dot) shall be used instead of "+' (plus).</p>
+ *
+ * <p>Used by SASL password file manipulation primitives.</p>
+ *
+ * @param buffer an arbitrary sequence of bytes to represent in Base-64.
+ * @return unpadded (without the '=' character(s)) Base-64 representation of
+ * the input.
+ */
+ public static final String toBase64(byte[] buffer)
+ {
+ int len = buffer.length, pos = len % 3;
+ byte b0 = 0, b1 = 0, b2 = 0;
+ switch (pos)
+ {
+ case 1:
+ b2 = buffer[0];
+ break;
+ case 2:
+ b1 = buffer[0];
+ b2 = buffer[1];
+ break;
+ }
+ StringBuffer sb = new StringBuffer();
+ int c;
+ boolean notleading = false;
+ do
+ {
+ c = (b0 & 0xFC) >>> 2;
+ if (notleading || c != 0)
+ {
+ sb.append(BASE64_CHARSET[c]);
+ notleading = true;
+ }
+ c = ((b0 & 0x03) << 4) | ((b1 & 0xF0) >>> 4);
+ if (notleading || c != 0)
+ {
+ sb.append(BASE64_CHARSET[c]);
+ notleading = true;
+ }
+ c = ((b1 & 0x0F) << 2) | ((b2 & 0xC0) >>> 6);
+ if (notleading || c != 0)
+ {
+ sb.append(BASE64_CHARSET[c]);
+ notleading = true;
+ }
+ c = b2 & 0x3F;
+ if (notleading || c != 0)
+ {
+ sb.append(BASE64_CHARSET[c]);
+ notleading = true;
+ }
+ if (pos >= len)
+ {
+ break;
+ }
+ else
+ {
+ try
+ {
+ b0 = buffer[pos++];
+ b1 = buffer[pos++];
+ b2 = buffer[pos++];
+ }
+ catch (ArrayIndexOutOfBoundsException x)
+ {
+ break;
+ }
+ }
+ }
+ while (true);
+
+ if (notleading)
+ {
+ return sb.toString();
+ }
+ return "0";
+ }
+
+ /**
+ * <p>The inverse function of the above.</p>
+ *
+ * <p>Converts a string representing the encoding of some bytes in Base-64
+ * to their original form.</p>
+ *
+ * @param str the Base-64 encoded representation of some byte(s).
+ * @return the bytes represented by the <code>str</code>.
+ * @throws NumberFormatException if <code>str</code> is <code>null</code>, or
+ * <code>str</code> contains an illegal Base-64 character.
+ * @see #toBase64(byte[])
+ */
+ public static final byte[] fromBase64(String str)
+ {
+ int len = str.length();
+ if (len == 0)
+ {
+ throw new NumberFormatException("Empty string");
+ }
+ byte[] a = new byte[len + 1];
+ int i, j;
+ for (i = 0; i < len; i++)
+ {
+ try
+ {
+ a[i] = (byte) BASE64_CHARS.indexOf(str.charAt(i));
+ }
+ catch (ArrayIndexOutOfBoundsException x)
+ {
+ throw new NumberFormatException("Illegal character at #" + i);
+ }
+ }
+ i = len - 1;
+ j = len;
+ try
+ {
+ while (true)
+ {
+ a[j] = a[i];
+ if (--i < 0)
+ {
+ break;
+ }
+ a[j] |= (a[i] & 0x03) << 6;
+ j--;
+ a[j] = (byte) ((a[i] & 0x3C) >>> 2);
+ if (--i < 0)
+ {
+ break;
+ }
+ a[j] |= (a[i] & 0x0F) << 4;
+ j--;
+ a[j] = (byte) ((a[i] & 0x30) >>> 4);
+ if (--i < 0)
+ {
+ break;
+ }
+ a[j] |= (a[i] << 2);
+ j--;
+ a[j] = 0;
+ if (--i < 0)
+ {
+ break;
+ }
+ }
+ }
+ catch (Exception ignored)
+ {
+ }
+
+ try
+ { // ignore leading 0-bytes
+ while (a[j] == 0)
+ {
+ j++;
+ }
+ }
+ catch (Exception x)
+ {
+ return new byte[1]; // one 0-byte
+ }
+ byte[] result = new byte[len - j + 1];
+ System.arraycopy(a, j, result, 0, len - j + 1);
+ return result;
+ }
+
+ // BigInteger utilities ----------------------------------------------------
+
+ /**
+ * <p>Treats the input as the MSB representation of a number, and discards
+ * leading zero elements. For efficiency, the input is simply returned if no
+ * leading zeroes are found.</p>
+ *
+ * @param n the {@link BigInteger} to trim.
+ * @return the byte array representation of the designated {@link BigInteger}
+ * with no leading 0-bytes.
+ */
+ public static final byte[] trim(BigInteger n)
+ {
+ byte[] in = n.toByteArray();
+ if (in.length == 0 || in[0] != 0)
+ {
+ return in;
+ }
+ int len = in.length;
+ int i = 1;
+ while (in[i] == 0 && i < len)
+ {
+ ++i;
+ }
+ byte[] result = new byte[len - i];
+ System.arraycopy(in, i, result, 0, len - i);
+ return result;
+ }
+
+ /**
+ * <p>Returns a hexadecimal dump of the trimmed bytes of a {@link BigInteger}.
+ * </p>
+ *
+ * @param x the {@link BigInteger} to display.
+ * @return the string representation of the designated {@link BigInteger}.
+ */
+ public static final String dump(BigInteger x)
+ {
+ return dumpString(trim(x));
+ }
+}
diff --git a/gnu/javax/crypto/assembly/Assembly.java b/gnu/javax/crypto/assembly/Assembly.java
new file mode 100644
index 000000000..1d70eff87
--- /dev/null
+++ b/gnu/javax/crypto/assembly/Assembly.java
@@ -0,0 +1,298 @@
+/* Assembly.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import java.util.Map;
+
+/**
+ * <p>An <code>Assembly</code> is a construction consisting of a chain of
+ * {@link Transformer} elements; each wired in pre- or post- transformation
+ * mode. This chain is terminated by one <code>LoopbackTransformer</code>
+ * element.</p>
+ *
+ * <p>Once constructed, and correctly initialised, the bulk of the methods
+ * available on the <code>Assembly</code> are delegated to the <i>head</i>
+ * of the {@link Transformer} chain of the <code>Assembly</code>.</p>
+ *
+ * @see Transformer
+ * @version $Revision: 1.1 $
+ */
+public class Assembly
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String DIRECTION = "gnu.crypto.assembly.assembly.direction";
+
+ /** Flag that tells if the instance is initialised or not; and if yes how. */
+ private Direction wired;
+
+ /** The first Transformer in the chain. */
+ private Transformer head;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial constructor that sets the <i>chain</i> to a
+ * <code>LoopbackTransformer</code>.
+ */
+ public Assembly()
+ {
+ super();
+
+ wired = null;
+ head = new LoopbackTransformer();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Adds the designated {@link Transformer} and signals that it should operate
+ * in pre-processing mode; i.e. it should apply its internal transformation
+ * algorithm on the input data stream, <b>before</b> it passes that stream to
+ * the next element in the <i>chain</i>.
+ *
+ * @param t the {@link Transformer} to add at the head of the current chain.
+ * @throws IllegalArgumentException if the designated {@link Transformer}
+ * has a non-null tail; i.e. it is already an element of a chain.
+ */
+ public void addPreTransformer(Transformer t)
+ {
+ wireTransformer(t, Operation.PRE_PROCESSING);
+ }
+
+ /**
+ * Adds the designated {@link Transformer} and signals that it should operate
+ * in post-processing mode; i.e. it should apply its internal transformation
+ * algorithm on the input data stream, <b>after</b> it passes that stream to
+ * the next element in the <i>chain</i>.
+ *
+ * @param t the {@link Transformer} to add at the head of the current chain.
+ * @throws IllegalArgumentException if the designated {@link Transformer}
+ * has a non-null tail; i.e. it is already an element of a chain.
+ */
+ public void addPostTransformer(Transformer t)
+ {
+ wireTransformer(t, Operation.POST_PROCESSING);
+ }
+
+ /**
+ * Initialises the <code>Assembly</code> for operation with specific
+ * characteristics.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalStateException if the instance is already initialised.
+ */
+ public void init(Map attributes) throws TransformerException
+ {
+ if (wired != null)
+ {
+ throw new IllegalStateException();
+ }
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == null)
+ {
+ flow = Direction.FORWARD;
+ }
+ attributes.put(Transformer.DIRECTION, flow);
+ head.init(attributes);
+ wired = flow;
+ }
+
+ /**
+ * Resets the <code>Assembly</code> for re-initialisation and use with other
+ * characteristics. This method always succeeds.
+ */
+ public void reset()
+ {
+ head.reset();
+ wired = null;
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments, using a byte array of length <code>1</code> whose contents are
+ * the designated byte.
+ *
+ * @param b the byte to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #update(byte[], int, int)
+ */
+ public byte[] update(byte b) throws TransformerException
+ {
+ return update(new byte[] { b }, 0, 1);
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments. All bytes in <code>in</code>, starting from index position
+ * <code>0</code> are considered.
+ *
+ * @param in the input data bytes.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #update(byte[], int, int)
+ */
+ public byte[] update(byte[] in) throws TransformerException
+ {
+ return update(in, 0, in.length);
+ }
+
+ /**
+ * Processes a designated number of bytes from a given byte array.
+ *
+ * @param in the input data bytes.
+ * @param offset index of <code>in</code> from which to start considering
+ * data.
+ * @param length the count of bytes to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ */
+ public byte[] update(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ if (wired == null)
+ {
+ throw new IllegalStateException();
+ }
+ return head.update(in, offset, length);
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments using a 0-long byte array.
+ *
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate() throws TransformerException
+ {
+ return lastUpdate(new byte[0], 0, 0);
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments, using a byte array of length <code>1</code> whose contents are
+ * the designated byte.
+ *
+ * @param b the byte to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate(byte b) throws TransformerException
+ {
+ return lastUpdate(new byte[] { b }, 0, 1);
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments. All bytes in <code>in</code>, starting from index position
+ * <code>0</code> are considered.
+ *
+ * @param in the input data bytes.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate(byte[] in) throws TransformerException
+ {
+ return lastUpdate(in, 0, in.length);
+ }
+
+ /**
+ * Processes a designated number of bytes from a given byte array and
+ * signals, at the same time, that this is the last <i>push</i> operation for
+ * this <code>Assembly</code>.
+ *
+ * @param in the input data bytes.
+ * @param offset index of <code>in</code> from which to start considering
+ * data.
+ * @param length the count of bytes to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception
+ * occurs during the operation.
+ */
+ public byte[] lastUpdate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ if (wired == null)
+ {
+ throw new IllegalStateException();
+ }
+ byte[] result = head.lastUpdate(in, offset, length);
+ reset();
+ return result;
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ private void wireTransformer(Transformer t, Operation mode)
+ {
+ if (t.tail != null)
+ {
+ throw new IllegalArgumentException();
+ }
+ t.setMode(mode);
+ t.tail = head;
+ head = t;
+ }
+}
diff --git a/gnu/javax/crypto/assembly/Cascade.java b/gnu/javax/crypto/assembly/Cascade.java
new file mode 100644
index 000000000..20cd3de9d
--- /dev/null
+++ b/gnu/javax/crypto/assembly/Cascade.java
@@ -0,0 +1,405 @@
+/* Cascade.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>A <i>Cascade</i> Cipher is the concatenation of two or more block ciphers
+ * each with independent keys. Plaintext is input to the first stage; the output
+ * of stage <code>i</code> is input to stage <code>i + 1</code>; and the output
+ * of the last stage is the <i>Cascade</i>'s ciphertext output.</p>
+ *
+ * <p>In the simplest case, all stages in a <code>Cascade</code> have <i>k</i>-bit
+ * keys, and the stage inputs and outputs are all n-bit quantities. The stage
+ * ciphers may differ (general cascade of ciphers), or all be identical (cascade
+ * of identical ciphers).</p>
+ *
+ * <p>The term "block ciphers" used above refers to implementations of
+ * {@link gnu.crypto.mode.IMode}, including the {@link gnu.crypto.mode.ECB}
+ * mode which basically exposes a symmetric-key block cipher algorithm as a
+ * <i>Mode</i> of Operations.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
+ * Applied Cryptography.<br>
+ * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
+ * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Cascade
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String DIRECTION = "gnu.crypto.assembly.cascade.direction";
+
+ /** The map of Stages chained in this cascade. */
+ protected HashMap stages;
+
+ /** The ordered list of Stage UIDs to their attribute maps. */
+ protected LinkedList stageKeys;
+
+ /** The current operational direction of this instance. */
+ protected Direction wired;
+
+ /** The curently set block-size for this instance. */
+ protected int blockSize;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Cascade()
+ {
+ super();
+
+ stages = new HashMap(3);
+ stageKeys = new LinkedList();
+ wired = null;
+ blockSize = 0;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns the Least Common Multiple of two integers.
+ *
+ * @param a the first integer.
+ * @param b the second integer.
+ * @return the LCM of <code>abs(a)</code> and <code>abs(b)</code>.
+ */
+ private static final int lcm(int a, int b)
+ {
+ BigInteger A = BigInteger.valueOf(a * 1L);
+ BigInteger B = BigInteger.valueOf(b * 1L);
+ return A.multiply(B).divide(A.gcd(B)).abs().intValue();
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Adds to the end of the current chain, a designated {@link Stage}.
+ *
+ * @param stage the {@link Stage} to append to the chain.
+ * @return a unique identifier for this stage, within this cascade.
+ * @throws IllegalStateException if the instance is already initialised.
+ * @throws IllegalArgumentException if the designated stage is already in
+ * the chain, or it has incompatible characteristics with the current
+ * elements already in the chain.
+ */
+ public Object append(Stage stage) throws IllegalArgumentException
+ {
+ return insert(size(), stage);
+ }
+
+ /**
+ * Adds to the begining of the current chain, a designated {@link Stage}.
+ *
+ * @param stage the {@link Stage} to prepend to the chain.
+ * @return a unique identifier for this stage, within this cascade.
+ * @throws IllegalStateException if the instance is already initialised.
+ * @throws IllegalArgumentException if the designated stage is already in
+ * the chain, or it has incompatible characteristics with the current
+ * elements already in the chain.
+ */
+ public Object prepend(Stage stage) throws IllegalArgumentException
+ {
+ return insert(0, stage);
+ }
+
+ /**
+ * Inserts a {@link Stage} into the current chain, at the specified index
+ * (zero-based) position.
+ *
+ * @param stage the {@link Stage} to insert into the chain.
+ * @return a unique identifier for this stage, within this cascade.
+ * @throws IllegalArgumentException if the designated stage is already in
+ * the chain, or it has incompatible characteristics with the current
+ * elements already in the chain.
+ * @throws IllegalStateException if the instance is already initialised.
+ * @throws IndexOutOfBoundsException if <code>index</code> is less than
+ * <code>0</code> or greater than the current size of this cascade.
+ */
+ public Object insert(int index, Stage stage) throws IllegalArgumentException,
+ IndexOutOfBoundsException
+ {
+ if (stages.containsValue(stage))
+ {
+ throw new IllegalArgumentException();
+ }
+ if (wired != null || stage == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ if (index < 0 || index > size())
+ {
+ throw new IndexOutOfBoundsException();
+ }
+
+ // check that there is a non-empty set of common block-sizes
+ Set set = stage.blockSizes();
+ if (stages.isEmpty())
+ {
+ if (set.isEmpty())
+ {
+ throw new IllegalArgumentException("1st stage with no block sizes");
+ }
+ }
+ else
+ {
+ Set common = this.blockSizes();
+ common.retainAll(set);
+ if (common.isEmpty())
+ {
+ throw new IllegalArgumentException("no common block sizes found");
+ }
+ }
+
+ Object result = new Object();
+ stageKeys.add(index, result);
+ stages.put(result, stage);
+
+ return result;
+ }
+
+ /**
+ * Returns the current number of stages in this chain.
+ *
+ * @return the current count of stages in this chain.
+ */
+ public int size()
+ {
+ return stages.size();
+ }
+
+ /**
+ * Returns an {@link Iterator} over the stages contained in this instance.
+ * Each element of this iterator is a concrete implementation of a {@link
+ * Stage}.
+ *
+ * @return an {@link Iterator} over the stages contained in this instance.
+ * Each element of the returned iterator is a concrete instance of a {@link
+ * Stage}.
+ */
+ public Iterator stages()
+ {
+ LinkedList result = new LinkedList();
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ {
+ result.addLast(stages.get(it.next()));
+ }
+ return result.listIterator();
+ }
+
+ /**
+ * Returns the {@link Set} of supported block sizes for this
+ * <code>Cascade</code> that are common to all of its chained stages. Each
+ * element in the returned {@link Set} is an instance of {@link Integer}.
+ *
+ * @return a {@link Set} of supported block sizes common to all the stages
+ * of the chain.
+ */
+ public Set blockSizes()
+ {
+ HashSet result = null;
+ for (Iterator it = stages.values().iterator(); it.hasNext();)
+ {
+ Stage aStage = (Stage) it.next();
+ if (result == null)
+ { // first time
+ result = new HashSet(aStage.blockSizes());
+ }
+ else
+ {
+ result.retainAll(aStage.blockSizes());
+ }
+ }
+ return result == null ? Collections.EMPTY_SET : result;
+ }
+
+ /**
+ * Initialises the chain for operation with specific characteristics.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalStateException if the chain, or any of its stages, is
+ * already initialised.
+ * @throws InvalidKeyException if the intialisation data provided with the
+ * stage is incorrect or causes an invalid key to be generated.
+ * @see Direction#FORWARD
+ * @see Direction#REVERSED
+ */
+ public void init(Map attributes) throws InvalidKeyException
+ {
+ if (wired != null)
+ {
+ throw new IllegalStateException();
+ }
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == null)
+ {
+ flow = Direction.FORWARD;
+ }
+
+ int optimalSize = 0;
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ {
+ Object id = it.next();
+ Map attr = (Map) attributes.get(id);
+ attr.put(Stage.DIRECTION, flow);
+ Stage stage = (Stage) stages.get(id);
+ stage.init(attr);
+ optimalSize = optimalSize == 0 ? stage.currentBlockSize()
+ : lcm(optimalSize,
+ stage.currentBlockSize());
+ }
+
+ if (flow == Direction.REVERSED)
+ { // reverse order
+ Collections.reverse(stageKeys);
+ }
+ wired = flow;
+ blockSize = optimalSize;
+ }
+
+ /**
+ * Returns the currently set block size for the chain.
+ *
+ * @return the current block size for the chain.
+ * @throws IllegalStateException if the instance is not initialised.
+ */
+ public int currentBlockSize()
+ {
+ if (wired == null)
+ {
+ throw new IllegalStateException();
+ }
+ return blockSize;
+ }
+
+ /**
+ * Resets the chain for re-initialisation and use with other characteristics.
+ * This method always succeeds.
+ */
+ public void reset()
+ {
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ {
+ ((Stage) stages.get(it.next())).reset();
+ }
+ if (wired == Direction.REVERSED)
+ { // reverse it back
+ Collections.reverse(stageKeys);
+ }
+ wired = null;
+ blockSize = 0;
+ }
+
+ /**
+ * Processes exactly one block of <i>plaintext</i> (if initialised in the
+ * {@link Direction#FORWARD} state) or <i>ciphertext</i> (if initialised in the
+ * {@link Direction#REVERSED} state).
+ *
+ * @param in the plaintext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the ciphertext.
+ * @param outOffset index of <code>out</code> from which to store result.
+ * @throws IllegalStateException if the instance is not initialised.
+ */
+ public void update(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ if (wired == null)
+ {
+ throw new IllegalStateException();
+ }
+ int stageBlockSize, j, i = stages.size();
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ {
+ Stage stage = (Stage) stages.get(it.next());
+ stageBlockSize = stage.currentBlockSize();
+ for (j = 0; j < blockSize; j += stageBlockSize)
+ {
+ stage.update(in, inOffset + j, out, outOffset + j);
+ }
+ i--;
+ if (i > 0)
+ {
+ System.arraycopy(out, outOffset, in, inOffset, blockSize);
+ }
+ }
+ }
+
+ /**
+ * Conducts a simple <i>correctness</i> test that consists of basic symmetric
+ * encryption / decryption test(s) for all supported block and key sizes of
+ * underlying block cipher(s) wrapped by Mode leafs. The test also includes
+ * one (1) variable key Known Answer Test (KAT) for each block cipher.
+ *
+ * @return <code>true</code> if the implementation passes simple
+ * <i>correctness</i> tests. Returns <code>false</code> otherwise.
+ */
+ public boolean selfTest()
+ {
+ for (Iterator it = stageKeys.listIterator(); it.hasNext();)
+ {
+ if (!((Stage) stages.get(it.next())).selfTest())
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/gnu/javax/crypto/assembly/CascadeStage.java b/gnu/javax/crypto/assembly/CascadeStage.java
new file mode 100644
index 000000000..71a8b178f
--- /dev/null
+++ b/gnu/javax/crypto/assembly/CascadeStage.java
@@ -0,0 +1,109 @@
+/* CascadeStage.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import java.security.InvalidKeyException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>A Cascade <i>Stage</i> in a Cascade Cipher.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+class CascadeStage extends Stage
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private Cascade delegate;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ CascadeStage(Cascade cascade, Direction forwardDirection)
+ {
+ super(forwardDirection);
+
+ this.delegate = cascade;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public Set blockSizes()
+ {
+ return Collections.unmodifiableSet(delegate.blockSizes());
+ }
+
+ void initDelegate(Map attributes) throws InvalidKeyException
+ {
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ attributes.put(DIRECTION, flow.equals(forward) ? forward
+ : Direction.reverse(forward));
+ // delegate.init(flow.equals(forward) ? forward : backward);
+ // delegate.init(flow.equals(forward) ? forward : Direction.reverse(forward));
+ delegate.init(attributes);
+ }
+
+ public int currentBlockSize() throws IllegalStateException
+ {
+ return delegate.currentBlockSize();
+ }
+
+ void resetDelegate()
+ {
+ delegate.reset();
+ }
+
+ void updateDelegate(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ delegate.update(in, inOffset, out, outOffset);
+ }
+
+ public boolean selfTest()
+ {
+ return delegate.selfTest();
+ }
+}
diff --git a/gnu/javax/crypto/assembly/CascadeTransformer.java b/gnu/javax/crypto/assembly/CascadeTransformer.java
new file mode 100644
index 000000000..325571dcd
--- /dev/null
+++ b/gnu/javax/crypto/assembly/CascadeTransformer.java
@@ -0,0 +1,139 @@
+/* CascadeTransformer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import java.security.InvalidKeyException;
+import java.util.Map;
+
+/**
+ * An Adapter to use any {@link Cascade} as a {@link Transformer} in an
+ * {@link Assembly}.
+ *
+ * @version $Revision: 1.1 $
+ */
+class CascadeTransformer extends Transformer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private Cascade delegate;
+
+ private int blockSize;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ CascadeTransformer(Cascade delegate)
+ {
+ super();
+
+ this.delegate = delegate;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instant methods
+ // -------------------------------------------------------------------------
+
+ void initDelegate(Map attributes) throws TransformerException
+ {
+ attributes.put(Cascade.DIRECTION, wired);
+ try
+ {
+ delegate.init(attributes);
+ }
+ catch (InvalidKeyException x)
+ {
+ throw new TransformerException("initDelegate()", x);
+ }
+ blockSize = delegate.currentBlockSize();
+ }
+
+ int delegateBlockSize()
+ {
+ return blockSize;
+ }
+
+ void resetDelegate()
+ {
+ delegate.reset();
+ blockSize = 0;
+ }
+
+ byte[] updateDelegate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ byte[] result = updateInternal(in, offset, length);
+ return result;
+ }
+
+ byte[] lastUpdateDelegate() throws TransformerException
+ {
+ if (inBuffer.size() != 0)
+ {
+ throw new TransformerException(
+ "lastUpdateDelegate()",
+ new IllegalStateException(
+ "Cascade transformer, after last "
+ + "update, must be empty but isn't"));
+ }
+ return new byte[0];
+ }
+
+ private byte[] updateInternal(byte[] in, int offset, int length)
+ {
+ byte[] result;
+ for (int i = 0; i < length; i++)
+ {
+ inBuffer.write(in[offset++] & 0xFF);
+ if (inBuffer.size() >= blockSize)
+ {
+ result = inBuffer.toByteArray();
+ inBuffer.reset();
+ delegate.update(result, 0, result, 0);
+ outBuffer.write(result, 0, blockSize);
+ }
+ }
+ result = outBuffer.toByteArray();
+ outBuffer.reset();
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/assembly/DeflateTransformer.java b/gnu/javax/crypto/assembly/DeflateTransformer.java
new file mode 100644
index 000000000..35328a6c1
--- /dev/null
+++ b/gnu/javax/crypto/assembly/DeflateTransformer.java
@@ -0,0 +1,233 @@
+/* DeflateTransformer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import java.util.Map;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+/**
+ * <p>A {@link Transformer} Adapter allowing inclusion of a DEFLATE compression
+ * algorithm in an {@link Assembly} chain. The {@link Direction#FORWARD}
+ * transformation is a compression (deflate) of input data, while the
+ * {@link Direction#REVERSED} one is a decompression (inflate) that restores
+ * the original data.</p>
+ *
+ * <p>This {@link Transformer} uses a {@link Deflater} instance to carry on the
+ * compression, and an {@link Inflater} to do the decompression.</p>
+ *
+ * <p>When using such a {@link Transformer}, in an {@link Assembly}, there must
+ * be at least one element behind this instance in the constructed chain;
+ * otherwise, a {@link TransformerException} is thrown at initialisation time.</p>
+ *
+ * @version Revision: $
+ */
+class DeflateTransformer extends Transformer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private Deflater compressor;
+
+ private Inflater decompressor;
+
+ private int outputBlockSize = 512; // default zlib buffer size
+
+ private byte[] zlibBuffer;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ DeflateTransformer()
+ {
+ super();
+
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ void initDelegate(Map attributes) throws TransformerException
+ {
+ if (tail == null)
+ {
+ throw new TransformerException(
+ "initDelegate()",
+ new IllegalStateException(
+ "Compression transformer missing its tail!"));
+ }
+ outputBlockSize = tail.currentBlockSize();
+ zlibBuffer = new byte[outputBlockSize];
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == Direction.FORWARD)
+ {
+ compressor = new Deflater();
+ }
+ else
+ {
+ decompressor = new Inflater();
+ }
+ }
+
+ int delegateBlockSize()
+ {
+ // return outputBlockSize;
+ return 1;
+ }
+
+ void resetDelegate()
+ {
+ compressor = null;
+ decompressor = null;
+ outputBlockSize = 1;
+ zlibBuffer = null;
+ }
+
+ byte[] updateDelegate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ byte[] result;
+ if (wired == Direction.FORWARD)
+ {
+ compressor.setInput(in, offset, length);
+ while (!compressor.needsInput())
+ {
+ compress();
+ }
+ }
+ else
+ { // decompression: inflate first and then update tail
+ decompress(in, offset, length);
+ }
+
+ result = inBuffer.toByteArray();
+ inBuffer.reset();
+ return result;
+ }
+
+ // byte[] lastUpdateDelegate(byte[] in, int offset, int length)
+ // throws TransformerException {
+ // // process multiples of blocksize as much as possible
+ // byte[] result = this.updateDelegate(in, offset, length);
+ // inBuffer.write(result, 0, result.length);
+ // if (wired == Direction.FORWARD) { // compressing
+ // if (!compressor.finished()) {
+ // compressor.finish();
+ // while (!compressor.finished()) {
+ // compress();
+ // }
+ // }
+ // } else { // decompressing
+ // if (!decompressor.finished()) {
+ // throw new TransformerException("lastUpdateDelegate()",
+ // new IllegalStateException("Compression transformer, after last "
+ // +"update, must be finished but isn't"));
+ // }
+ // }
+ //
+ // result = inBuffer.toByteArray();
+ // inBuffer.reset();
+ // return result;
+ // }
+ byte[] lastUpdateDelegate() throws TransformerException
+ {
+ // process multiples of blocksize as much as possible
+ if (wired == Direction.FORWARD)
+ { // compressing
+ if (!compressor.finished())
+ {
+ compressor.finish();
+ while (!compressor.finished())
+ {
+ compress();
+ }
+ }
+ }
+ else
+ { // decompressing
+ if (!decompressor.finished())
+ {
+ throw new TransformerException(
+ "lastUpdateDelegate()",
+ new IllegalStateException(
+ "Compression transformer, after last "
+ + "update, must be finished but isn't"));
+ }
+ }
+ byte[] result = inBuffer.toByteArray();
+ inBuffer.reset();
+ return result;
+ }
+
+ private void compress()
+ {
+ int len = compressor.deflate(zlibBuffer);
+ if (len > 0)
+ {
+ inBuffer.write(zlibBuffer, 0, len);
+ }
+ }
+
+ private void decompress(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ decompressor.setInput(in, offset, length);
+ int len = 1;
+ while (len > 0)
+ {
+ try
+ {
+ len = decompressor.inflate(zlibBuffer);
+ }
+ catch (DataFormatException x)
+ {
+ throw new TransformerException("decompress()", x);
+ }
+ if (len > 0)
+ {
+ inBuffer.write(zlibBuffer, 0, len);
+ }
+ }
+ }
+}
diff --git a/gnu/javax/crypto/assembly/Direction.java b/gnu/javax/crypto/assembly/Direction.java
new file mode 100644
index 000000000..2e8ef1145
--- /dev/null
+++ b/gnu/javax/crypto/assembly/Direction.java
@@ -0,0 +1,92 @@
+/* Direction.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+/**
+ * <p>An enumeration type for wiring {@link Stage} instances into {@link
+ * Cascade} Cipher chains, as well as for operating a {@link Cascade} in a
+ * given direction.</p>
+ *
+ * <p>The possible values for this type are two:</p>
+ * <ol>
+ * <li>FORWARD: equivalent to {@link gnu.crypto.mode.IMode#ENCRYPTION}, and
+ * its inverse value</li>
+ * <li>REVERSED: equivalent to {@link gnu.crypto.mode.IMode#DECRYPTION}.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class Direction
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final Direction FORWARD = new Direction(1);
+
+ public static final Direction REVERSED = new Direction(2);
+
+ private int value;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ private Direction(int value)
+ {
+ super();
+
+ this.value = value;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final Direction reverse(Direction d)
+ {
+ return (d.equals(FORWARD) ? REVERSED : FORWARD);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public String toString()
+ {
+ return (this == FORWARD ? "forward" : "reversed");
+ }
+}
diff --git a/gnu/javax/crypto/assembly/LoopbackTransformer.java b/gnu/javax/crypto/assembly/LoopbackTransformer.java
new file mode 100644
index 000000000..62791264f
--- /dev/null
+++ b/gnu/javax/crypto/assembly/LoopbackTransformer.java
@@ -0,0 +1,116 @@
+/* LoopbackTransformer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import java.util.Map;
+
+/**
+ * A trivial {@link Transformer} to allow closing a chain in an {@link Assembly}.
+ * This class is not visible outside this package.
+ *
+ * @version $Revision: 1.1 $
+ */
+final class LoopbackTransformer extends Transformer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial protected constructor. */
+ LoopbackTransformer()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public void init(Map attributes) throws TransformerException
+ {
+ }
+
+ public void reset()
+ {
+ }
+
+ public byte[] update(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ return updateDelegate(in, offset, length);
+ }
+
+ public byte[] lastUpdate() throws TransformerException
+ {
+ return lastUpdateDelegate();
+ }
+
+ // abstract methods to be implemented by concrete subclasses ---------------
+
+ void initDelegate(Map attributes) throws TransformerException
+ {
+ }
+
+ int delegateBlockSize()
+ {
+ return 1;
+ }
+
+ void resetDelegate()
+ {
+ }
+
+ byte[] updateDelegate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ byte[] result = new byte[length];
+ System.arraycopy(in, offset, result, 0, length);
+ return result;
+ }
+
+ byte[] lastUpdateDelegate() throws TransformerException
+ {
+ return new byte[0];
+ }
+}
diff --git a/gnu/javax/crypto/assembly/ModeStage.java b/gnu/javax/crypto/assembly/ModeStage.java
new file mode 100644
index 000000000..1cd8fd915
--- /dev/null
+++ b/gnu/javax/crypto/assembly/ModeStage.java
@@ -0,0 +1,129 @@
+/* ModeStage.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import gnu.javax.crypto.mode.IMode;
+
+import java.security.InvalidKeyException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>An {@link IMode} {@link Stage} in a {@link Cascade} Cipher chain.</p>
+ *
+ * <p>Such a stage wraps an implementation of a Block Cipher Mode of Operation
+ * ({@link IMode}) to allow inclusion of such an instance in a cascade of block
+ * ciphers.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+class ModeStage extends Stage
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private IMode delegate;
+
+ private transient Set cachedBlockSizes;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ ModeStage(IMode mode, Direction forwardDirection)
+ {
+ super(forwardDirection);
+
+ delegate = mode;
+ cachedBlockSizes = null;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public Set blockSizes()
+ {
+ if (cachedBlockSizes == null)
+ {
+ HashSet result = new HashSet();
+ for (Iterator it = delegate.blockSizes(); it.hasNext();)
+ {
+ result.add(it.next());
+ }
+ cachedBlockSizes = Collections.unmodifiableSet(result);
+ }
+ return cachedBlockSizes;
+ }
+
+ void initDelegate(Map attributes) throws InvalidKeyException
+ {
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ attributes.put(IMode.STATE,
+ new Integer(flow.equals(forward) ? IMode.ENCRYPTION
+ : IMode.DECRYPTION));
+
+ delegate.init(attributes);
+ }
+
+ public int currentBlockSize() throws IllegalStateException
+ {
+ return delegate.currentBlockSize();
+ }
+
+ void resetDelegate()
+ {
+ delegate.reset();
+ }
+
+ void updateDelegate(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ delegate.update(in, inOffset, out, outOffset);
+ }
+
+ public boolean selfTest()
+ {
+ return delegate.selfTest();
+ }
+}
diff --git a/gnu/javax/crypto/assembly/Operation.java b/gnu/javax/crypto/assembly/Operation.java
new file mode 100644
index 000000000..2646e1f33
--- /dev/null
+++ b/gnu/javax/crypto/assembly/Operation.java
@@ -0,0 +1,89 @@
+/* Operation.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+/**
+ * <p>An enumeration type for specifying the operation type of a
+ * {@link Transformer}.</p>
+ *
+ * <p>The possible values for this type are two:</p>
+ * <ol>
+ * <li>PRE_PROCESSING: where the input data is first processed by the
+ * current {@link Transformer} before being passed to the rest of the chain;
+ * and</li>
+ * <li>POST_PROCESSING: where the input data is first passed to the rest of
+ * the chain, and the resulting bytes are then processed by the current
+ * {@link Transformer}.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class Operation
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final Operation PRE_PROCESSING = new Operation(1);
+
+ public static final Operation POST_PROCESSING = new Operation(2);
+
+ private int value;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ private Operation(int value)
+ {
+ super();
+
+ this.value = value;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public String toString()
+ {
+ return (this == PRE_PROCESSING ? "pre-processing" : "post-processing");
+ }
+}
diff --git a/gnu/javax/crypto/assembly/PaddingTransformer.java b/gnu/javax/crypto/assembly/PaddingTransformer.java
new file mode 100644
index 000000000..8af46a72a
--- /dev/null
+++ b/gnu/javax/crypto/assembly/PaddingTransformer.java
@@ -0,0 +1,178 @@
+/* PaddingTransformer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import gnu.javax.crypto.pad.IPad;
+import gnu.javax.crypto.pad.WrongPaddingException;
+
+import java.util.Map;
+
+/**
+ * <p>An Adapter to use any {@link IPad} as a {@link Transformer} in an
+ * {@link Assembly}.</p>
+ *
+ * <p>When using such a {@link Transformer}, in an {@link Assembly}, there must
+ * be at least one element behind this instance in the constructed chain;
+ * otherwise, a {@link TransformerException} is thrown at initialisation time.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+class PaddingTransformer extends Transformer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private IPad delegate;
+
+ private int outputBlockSize = 1;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ PaddingTransformer(IPad padding)
+ {
+ super();
+
+ this.delegate = padding;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ void initDelegate(Map attributes) throws TransformerException
+ {
+ if (tail == null)
+ {
+ throw new TransformerException(
+ "initDelegate()",
+ new IllegalStateException(
+ "Padding transformer missing its tail!"));
+ }
+ outputBlockSize = tail.currentBlockSize();
+ delegate.init(outputBlockSize);
+ }
+
+ int delegateBlockSize()
+ {
+ return outputBlockSize;
+ }
+
+ void resetDelegate()
+ {
+ delegate.reset();
+ outputBlockSize = 1;
+ }
+
+ byte[] updateDelegate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ inBuffer.write(in, offset, length);
+ byte[] tmp = inBuffer.toByteArray();
+ inBuffer.reset();
+ byte[] result;
+ if (wired == Direction.FORWARD)
+ { // padding
+ // buffers remaining bytes from (inBuffer + in) that are less than 1 block
+ if (tmp.length < outputBlockSize)
+ {
+ inBuffer.write(tmp, 0, tmp.length);
+ result = new byte[0];
+ }
+ else
+ {
+ int newlen = outputBlockSize * (tmp.length / outputBlockSize);
+ inBuffer.write(tmp, newlen, tmp.length - newlen);
+ result = new byte[newlen];
+ System.arraycopy(tmp, 0, result, 0, newlen);
+ }
+ }
+ else
+ { // unpadding
+ // always keep in own buffer a max of 1 block to cater for lastUpdate
+ if (tmp.length < outputBlockSize)
+ {
+ inBuffer.write(tmp, 0, tmp.length);
+ result = new byte[0];
+ }
+ else
+ {
+ result = new byte[tmp.length - outputBlockSize];
+ System.arraycopy(tmp, 0, result, 0, result.length);
+ inBuffer.write(tmp, result.length, outputBlockSize);
+ }
+ }
+ return result;
+ }
+
+ byte[] lastUpdateDelegate() throws TransformerException
+ {
+ byte[] result;
+ // process multiples of blocksize as much as possible
+ // catenate result from processing inBuffer with last-update( tail )
+ if (wired == Direction.FORWARD)
+ { // padding
+ result = inBuffer.toByteArray();
+ byte[] padding = delegate.pad(result, 0, result.length);
+ inBuffer.write(padding, 0, padding.length);
+ }
+ else
+ { // unpadding
+ byte[] tmp = inBuffer.toByteArray();
+ inBuffer.reset();
+ int realLength;
+ try
+ {
+ realLength = tmp.length; // should be outputBlockSize
+ realLength -= delegate.unpad(tmp, 0, tmp.length);
+ }
+ catch (WrongPaddingException x)
+ {
+ throw new TransformerException("lastUpdateDelegate()", x);
+ }
+ inBuffer.write(tmp, 0, realLength);
+ }
+ result = inBuffer.toByteArray();
+ inBuffer.reset();
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/assembly/Stage.java b/gnu/javax/crypto/assembly/Stage.java
new file mode 100644
index 000000000..e44985534
--- /dev/null
+++ b/gnu/javax/crypto/assembly/Stage.java
@@ -0,0 +1,218 @@
+/* Stage.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import gnu.javax.crypto.mode.IMode;
+
+import java.security.InvalidKeyException;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>A <i>Stage</i> in a Cascade Cipher.</p>
+ *
+ * <p>Each stage may be either an implementation of a Block Cipher Mode of
+ * Operation ({@link IMode}) or another Cascade Cipher ({@link Cascade}). Each
+ * stage has also a <i>natural</i> operational direction when constructed for
+ * inclusion within a {@link Cascade}. This <i>natural</i> direction dictates
+ * how data flows from one stage into another when stages are chained together
+ * in a cascade. One can think of a stage and its natural direction as the
+ * specification of how to wire the stage into the chain. The following diagrams
+ * may help understand the paradigme. The first shows two stages chained each
+ * with a {@link Direction#FORWARD} direction.</p>
+ * <pre>
+ * FORWARD FORWARD
+ * +------+ +-------+
+ * | | | |
+ * | +--in --+ | +--in --+
+ * ---+ | Stage | | | Stage | +---
+ * +--out--+ | +--out--+ |
+ * | | | |
+ * +-------+ +------+
+ * </pre>
+ * <p>The second diagram shows two stages, one in a {@link Direction#FORWARD}
+ * direction, while the other is wired in a {@link Direction#REVERSED}
+ * direction.</p>
+ * <pre>
+ * FORWARD REVERSED
+ * +------+ +------+
+ * | | | |
+ * | +--in --+ +--in --+ |
+ * ---+ | Stage | | Stage | +---
+ * +--out--+ +--out--+
+ * | |
+ * +---------------+
+ * </pre>
+ *
+ * @see ModeStage
+ * @see CascadeStage
+ * @version $Revision: 1.1 $
+ */
+public abstract class Stage
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String DIRECTION = "gnu.crypto.assembly.stage.direction";
+
+ protected Direction forward;
+
+ protected Direction wired;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected Stage(Direction forwardDirection)
+ {
+ super();
+
+ this.forward = forwardDirection;
+ this.wired = null;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final Stage getInstance(IMode mode, Direction forwardDirection)
+ {
+ return new ModeStage(mode, forwardDirection);
+ }
+
+ public static final Stage getInstance(Cascade cascade,
+ Direction forwardDirection)
+ {
+ return new CascadeStage(cascade, forwardDirection);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns the {@link Set} of supported block sizes for this
+ * <code>Stage</code>. Each element in the returned {@link Set} is an
+ * instance of {@link Integer}.
+ *
+ * @return a {@link Set} of supported block sizes.
+ */
+ public abstract Set blockSizes();
+
+ /**
+ * Initialises the stage for operation with specific characteristics.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalStateException if the instance is already initialised.
+ * @throws InvalidKeyException if the key data is invalid.
+ */
+ public void init(Map attributes) throws InvalidKeyException
+ {
+ if (wired != null)
+ {
+ throw new IllegalStateException();
+ }
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == null)
+ {
+ flow = Direction.FORWARD;
+ attributes.put(DIRECTION, flow);
+ }
+ initDelegate(attributes);
+ wired = flow;
+ }
+
+ /**
+ * Returns the currently set block size for the stage.
+ *
+ * @return the current block size for this stage.
+ * @throws IllegalStateException if the instance is not initialised.
+ */
+ public abstract int currentBlockSize() throws IllegalStateException;
+
+ /**
+ * Resets the stage for re-initialisation and use with other characteristics.
+ * This method always succeeds.
+ */
+ public void reset()
+ {
+ resetDelegate();
+ wired = null;
+ }
+
+ /**
+ * Processes exactly one block of <i>plaintext</i> (if initialised in the
+ * {@link Direction#FORWARD} state) or <i>ciphertext</i> (if initialised in
+ * the {@link Direction#REVERSED} state).
+ *
+ * @param in the plaintext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the ciphertext.
+ * @param outOffset index of <code>out</code> from which to store result.
+ * @throws IllegalStateException if the instance is not initialised.
+ */
+ public void update(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ if (wired == null)
+ {
+ throw new IllegalStateException();
+ }
+ updateDelegate(in, inOffset, out, outOffset);
+ }
+
+ /**
+ * Conducts a simple <i>correctness</i> test that consists of basic symmetric
+ * encryption / decryption test(s) for all supported block and key sizes of
+ * underlying block cipher(s) wrapped by Mode leafs. The test also includes
+ * one (1) variable key Known Answer Test (KAT) for each block cipher.
+ *
+ * @return <code>true</code> if the implementation passes simple
+ * <i>correctness</i> tests. Returns <code>false</code> otherwise.
+ */
+ public abstract boolean selfTest();
+
+ // abstract methods to be implemented by concrete subclasses ---------------
+
+ abstract void initDelegate(Map attributes) throws InvalidKeyException;
+
+ abstract void resetDelegate();
+
+ abstract void updateDelegate(byte[] in, int inOffset, byte[] out,
+ int outOffset);
+}
diff --git a/gnu/javax/crypto/assembly/Transformer.java b/gnu/javax/crypto/assembly/Transformer.java
new file mode 100644
index 000000000..c62c4677f
--- /dev/null
+++ b/gnu/javax/crypto/assembly/Transformer.java
@@ -0,0 +1,460 @@
+/* Transformer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import gnu.javax.crypto.pad.IPad;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Map;
+
+/**
+ * <p>A <code>Transformer</code> is an abstract representation of a two-way
+ * <i>transformation</i> that can be chained together with other instances of
+ * this type. Examples of such transformations in this library are:
+ * {@link Cascade} cipher, {@link gnu.crypto.pad.IPad} algorithm, and a
+ * ZLib-based deflater/inflater algorithm. A special implementation of a
+ * <code>Transformer</code> to close a chain is also provided.</p>
+ *
+ * <p>A <code>Transformer</code> is characterised by the followings:<p>
+ * <ul>
+ * <li>It can be chained to other instances, to form an {@link Assembly}.</li>
+ * <li>When configured in an {@link Assembly}, it can be set to apply its
+ * internal transformation on the input data stream before (pre-processing)
+ * or after (post-processing) passing the input data to the next element in
+ * the chain. Note that the same type <code>Transformer</code> can be used as
+ * either in pre-processing or a post-processing modes.</li>
+ * <li>A special transformer --<code>LoopbackTransformer</code>-- is used to
+ * close the chain.</li>
+ * <li>A useful type of <code>Transformer</code> --one we're interested in--
+ * has internal buffers. The distinction between a casual push (update)
+ * operation and the last one allows to correctly flush any intermediate
+ * bytes that may exist in those buffers.</li>
+ * </ul>
+ *
+ * <p>To allow wiring <code>Transformer</code> instances together, a
+ * <i>minimal-output-size</i> in bytes is necessary. The trivial case of a
+ * value of <code>1</code> for such attribute practically means that no output
+ * buffering, from the previous element, is needed --which is independant of
+ * buffering the input if the <code>Transformer</code> implementation itself is
+ * block-based.</p>
+ *
+ * @see CascadeTransformer
+ * @see PaddingTransformer
+ * @see DeflateTransformer
+ * @version $Revision: 1.1 $
+ */
+public abstract class Transformer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String DIRECTION = "gnu.crypto.assembly.transformer.direction";
+
+ // public static final String MODE = "gnu.crypto.assembly.transformer.mode";
+
+ protected Direction wired;
+
+ protected Operation mode;
+
+ protected Transformer tail = null;
+
+ protected ByteArrayOutputStream inBuffer = new ByteArrayOutputStream(2048);
+
+ protected ByteArrayOutputStream outBuffer = new ByteArrayOutputStream(2048);
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial protected constructor. */
+ protected Transformer()
+ {
+ super();
+
+ this.wired = null;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final Transformer getCascadeTransformer(Cascade cascade)
+ {
+ return new CascadeTransformer(cascade);
+ }
+
+ public static final Transformer getPaddingTransformer(IPad padding)
+ {
+ return new PaddingTransformer(padding);
+ }
+
+ public static final Transformer getDeflateTransformer()
+ {
+ return new DeflateTransformer();
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Sets the operational mode of this <code>Transformer</code>.
+ *
+ * @param mode the processing mode this <code>Transformer</code> is required
+ * to operate in.
+ * @throws IllegalStateException if this instance has already been assigned
+ * an operational mode.
+ */
+ public void setMode(final Operation mode)
+ {
+ if (this.mode != null)
+ {
+ throw new IllegalStateException();
+ }
+ this.mode = mode;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Transformer</code> was wired in
+ * pre-processing mode; <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this <code>Transformer</code> has been wired
+ * in pre-processing mode; <code>false</code> otherwise.
+ * @throws IllegalStateException if this instance has not yet been assigned
+ * an operational <i>type</i>.
+ */
+ public boolean isPreProcessing()
+ {
+ if (mode == null)
+ {
+ throw new IllegalStateException();
+ }
+ return (mode == Operation.PRE_PROCESSING);
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Transformer</code> was wired in
+ * post-processing mode; <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this <code>Transformer</code> has been wired
+ * in post-processing mode; <code>false</code> otherwise.
+ * @throws IllegalStateException if this instance has not yet been assigned
+ * an operational <i>type</i>.
+ */
+ public boolean isPostProcessing()
+ {
+ return !isPreProcessing();
+ }
+
+ /**
+ * Initialises the <code>Transformer</code> for operation with specific
+ * characteristics.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalStateException if the instance is already initialised.
+ */
+ public void init(Map attributes) throws TransformerException
+ {
+ if (wired != null)
+ {
+ throw new IllegalStateException();
+ }
+ Direction flow = (Direction) attributes.get(DIRECTION);
+ if (flow == null)
+ {
+ flow = Direction.FORWARD;
+ }
+ wired = flow;
+ inBuffer.reset();
+ outBuffer.reset();
+
+ tail.init(attributes); // initialise tail first
+ initDelegate(attributes); // initialise this instance
+ }
+
+ /**
+ * Returns the block-size of this <code>Transformer</code>. A value of
+ * <code>1</code> indicates that this instance is block-agnostic.
+ *
+ * @return the current minimal required block size.
+ */
+ public int currentBlockSize()
+ {
+ if (wired == null)
+ {
+ throw new IllegalStateException();
+ }
+ return delegateBlockSize();
+ }
+
+ /**
+ * Resets the <code>Transformer</code> for re-initialisation and use with
+ * other characteristics. This method always succeeds.
+ */
+ public void reset()
+ {
+ resetDelegate();
+ wired = null;
+ inBuffer.reset();
+ outBuffer.reset();
+ tail.reset(); // reset tail last
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments, using a byte array of length <code>1</code> whose contents are
+ * the designated byte.
+ *
+ * @param b the byte to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #update(byte[], int, int)
+ */
+ public byte[] update(byte b) throws TransformerException
+ {
+ return update(new byte[] { b }, 0, 1);
+ }
+
+ /**
+ * Convenience method that calls the same method with three arguments. All
+ * bytes in <code>in</code>, starting from index position <code>0</code> are
+ * considered.
+ *
+ * @param in the input data bytes.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #update(byte[], int, int)
+ */
+ public byte[] update(byte[] in) throws TransformerException
+ {
+ return update(in, 0, in.length);
+ }
+
+ /**
+ * Processes a designated number of bytes from a given byte array.
+ *
+ * @param in the input data bytes.
+ * @param offset index of <code>in</code> from which to start considering
+ * data.
+ * @param length the count of bytes to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ */
+ public byte[] update(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ if (wired == null)
+ {
+ throw new IllegalStateException();
+ }
+ byte[] result = (wired == Direction.FORWARD ? forwardUpdate(in, offset,
+ length)
+ : inverseUpdate(in, offset,
+ length));
+ return result;
+ }
+
+ /**
+ * Convenience method that calls the same method with three arguments. A
+ * zero-long byte array is used.
+ *
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate() throws TransformerException
+ {
+ byte[] result = (wired == Direction.FORWARD ? lastForwardUpdate()
+ : lastInverseUpdate());
+ if (inBuffer.size() != 0)
+ { // we still have some buffered bytes
+ throw new TransformerException("lastUpdate(): input buffer not empty");
+ }
+ return result;
+ }
+
+ /**
+ * Convenience method that calls the method with same name and three
+ * arguments, using a byte array of length <code>1</code> whose contents are
+ * the designated byte.
+ *
+ * @param b the byte to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate(byte b) throws TransformerException
+ {
+ return lastUpdate(new byte[] { b }, 0, 1);
+ }
+
+ /**
+ * Convenience method that calls the same method with three arguments. All
+ * bytes in <code>in</code>, starting from index position <code>0</code> are
+ * considered.
+ *
+ * @param in the input data bytes.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ * @see #lastUpdate(byte[], int, int)
+ */
+ public byte[] lastUpdate(byte[] in) throws TransformerException
+ {
+ return lastUpdate(in, 0, in.length);
+ }
+
+ /**
+ * Processes a designated number of bytes from a given byte array and
+ * signals, at the same time, that this is the last <i>push</i> operation on
+ * this <code>Transformer</code>.
+ *
+ * @param in the input data bytes.
+ * @param offset index of <code>in</code> from which to start considering
+ * data.
+ * @param length the count of bytes to process.
+ * @return the result of transformation.
+ * @throws IllegalStateException if the instance is not initialised.
+ * @throws TransformerException if a transformation-related exception occurs
+ * during the operation.
+ */
+ public byte[] lastUpdate(byte[] in, int offset, int length)
+ throws TransformerException
+ {
+ byte[] result = update(in, offset, length);
+ byte[] rest = lastUpdate();
+ if (rest.length > 0)
+ {
+ byte[] newResult = new byte[result.length + rest.length];
+ System.arraycopy(result, 0, newResult, 0, result.length);
+ System.arraycopy(rest, 0, newResult, result.length, rest.length);
+ result = newResult;
+ }
+ return result;
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ private byte[] forwardUpdate(byte[] in, int off, int len)
+ throws TransformerException
+ {
+ return (isPreProcessing() ? preTransform(in, off, len) : postTransform(in,
+ off,
+ len));
+ }
+
+ private byte[] inverseUpdate(byte[] in, int off, int len)
+ throws TransformerException
+ {
+ return (isPreProcessing() ? postTransform(in, off, len) : preTransform(in,
+ off,
+ len));
+ }
+
+ private byte[] preTransform(byte[] in, int off, int len)
+ throws TransformerException
+ {
+ byte[] result = updateDelegate(in, off, len);
+ result = tail.update(result);
+ return result;
+ }
+
+ private byte[] postTransform(byte[] in, int off, int len)
+ throws TransformerException
+ {
+ byte[] result = tail.update(in, off, len);
+ result = updateDelegate(result, 0, result.length);
+ return result;
+ }
+
+ private byte[] lastForwardUpdate() throws TransformerException
+ {
+ return (isPreProcessing() ? preLastTransform() : postLastTransform());
+ }
+
+ private byte[] lastInverseUpdate() throws TransformerException
+ {
+ return (isPreProcessing() ? postLastTransform() : preLastTransform());
+ }
+
+ private byte[] preLastTransform() throws TransformerException
+ {
+ byte[] result = lastUpdateDelegate();
+ result = tail.lastUpdate(result);
+ return result;
+ }
+
+ private byte[] postLastTransform() throws TransformerException
+ {
+ byte[] result = tail.lastUpdate();
+ result = updateDelegate(result, 0, result.length);
+ byte[] rest = lastUpdateDelegate();
+ if (rest.length > 0)
+ {
+ byte[] newResult = new byte[result.length + rest.length];
+ System.arraycopy(result, 0, newResult, 0, result.length);
+ System.arraycopy(rest, 0, newResult, result.length, rest.length);
+ result = newResult;
+ }
+ return result;
+ }
+
+ // abstract methods to be implemented by concrete subclasses ---------------
+
+ abstract void initDelegate(Map attributes) throws TransformerException;
+
+ abstract int delegateBlockSize();
+
+ abstract void resetDelegate();
+
+ abstract byte[] updateDelegate(byte[] in, int off, int len)
+ throws TransformerException;
+
+ abstract byte[] lastUpdateDelegate() throws TransformerException;
+}
diff --git a/gnu/javax/crypto/assembly/TransformerException.java b/gnu/javax/crypto/assembly/TransformerException.java
new file mode 100644
index 000000000..412f0f0f1
--- /dev/null
+++ b/gnu/javax/crypto/assembly/TransformerException.java
@@ -0,0 +1,158 @@
+/* TransformerException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.assembly;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ */
+public class TransformerException extends Exception
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private Throwable _exception = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public TransformerException()
+ {
+ super();
+ }
+
+ public TransformerException(String details)
+ {
+ super(details);
+ }
+
+ public TransformerException(Throwable cause)
+ {
+ super();
+
+ this._exception = cause;
+ }
+
+ public TransformerException(String details, Throwable cause)
+ {
+ super(details);
+
+ this._exception = cause;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instant methods
+ // -------------------------------------------------------------------------
+
+ public Throwable getCause()
+ {
+ return _exception;
+ }
+
+ /**
+ * Prints this exception's stack trace to <code>System.err</code>. If this
+ * exception has a root exception; the stack trace of the root exception is
+ * also printed to <code>System.err</code>.
+ */
+ public void printStackTrace()
+ {
+ super.printStackTrace();
+ if (_exception != null)
+ {
+ _exception.printStackTrace();
+ }
+ }
+
+ /**
+ * Prints this exception's stack trace to a print stream. If this exception
+ * has a root exception; the stack trace of the root exception is also
+ * printed to the print stream.
+ *
+ * @param ps the non-null print stream to which to print.
+ */
+ public void printStackTrace(PrintStream ps)
+ {
+ super.printStackTrace(ps);
+ if (_exception != null)
+ {
+ _exception.printStackTrace(ps);
+ }
+ }
+
+ /**
+ * Prints this exception's stack trace to a print writer. If this exception
+ * has a root exception; the stack trace of the root exception is also
+ * printed to the print writer.
+ *
+ * @param pw the non-null print writer to use for output.
+ */
+ public void printStackTrace(PrintWriter pw)
+ {
+ super.printStackTrace(pw);
+ if (_exception != null)
+ {
+ _exception.printStackTrace(pw);
+ }
+ }
+
+ /**
+ * Returns the string representation of this exception. The string
+ * representation contains this exception's class name, its detailed
+ * messsage, and if it has a root exception, the string representation of the
+ * root exception. This string representation is meant for debugging and not
+ * meant to be interpreted programmatically.
+ *
+ * @return the non-null string representation of this exception.
+ * @see Throwable#getMessage()
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer(this.getClass().getName()).append(": ").append(
+ super.toString());
+ if (_exception != null)
+ {
+ sb.append("; caused by: ").append(_exception.toString());
+ }
+ return sb.toString();
+ }
+}
diff --git a/gnu/javax/crypto/cipher/Anubis.java b/gnu/javax/crypto/cipher/Anubis.java
new file mode 100644
index 000000000..63b97ce4e
--- /dev/null
+++ b/gnu/javax/crypto/cipher/Anubis.java
@@ -0,0 +1,583 @@
+/* Anubis.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+//import java.io.PrintWriter;
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>Anubis is a 128-bit block cipher that accepts a variable-length key. The
+ * cipher is a uniform substitution-permutation network whose inverse only
+ * differs from the forward operation in the key schedule. The design of both
+ * the round transformation and the key schedule is based upon the Wide Trail
+ * strategy and permits a wide variety of implementation trade-offs.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://planeta.terra.com.br/informatica/paulobarreto/AnubisPage.html">The
+ * ANUBIS Block Cipher</a>.<br>
+ * <a href="mailto:paulo.barreto@terra.com.br">Paulo S.L.M. Barreto</a> and
+ * <a href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a>.</li>
+ * </ol>
+ */
+public final class Anubis extends BaseCipher
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ // private static final String NAME = "anubis";
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 9;
+
+ // private static final PrintWriter err = new PrintWriter(System.out, true);
+ // private static void debug(String s) {
+ // err.println(">>> "+NAME+": "+s);
+ // }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes
+
+ private static final int DEFAULT_KEY_SIZE = 16; // in bytes
+
+ private static final String Sd = // p. 25 [ANUBIS]
+ "\uBA54\u2F74\u53D3\uD24D\u50AC\u8DBF\u7052\u9A4C"
+ + "\uEAD5\u97D1\u3351\u5BA6\uDE48\uA899\uDB32\uB7FC"
+ + "\uE39E\u919B\uE2BB\u416E\uA5CB\u6B95\uA1F3\uB102"
+ + "\uCCC4\u1D14\uC363\uDA5D\u5FDC\u7DCD\u7F5A\u6C5C"
+ + "\uF726\uFFED\uE89D\u6F8E\u19A0\uF089\u0F07\uAFFB"
+ + "\u0815\u0D04\u0164\uDF76\u79DD\u3D16\u3F37\u6D38"
+ + "\uB973\uE935\u5571\u7B8C\u7288\uF62A\u3E5E\u2746"
+ + "\u0C65\u6861\u03C1\u57D6\uD958\uD866\uD73A\uC83C"
+ + "\uFA96\uA798\uECB8\uC7AE\u694B\uABA9\u670A\u47F2"
+ + "\uB522\uE5EE\uBE2B\u8112\u831B\u0E23\uF545\u21CE"
+ + "\u492C\uF9E6\uB628\u1782\u1A8B\uFE8A\u09C9\u874E"
+ + "\uE12E\uE4E0\uEB90\uA41E\u8560\u0025\uF4F1\u940B"
+ + "\uE775\uEF34\u31D4\uD086\u7EAD\uFD29\u303B\u9FF8"
+ + "\uC613\u0605\uC511\u777C\u7A78\u361C\u3959\u1856"
+ + "\uB3B0\u2420\uB292\uA3C0\u4462\u10B4\u8443\u93C2"
+ + "\u4ABD\u8F2D\uBC9C\u6A40\uCFA2\u804F\u1FCA\uAA42";
+
+ private static final byte[] S = new byte[256];
+
+ private static final int[] T0 = new int[256];
+
+ private static final int[] T1 = new int[256];
+
+ private static final int[] T2 = new int[256];
+
+ private static final int[] T3 = new int[256];
+
+ private static final int[] T4 = new int[256];
+
+ private static final int[] T5 = new int[256];
+
+ /**
+ * Anubis round constants. This is the largest possible considering that we
+ * always use R values, R = 8 + N, and 4 &lt;= N &lt;= 10.
+ */
+ private static final int[] rc = new int[18];
+
+ /**
+ * KAT vector (from ecb_vk):
+ * I=83
+ * KEY=000000000000000000002000000000000000000000000000
+ * CT=2E66AB15773F3D32FB6C697509460DF4
+ */
+ private static final byte[] KAT_KEY = Util.toBytesFromString("000000000000000000002000000000000000000000000000");
+
+ private static final byte[] KAT_CT = Util.toBytesFromString("2E66AB15773F3D32FB6C697509460DF4");
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ // Static code - to initialise lookup tables -------------------------------
+
+ static
+ {
+ long time = System.currentTimeMillis();
+
+ int ROOT = 0x11d; // para. 2.1 [ANUBIS]
+ int i, s, s2, s4, s6, s8, t;
+ char c;
+ for (i = 0; i < 256; i++)
+ {
+ c = Sd.charAt(i >>> 1);
+ s = ((i & 1) == 0 ? c >>> 8 : c) & 0xFF;
+ S[i] = (byte) s;
+
+ s2 = s << 1;
+ if (s2 > 0xFF)
+ {
+ s2 ^= ROOT;
+ }
+
+ s4 = s2 << 1;
+ if (s4 > 0xFF)
+ {
+ s4 ^= ROOT;
+ }
+
+ s6 = s4 ^ s2;
+ s8 = s4 << 1;
+ if (s8 > 0xFF)
+ {
+ s8 ^= ROOT;
+ }
+
+ T0[i] = s << 24 | s2 << 16 | s4 << 8 | s6;
+ T1[i] = s2 << 24 | s << 16 | s6 << 8 | s4;
+ T2[i] = s4 << 24 | s6 << 16 | s << 8 | s2;
+ T3[i] = s6 << 24 | s4 << 16 | s2 << 8 | s;
+
+ T4[i] = s << 24 | s << 16 | s << 8 | s;
+ T5[s] = s << 24 | s2 << 16 | s6 << 8 | s8;
+ }
+
+ // compute round constant
+ for (i = 0, s = 0; i < 18;)
+ {
+ rc[i++] = S[(s++) & 0xFF] << 24 | (S[(s++) & 0xFF] & 0xFF) << 16
+ | (S[(s++) & 0xFF] & 0xFF) << 8 | (S[(s++) & 0xFF] & 0xFF);
+ }
+
+ time = System.currentTimeMillis() - time;
+
+ if (DEBUG && debuglevel > 8)
+ {
+ System.out.println("==========");
+ System.out.println();
+ System.out.println("Static data");
+ System.out.println();
+
+ System.out.println();
+ System.out.println("T0[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (t = 0; t < 4; t++)
+ {
+ System.out.print("0x" + Util.toString(T0[i * 4 + t]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T1[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (t = 0; t < 4; t++)
+ {
+ System.out.print("0x" + Util.toString(T1[i * 4 + t]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T2[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (t = 0; t < 4; t++)
+ {
+ System.out.print("0x" + Util.toString(T2[i * 4 + t]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T3[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (t = 0; t < 4; t++)
+ {
+ System.out.print("0x" + Util.toString(T3[i * 4 + t]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T4[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (t = 0; t < 4; t++)
+ {
+ System.out.print("0x" + Util.toString(T4[i * 4 + t]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T5[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (t = 0; t < 4; t++)
+ {
+ System.out.print("0x" + Util.toString(T5[i * 4 + t]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("rc[]:");
+ for (i = 0; i < 18; i++)
+ {
+ System.out.println("0x" + Util.toString(rc[i]));
+ }
+ System.out.println();
+
+ System.out.println();
+ System.out.println("Total initialization time: " + time + " ms.");
+ System.out.println();
+ }
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Anubis()
+ {
+ super(Registry.ANUBIS_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ private static void anubis(byte[] in, int i, byte[] out, int j, int[][] K)
+ {
+ // extract encryption round keys
+ int R = K.length - 1;
+ int[] Ker = K[0];
+
+ // mu function + affine key addition
+ int a0 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Ker[0];
+ int a1 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Ker[1];
+ int a2 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Ker[2];
+ int a3 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i] & 0xFF))
+ ^ Ker[3];
+
+ int b0, b1, b2, b3;
+ // round function
+ for (int r = 1; r < R; r++)
+ {
+ Ker = K[r];
+ b0 = T0[a0 >>> 24] ^ T1[a1 >>> 24] ^ T2[a2 >>> 24] ^ T3[a3 >>> 24]
+ ^ Ker[0];
+ b1 = T0[(a0 >>> 16) & 0xFF] ^ T1[(a1 >>> 16) & 0xFF]
+ ^ T2[(a2 >>> 16) & 0xFF] ^ T3[(a3 >>> 16) & 0xFF] ^ Ker[1];
+ b2 = T0[(a0 >>> 8) & 0xFF] ^ T1[(a1 >>> 8) & 0xFF]
+ ^ T2[(a2 >>> 8) & 0xFF] ^ T3[(a3 >>> 8) & 0xFF] ^ Ker[2];
+ b3 = T0[a0 & 0xFF] ^ T1[a1 & 0xFF] ^ T2[a2 & 0xFF] ^ T3[a3 & 0xFF]
+ ^ Ker[3];
+ a0 = b0;
+ a1 = b1;
+ a2 = b2;
+ a3 = b3;
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("T" + r + "=" + Util.toString(a0)
+ + Util.toString(a1) + Util.toString(a2)
+ + Util.toString(a3));
+ }
+ }
+
+ // last round function
+ Ker = K[R];
+ int tt = Ker[0];
+ out[j++] = (byte) (S[a0 >>> 24] ^ (tt >>> 24));
+ out[j++] = (byte) (S[a1 >>> 24] ^ (tt >>> 16));
+ out[j++] = (byte) (S[a2 >>> 24] ^ (tt >>> 8));
+ out[j++] = (byte) (S[a3 >>> 24] ^ tt);
+ tt = Ker[1];
+ out[j++] = (byte) (S[(a0 >>> 16) & 0xFF] ^ (tt >>> 24));
+ out[j++] = (byte) (S[(a1 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (S[(a2 >>> 16) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (S[(a3 >>> 16) & 0xFF] ^ tt);
+ tt = Ker[2];
+ out[j++] = (byte) (S[(a0 >>> 8) & 0xFF] ^ (tt >>> 24));
+ out[j++] = (byte) (S[(a1 >>> 8) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (S[(a2 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (S[(a3 >>> 8) & 0xFF] ^ tt);
+ tt = Ker[3];
+ out[j++] = (byte) (S[a0 & 0xFF] ^ (tt >>> 24));
+ out[j++] = (byte) (S[a1 & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (S[a2 & 0xFF] ^ (tt >>> 8));
+ out[j] = (byte) (S[a3 & 0xFF] ^ tt);
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("T=" + Util.toString(out, j - 15, 16));
+ System.out.println();
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ Anubis result = new Anubis();
+ result.currentBlockSize = this.currentBlockSize;
+
+ return result;
+ }
+
+ // IBlockCipherSpi interface implementation --------------------------------
+
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(DEFAULT_BLOCK_SIZE));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ ArrayList al = new ArrayList();
+ for (int n = 4; n < 10; n++)
+ {
+ al.add(new Integer(n * 32 / 8));
+ }
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ /**
+ * <p>Expands a user-supplied key material into a session key for a
+ * designated <i>block size</i>.</p>
+ *
+ * @param uk the 32N-bit user-supplied key material; 4 &lt;= N &lt;= 10.
+ * @param bs the desired block size in bytes.
+ * @return an Object encapsulating the session key.
+ * @exception IllegalArgumentException if the block size is not 16 (128-bit).
+ * @exception InvalidKeyException if the key data is invalid.
+ */
+ public Object makeKey(byte[] uk, int bs) throws InvalidKeyException
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (uk == null)
+ {
+ throw new InvalidKeyException("Empty key");
+ }
+ if ((uk.length % 4) != 0)
+ {
+ throw new InvalidKeyException("Key is not multiple of 32-bit.");
+ }
+ int N = uk.length / 4;
+ if (N < 4 || N > 10)
+ {
+ throw new InvalidKeyException("Key is not 32N; 4 <= N <= 10");
+ }
+ int R = 8 + N;
+ int[][] Ke = new int[R + 1][4]; // encryption round keys
+ int[][] Kd = new int[R + 1][4]; // decryption round keys
+ int[] tk = new int[N];
+ int[] kk = new int[N];
+ int r, i, j, k, k0, k1, k2, k3, tt;
+
+ // apply mu to k0
+ for (r = 0, i = 0; r < N;)
+ {
+ tk[r++] = uk[i++] << 24 | (uk[i++] & 0xFF) << 16
+ | (uk[i++] & 0xFF) << 8 | (uk[i++] & 0xFF);
+ }
+ for (r = 0; r <= R; r++)
+ {
+ if (r > 0)
+ {
+ // psi = key evolution function
+ kk[0] = T0[(tk[0] >>> 24)] ^ T1[(tk[N - 1] >>> 16) & 0xFF]
+ ^ T2[(tk[N - 2] >>> 8) & 0xFF] ^ T3[tk[N - 3] & 0xFF];
+ kk[1] = T0[(tk[1] >>> 24)] ^ T1[(tk[0] >>> 16) & 0xFF]
+ ^ T2[(tk[N - 1] >>> 8) & 0xFF] ^ T3[tk[N - 2] & 0xFF];
+ kk[2] = T0[(tk[2] >>> 24)] ^ T1[(tk[1] >>> 16) & 0xFF]
+ ^ T2[(tk[0] >>> 8) & 0xFF] ^ T3[tk[N - 1] & 0xFF];
+ kk[3] = T0[(tk[3] >>> 24)] ^ T1[(tk[2] >>> 16) & 0xFF]
+ ^ T2[(tk[1] >>> 8) & 0xFF] ^ T3[tk[0] & 0xFF];
+
+ for (i = 4; i < N; i++)
+ {
+ kk[i] = T0[tk[i] >>> 24] ^ T1[(tk[i - 1] >>> 16) & 0xFF]
+ ^ T2[(tk[i - 2] >>> 8) & 0xFF] ^ T3[tk[i - 3] & 0xFF];
+ }
+ // apply sigma (affine addition) to round constant
+ tk[0] = rc[r - 1] ^ kk[0];
+ for (i = 1; i < N; i++)
+ {
+ tk[i] = kk[i];
+ }
+ }
+
+ // phi = key selection function
+ tt = tk[N - 1];
+ k0 = T4[tt >>> 24];
+ k1 = T4[(tt >>> 16) & 0xFF];
+ k2 = T4[(tt >>> 8) & 0xFF];
+ k3 = T4[tt & 0xFF];
+
+ for (k = N - 2; k >= 0; k--)
+ {
+ tt = tk[k];
+ k0 = T4[tt >>> 24] ^ (T5[(k0 >>> 24) & 0xFF] & 0xFF000000)
+ ^ (T5[(k0 >>> 16) & 0xFF] & 0x00FF0000)
+ ^ (T5[(k0 >>> 8) & 0xFF] & 0x0000FF00)
+ ^ (T5[k0 & 0xFF] & 0x000000FF);
+ k1 = T4[(tt >>> 16) & 0xFF] ^ (T5[(k1 >>> 24) & 0xFF] & 0xFF000000)
+ ^ (T5[(k1 >>> 16) & 0xFF] & 0x00FF0000)
+ ^ (T5[(k1 >>> 8) & 0xFF] & 0x0000FF00)
+ ^ (T5[k1 & 0xFF] & 0x000000FF);
+ k2 = T4[(tt >>> 8) & 0xFF] ^ (T5[(k2 >>> 24) & 0xFF] & 0xFF000000)
+ ^ (T5[(k2 >>> 16) & 0xFF] & 0x00FF0000)
+ ^ (T5[(k2 >>> 8) & 0xFF] & 0x0000FF00)
+ ^ (T5[(k2) & 0xFF] & 0x000000FF);
+ k3 = T4[tt & 0xFF] ^ (T5[(k3 >>> 24) & 0xFF] & 0xFF000000)
+ ^ (T5[(k3 >>> 16) & 0xFF] & 0x00FF0000)
+ ^ (T5[(k3 >>> 8) & 0xFF] & 0x0000FF00)
+ ^ (T5[k3 & 0xFF] & 0x000000FF);
+ }
+
+ Ke[r][0] = k0;
+ Ke[r][1] = k1;
+ Ke[r][2] = k2;
+ Ke[r][3] = k3;
+
+ if (r == 0 || r == R)
+ {
+ Kd[R - r][0] = k0;
+ Kd[R - r][1] = k1;
+ Kd[R - r][2] = k2;
+ Kd[R - r][3] = k3;
+ }
+ else
+ {
+ Kd[R - r][0] = T0[S[k0 >>> 24] & 0xFF]
+ ^ T1[S[(k0 >>> 16) & 0xFF] & 0xFF]
+ ^ T2[S[(k0 >>> 8) & 0xFF] & 0xFF]
+ ^ T3[S[k0 & 0xFF] & 0xFF];
+ Kd[R - r][1] = T0[S[k1 >>> 24] & 0xFF]
+ ^ T1[S[(k1 >>> 16) & 0xFF] & 0xFF]
+ ^ T2[S[(k1 >>> 8) & 0xFF] & 0xFF]
+ ^ T3[S[k1 & 0xFF] & 0xFF];
+ Kd[R - r][2] = T0[S[k2 >>> 24] & 0xFF]
+ ^ T1[S[(k2 >>> 16) & 0xFF] & 0xFF]
+ ^ T2[S[(k2 >>> 8) & 0xFF] & 0xFF]
+ ^ T3[S[k2 & 0xFF] & 0xFF];
+ Kd[R - r][3] = T0[S[k3 >>> 24] & 0xFF]
+ ^ T1[S[(k3 >>> 16) & 0xFF] & 0xFF]
+ ^ T2[S[(k3 >>> 8) & 0xFF] & 0xFF]
+ ^ T3[S[k3 & 0xFF] & 0xFF];
+ }
+ }
+
+ if (DEBUG && debuglevel > 8)
+ {
+ System.out.println();
+ System.out.println("Key schedule");
+ System.out.println();
+ System.out.println("Ke[]:");
+ for (r = 0; r < R + 1; r++)
+ {
+ System.out.print("#" + r + ": ");
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(Ke[r][j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("Kd[]:");
+ for (r = 0; r < R + 1; r++)
+ {
+ System.out.print("#" + r + ": ");
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(Kd[r][j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ }
+
+ return new Object[] { Ke, Kd };
+ }
+
+ public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[][] K = (int[][]) ((Object[]) k)[0];
+ anubis(in, i, out, j, K);
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[][] K = (int[][]) ((Object[]) k)[1];
+ anubis(in, i, out, j, K);
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ boolean result = super.selfTest(); // do symmetry tests
+ if (result)
+ {
+ result = testKat(KAT_KEY, KAT_CT);
+ }
+ valid = new Boolean(result);
+ }
+ return valid.booleanValue();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/BaseCipher.java b/gnu/javax/crypto/cipher/BaseCipher.java
new file mode 100644
index 000000000..9d62311ed
--- /dev/null
+++ b/gnu/javax/crypto/cipher/BaseCipher.java
@@ -0,0 +1,304 @@
+/* BaseCipher.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.util.Util;
+
+import java.security.InvalidKeyException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * <p>A basic abstract class to facilitate implementing symmetric key block
+ * ciphers.</p>
+ */
+public abstract class BaseCipher implements IBlockCipher, IBlockCipherSpi
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of the cipher. */
+ protected String name;
+
+ /** The default block size, in bytes. */
+ protected int defaultBlockSize;
+
+ /** The default key size, in bytes. */
+ protected int defaultKeySize;
+
+ /** The current block size, in bytes. */
+ protected int currentBlockSize;
+
+ /** The session key for this instance. */
+ protected transient Object currentKey;
+
+ /** The instance lock. */
+ protected Object lock = new Object();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name prefix of this instance.
+ * @param defaultBlockSize the default block size in bytes.
+ * @param defaultKeySize the default key size in bytes.
+ */
+ protected BaseCipher(String name, int defaultBlockSize, int defaultKeySize)
+ {
+ super();
+
+ this.name = name;
+ this.defaultBlockSize = defaultBlockSize;
+ this.defaultKeySize = defaultKeySize;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IBlockCipher interface implementation -----------------------------------
+
+ public abstract Object clone();
+
+ public String name()
+ {
+ StringBuffer sb = new StringBuffer(name).append('-');
+ if (currentKey == null)
+ {
+ sb.append(String.valueOf(8 * defaultBlockSize));
+ }
+ else
+ {
+ sb.append(String.valueOf(8 * currentBlockSize));
+ }
+ return sb.toString();
+ }
+
+ public int defaultBlockSize()
+ {
+ return defaultBlockSize;
+ }
+
+ public int defaultKeySize()
+ {
+ return defaultKeySize;
+ }
+
+ public void init(Map attributes) throws InvalidKeyException
+ {
+ synchronized (lock)
+ {
+ if (currentKey != null)
+ {
+ throw new IllegalStateException();
+ }
+
+ Integer bs = (Integer) attributes.get(CIPHER_BLOCK_SIZE);
+ if (bs == null)
+ { // no block size was specified.
+ if (currentBlockSize == 0)
+ { // happy birthday
+ currentBlockSize = defaultBlockSize;
+ } // else it's a clone. use as is
+ }
+ else
+ {
+ currentBlockSize = bs.intValue();
+ // ensure that value is valid
+ Iterator it;
+ boolean ok = false;
+ for (it = blockSizes(); it.hasNext();)
+ {
+ ok = (currentBlockSize == ((Integer) it.next()).intValue());
+ if (ok)
+ {
+ break;
+ }
+ }
+ if (!ok)
+ {
+ throw new IllegalArgumentException(
+ IBlockCipher.CIPHER_BLOCK_SIZE);
+ }
+ }
+
+ byte[] k = (byte[]) attributes.get(KEY_MATERIAL);
+ currentKey = makeKey(k, currentBlockSize);
+ }
+ }
+
+ public int currentBlockSize()
+ {
+ if (currentKey == null)
+ {
+ throw new IllegalStateException();
+ }
+ return currentBlockSize;
+ }
+
+ public void reset()
+ {
+ synchronized (lock)
+ {
+ // currentBlockSize = 0;
+ currentKey = null;
+ }
+ }
+
+ public void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ throws IllegalStateException
+ {
+ synchronized (lock)
+ {
+ if (currentKey == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ encrypt(in, inOffset, out, outOffset, currentKey, currentBlockSize);
+ }
+ }
+
+ public void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ throws IllegalStateException
+ {
+ synchronized (lock)
+ {
+ if (currentKey == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ decrypt(in, inOffset, out, outOffset, currentKey, currentBlockSize);
+ }
+ }
+
+ public boolean selfTest()
+ {
+ int ks;
+ Iterator bit;
+
+ // do symmetry tests for all block-size/key-size combos
+ for (Iterator kit = keySizes(); kit.hasNext();)
+ {
+ ks = ((Integer) kit.next()).intValue();
+ for (bit = blockSizes(); bit.hasNext();)
+ {
+ if (!testSymmetry(ks, ((Integer) bit.next()).intValue()))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private boolean testSymmetry(int ks, int bs)
+ {
+ try
+ {
+ byte[] kb = new byte[ks];
+ byte[] pt = new byte[bs];
+ byte[] ct = new byte[bs];
+ byte[] cpt = new byte[bs];
+ int i;
+ for (i = 0; i < ks; i++)
+ {
+ kb[i] = (byte) i;
+ }
+ for (i = 0; i < bs; i++)
+ {
+ pt[i] = (byte) i;
+ }
+
+ Object k = makeKey(kb, bs);
+ encrypt(pt, 0, ct, 0, k, bs);
+ decrypt(ct, 0, cpt, 0, k, bs);
+
+ return Arrays.equals(pt, cpt);
+
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace(System.err);
+ return false;
+ }
+ }
+
+ protected boolean testKat(byte[] kb, byte[] ct)
+ {
+ return testKat(kb, ct, new byte[ct.length]); // all-zero plaintext
+ }
+
+ protected boolean testKat(byte[] kb, byte[] ct, byte[] pt)
+ {
+ try
+ {
+ int bs = pt.length;
+ byte[] t = new byte[bs];
+
+ Object k = makeKey(kb, bs);
+
+ // test encryption
+ encrypt(pt, 0, t, 0, k, bs);
+ if (!Arrays.equals(t, ct))
+ {
+ return false;
+ }
+ // test decryption
+ decrypt(t, 0, t, 0, k, bs);
+ return Arrays.equals(t, pt);
+
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace(System.err);
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/Blowfish.java b/gnu/javax/crypto/cipher/Blowfish.java
new file mode 100644
index 000000000..5cb958ee4
--- /dev/null
+++ b/gnu/javax/crypto/cipher/Blowfish.java
@@ -0,0 +1,749 @@
+/* Blowfish.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+// --------------------------------------------------------------------------
+//
+// Based on the C implementation from the GNU Privacy Guard.
+//
+// --------------------------------------------------------------------------
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Sequence;
+import gnu.java.security.util.Util;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * Blowfish is a 16-round, 64-bit Feistel cipher designed by Bruce
+ * Schneier. It accepts a variable-length key of up to 448 bits.
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li>Schneier, Bruce: <i>Applied Cryptography</i>, Second Edition,
+ * 336--339, 647--654 (1996 Bruce Schneier).</li>
+ * <li><a href="http://www.counterpane.com/blowfish.html">The
+ * Blowfish Encryption Algorithm.</a></li>
+ * </ol>
+ */
+public class Blowfish extends BaseCipher
+{
+
+ // Constants and variables
+ // -----------------------------------------------------------------
+
+ private static final int DEFAULT_BLOCK_SIZE = 8;
+
+ private static final int DEFAULT_KEY_SIZE = 8;
+
+ private static final int MAX_KEY_LENGTH = 56;
+
+ /** Initial value of the p-array. */
+ private static final int[] P = { 0x243f6a88, 0x85a308d3, 0x13198a2e,
+ 0x03707344, 0xa4093822, 0x299f31d0,
+ 0x082efa98, 0xec4e6c89, 0x452821e6,
+ 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5,
+ 0xb5470917, 0x9216d5d9, 0x8979fb1b };
+
+ /** Initial value of S-box 1. */
+ static final int[] KS0 = { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a };
+
+ /** Initial value of S-box 2. */
+ private static final int[] KS1 = { 0x4b7a70e9, 0xb5b32944, 0xdb75092e,
+ 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
+ 0x9cee60b8, 0x8fedb266, 0xecaa8c71,
+ 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340,
+ 0xe4183a3e, 0x3f54989a, 0x5b429d65,
+ 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07,
+ 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6,
+ 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
+ 0x3c971814, 0x6b6a70a1, 0x687f3584,
+ 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec,
+ 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
+ 0xf01c1f04, 0x0200b3ff, 0xae0cf51a,
+ 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773,
+ 0x22f54701, 0x3ae5e581, 0x37c2dadc,
+ 0xc8b57634, 0x9af3dda7, 0xa9446146,
+ 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1,
+ 0x183eb331, 0x4e548b38, 0x4f6db908,
+ 0x6f420d03, 0xf60a04bf, 0x2cb81290,
+ 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12,
+ 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
+ 0x501adde6, 0x9f84cd87, 0x7a584718,
+ 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366,
+ 0xc464c3d2, 0xef1c1847, 0x3215d908,
+ 0xdd433b37, 0x24c2ba16, 0x12a14d43,
+ 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6,
+ 0x5f11199b, 0x043556f1, 0xd7a3c76b,
+ 0x3c11183b, 0x5924a509, 0xf28fe6ed,
+ 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a,
+ 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
+ 0x2965dcb9, 0x99e71d0f, 0x803e89d6,
+ 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53,
+ 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
+ 0x1939260f, 0x19c27960, 0x5223a708,
+ 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1,
+ 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
+ 0x65582185, 0x68ab9802, 0xeecea50f,
+ 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775,
+ 0x619f1510, 0x13cca830, 0xeb61bd96,
+ 0x0334fe1e, 0xaa0363cf, 0xb5735c90,
+ 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab,
+ 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
+ 0xa02369b9, 0x655abb50, 0x40685a32,
+ 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e,
+ 0x623d7da8, 0xf837889a, 0x97e32d77,
+ 0x11ed935f, 0x16681281, 0x0e358829,
+ 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff,
+ 0x1ac24696, 0xcdb30aeb, 0x532e3054,
+ 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef,
+ 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14,
+ 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
+ 0xdb6c4f15, 0xfacb4fd0, 0xc742f442,
+ 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a,
+ 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
+ 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3,
+ 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174,
+ 0x23820e00, 0x58428d2a, 0x0c55f5ea,
+ 0x1dadf43e, 0x233f7061, 0x3372f092,
+ 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7,
+ 0xce77326e, 0xa6078084, 0x19f8509e,
+ 0xe8efd855, 0x61d99735, 0xa969a7aa,
+ 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705,
+ 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
+ 0x675fda79, 0xe3674340, 0xc5c43465,
+ 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b,
+ 0xdb83adf7 };
+
+ /** Initial value of S-box 3. */
+ private static final int[] KS2 = { 0xe93d5a68, 0x948140f7, 0xf64c261c,
+ 0x94692934, 0x411520f7, 0x7602d4f7,
+ 0xbcf46b2e, 0xd4a20068, 0xd4082471,
+ 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0x1e39f62e, 0x97244546, 0x14214f74,
+ 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
+ 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec,
+ 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6,
+ 0xabca0a9a, 0x28507825, 0x530429f4,
+ 0x0a2c86da, 0xe9b66dfb, 0x68dc1462,
+ 0xd7486900, 0x680ec0a4, 0x27a18dee,
+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006,
+ 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
+ 0xce78a399, 0x406b2a42, 0x20fe9e35,
+ 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631,
+ 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
+ 0x6841e7f7, 0xca7820fb, 0xfb0af54e,
+ 0xd8feb397, 0x454056ac, 0xba489527,
+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7,
+ 0xd096954b, 0x55a867bc, 0xa1159a58,
+ 0xcca92963, 0x99e1db33, 0xa62a4a56,
+ 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c,
+ 0x05282ce3, 0x95c11548, 0xe4c66d22,
+ 0x48c1133f, 0xc70f86dc, 0x07f9c9ee,
+ 0x41041f0f, 0x404779a4, 0x5d886e17,
+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f,
+ 0x41113564, 0x257b7834, 0x602a9c60,
+ 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2,
+ 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62,
+ 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
+ 0xde720c8c, 0x2da2f728, 0xd0127845,
+ 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+ 0x5449a36f, 0x877d48fa, 0xc39dfd27,
+ 0xf33e8d1e, 0x0a476341, 0x992eff74,
+ 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60,
+ 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b,
+ 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
+ 0xb5390f92, 0x690fed0b, 0x667b9ffb,
+ 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+ 0xbb132f88, 0x515bad24, 0x7b9479bf,
+ 0x763bd6eb, 0x37392eb3, 0xcc115979,
+ 0x8026e297, 0xf42e312d, 0x6842ada7,
+ 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6,
+ 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
+ 0x3d25bdd8, 0xe2e1c3c9, 0x44421659,
+ 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+ 0x64af674e, 0xda86a85f, 0xbebfe988,
+ 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
+ 0x60787bf8, 0x6003604d, 0xd1fd8346,
+ 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187,
+ 0x3c005e5f, 0x77a057be, 0xbde8ae24,
+ 0x55464299, 0xbf582e61, 0x4e58f48f,
+ 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+ 0x5366f9c3, 0xc8b38e74, 0xb475f255,
+ 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
+ 0x846a0e79, 0x915f95e2, 0x466e598e,
+ 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248,
+ 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
+ 0x662d09a1, 0xc4324633, 0xe85a1f02,
+ 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f,
+ 0x2868f169, 0xdcb7da83, 0x573906fe,
+ 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01,
+ 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06,
+ 0x61a806b5, 0xf0177a28, 0xc0f586e0,
+ 0x006058aa, 0x30dc7d62, 0x11e69ed7,
+ 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1,
+ 0xce591d76, 0x6f05e409, 0x4b7c0188,
+ 0x39720a3d, 0x7c927c24, 0x86e3725f,
+ 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3,
+ 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
+ 0xa28514d9, 0x6c51133c, 0x6fd5c7e7,
+ 0x56e14ec4, 0x362abfce, 0xddc6c837,
+ 0xd79a3234, 0x92638212, 0x670efa8e,
+ 0x406000e0 };
+
+ /** Initial value of S-box 4. */
+ private static final int[] KS3 = { 0x3a39ce37, 0xd3faf5cf, 0xabc27737,
+ 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
+ 0xd3822740, 0x99bc9bbe, 0xd5118e9d,
+ 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be,
+ 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
+ 0xc6a376d2, 0x6549c2c8, 0x530ff8ee,
+ 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8,
+ 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
+ 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8,
+ 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550,
+ 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
+ 0x4ba99586, 0xef5562e9, 0xc72fefd3,
+ 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad,
+ 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
+ 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a,
+ 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472,
+ 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
+ 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d,
+ 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44,
+ 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
+ 0x03a16125, 0x0564f0bd, 0xc3eb9e15,
+ 0x3c9057a2, 0x97271aec, 0xa93a072a,
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb,
+ 0x26dcf319, 0x7533d928, 0xb155fdf5,
+ 0x03563482, 0x8aba3cbb, 0x28517711,
+ 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862,
+ 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
+ 0x5121ce64, 0x774fbe32, 0xa8b6e37e,
+ 0xc3293d46, 0x48de5369, 0x6413e680,
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd,
+ 0x09072166, 0xb39a460a, 0x6445c0dd,
+ 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd,
+ 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44,
+ 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
+ 0x8d6612ae, 0xbf3c6f47, 0xd29be463,
+ 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+ 0x740e0d8d, 0xe75b1357, 0xf8721671,
+ 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
+ 0x34d2466a, 0x0115af84, 0xe1b00428,
+ 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b,
+ 0x277227f8, 0x611560b1, 0xe7933fdc,
+ 0xbb3a792b, 0x344525bd, 0xa08839e1,
+ 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3,
+ 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
+ 0xd0dadecb, 0xd50ada38, 0x0339c32a,
+ 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff,
+ 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
+ 0x0f91fc71, 0x9b941525, 0xfae59361,
+ 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065,
+ 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
+ 0x4c98a0be, 0x3278e964, 0x9f1f9532,
+ 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120,
+ 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
+ 0xe60b6f47, 0x0fe3f11d, 0xe54cda54,
+ 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5,
+ 0xf6fb2299, 0xf523f357, 0xa6327623,
+ 0x93a83531, 0x56cccd02, 0xacf08162,
+ 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b,
+ 0x71c65614, 0xe6c6c7bd, 0x327a140a,
+ 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd,
+ 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+ 0x71126905, 0xb2040222, 0xb6cbcf7c,
+ 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
+ 0x38abbd60, 0x2547adf0, 0xba38209c,
+ 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0,
+ 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
+ 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869,
+ 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3,
+ 0x3ac372e6 };
+
+ /** Cache of the self test. */
+ private static Boolean valid;
+
+ /**
+ * Test vector, as published in
+ * href="http://www.counterpane.com/vectors.txt">http://www.counterpane.com/vectors.txt</a>.
+ *
+ * KEY=0000000000000000
+ * PT=0000000000000000
+ * CT=4EF997456198DD78
+ */
+ private static final byte[] TV_KEY = Util.toBytesFromString("0000000000000000");
+
+ private static final byte[] TV_CT = Util.toBytesFromString("4EF997456198DD78");
+
+ // Constructors
+ // -----------------------------------------------------------------------
+
+ public Blowfish()
+ {
+ super(Registry.BLOWFISH_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+ }
+
+ // Clonable interface implementation.
+ // -----------------------------------------------------------------------
+
+ public Object clone()
+ {
+ Blowfish result = new Blowfish();
+ result.currentBlockSize = currentBlockSize;
+ return result;
+ }
+
+ // Implementations of abstract methods from BaseCipher
+ // -----------------------------------------------------------------------
+
+ public Iterator keySizes()
+ {
+ return new Sequence(8, MAX_KEY_LENGTH, 8).iterator();
+ // return new Iterator() {
+ // private int i = 0;
+
+ // public boolean hasNext() {
+ // return i <= MAX_KEY_LENGTH-8;
+ // }
+
+ // public Object next() {
+ // if (hasNext()) {
+ // i += 8;
+ // return new Integer(i);
+ // }
+ // return null;
+ // }
+
+ // public void remove() {
+ // throw new UnsupportedOperationException();
+ // }
+ // };
+ }
+
+ public Iterator blockSizes()
+ {
+ return Collections.singleton(new Integer(DEFAULT_BLOCK_SIZE)).iterator();
+ }
+
+ public Object makeKey(byte[] k, int bs)
+ {
+ Context ctx = new Context();
+ System.arraycopy(P, 0, ctx.p, 0, P.length);
+ System.arraycopy(KS0, 0, ctx.s0, 0, KS0.length);
+ System.arraycopy(KS1, 0, ctx.s1, 0, KS1.length);
+ System.arraycopy(KS2, 0, ctx.s2, 0, KS2.length);
+ System.arraycopy(KS3, 0, ctx.s3, 0, KS3.length);
+
+ // XOR the key with the P-box
+ int l = 0;
+ for (int i = 0; i < ctx.p.length; i++)
+ {
+ int data = 0;
+ for (int j = 0; j < 4; j++)
+ {
+ data = (data << 8) | (k[l++] & 0xff);
+ if (l >= k.length)
+ {
+ l = 0;
+ }
+ }
+ ctx.p[i] ^= data;
+ }
+
+ // We swap the left and right words here only, so we can avoid
+ // swapping altogether during encryption/decryption.
+ int t;
+ Block x = new Block();
+ x.left = x.right = 0;
+ for (int i = 0; i < ctx.p.length; i += 2)
+ {
+ blowfishEncrypt(x, ctx);
+ ctx.p[i] = x.right;
+ ctx.p[i + 1] = x.left;
+ t = x.right;
+ x.right = x.left;
+ x.left = t;
+ }
+ for (int i = 0; i < ctx.s0.length; i += 2)
+ {
+ blowfishEncrypt(x, ctx);
+ ctx.s0[i] = x.right;
+ ctx.s0[i + 1] = x.left;
+ t = x.right;
+ x.right = x.left;
+ x.left = t;
+ }
+ for (int i = 0; i < ctx.s1.length; i += 2)
+ {
+ blowfishEncrypt(x, ctx);
+ ctx.s1[i] = x.right;
+ ctx.s1[i + 1] = x.left;
+ t = x.right;
+ x.right = x.left;
+ x.left = t;
+ }
+ for (int i = 0; i < ctx.s2.length; i += 2)
+ {
+ blowfishEncrypt(x, ctx);
+ ctx.s2[i] = x.right;
+ ctx.s2[i + 1] = x.left;
+ t = x.right;
+ x.right = x.left;
+ x.left = t;
+ }
+ for (int i = 0; i < ctx.s3.length; i += 2)
+ {
+ blowfishEncrypt(x, ctx);
+ ctx.s3[i] = x.right;
+ ctx.s3[i + 1] = x.left;
+ t = x.right;
+ x.right = x.left;
+ x.left = t;
+ }
+ x.left = x.right = 0;
+ return ctx;
+ }
+
+ public void encrypt(byte[] in, int i, byte[] out, int o, Object k, int bs)
+ {
+ Block x = new Block();
+ x.left = (in[i] & 0xff) << 24 | (in[i + 1] & 0xff) << 16
+ | (in[i + 2] & 0xff) << 8 | (in[i + 3] & 0xff);
+ x.right = (in[i + 4] & 0xff) << 24 | (in[i + 5] & 0xff) << 16
+ | (in[i + 6] & 0xff) << 8 | (in[i + 7] & 0xff);
+ blowfishEncrypt(x, (Context) k);
+ out[o] = (byte) (x.right >>> 24);
+ out[o + 1] = (byte) (x.right >>> 16);
+ out[o + 2] = (byte) (x.right >>> 8);
+ out[o + 3] = (byte) x.right;
+ out[o + 4] = (byte) (x.left >>> 24);
+ out[o + 5] = (byte) (x.left >>> 16);
+ out[o + 6] = (byte) (x.left >>> 8);
+ out[o + 7] = (byte) x.left;
+ x.left = x.right = 0;
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int o, Object k, int bs)
+ {
+ Block x = new Block();
+ x.left = (in[i] & 0xff) << 24 | (in[i + 1] & 0xff) << 16
+ | (in[i + 2] & 0xff) << 8 | (in[i + 3] & 0xff);
+ x.right = (in[i + 4] & 0xff) << 24 | (in[i + 5] & 0xff) << 16
+ | (in[i + 6] & 0xff) << 8 | (in[i + 7] & 0xff);
+ blowfishDecrypt(x, (Context) k);
+ out[o] = (byte) (x.right >>> 24);
+ out[o + 1] = (byte) (x.right >>> 16);
+ out[o + 2] = (byte) (x.right >>> 8);
+ out[o + 3] = (byte) x.right;
+ out[o + 4] = (byte) (x.left >>> 24);
+ out[o + 5] = (byte) (x.left >>> 16);
+ out[o + 6] = (byte) (x.left >>> 8);
+ out[o + 7] = (byte) x.left;
+ x.left = x.right = 0;
+ }
+
+ // Own methods
+ // -----------------------------------------------------------------
+
+ /** Encrypt a single pair of 32-bit integers. */
+ private void blowfishEncrypt(Block x, Context ctx)
+ {
+ int[] p = ctx.p;
+ int[] s0 = ctx.s0, s1 = ctx.s1, s2 = ctx.s2, s3 = ctx.s3;
+ x.left ^= p[0];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[1];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[2];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[3];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[4];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[5];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[6];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[7];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[8];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[9];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[10];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[11];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[12];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[13];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[14];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[15];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[16];
+ x.right ^= p[17];
+ }
+
+ /** Decrypt a single pair of 32-bit integers. */
+ private void blowfishDecrypt(Block x, Context ctx)
+ {
+ int[] p = ctx.p;
+ int[] s0 = ctx.s0, s1 = ctx.s1, s2 = ctx.s2, s3 = ctx.s3;
+ x.left ^= p[17];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[16];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[15];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[14];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[13];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[12];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[11];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[10];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[9];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[8];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[7];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[6];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[5];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[4];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[3];
+ x.right ^= ((s0[x.left >>> 24] + s1[x.left >>> 16 & 0xff]) ^ s2[x.left >>> 8 & 0xff])
+ + s3[x.left & 0xff] ^ p[2];
+ x.left ^= ((s0[x.right >>> 24] + s1[x.right >>> 16 & 0xff]) ^ s2[x.right >>> 8 & 0xff])
+ + s3[x.right & 0xff] ^ p[1];
+ x.right ^= p[0];
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ boolean result = super.selfTest(); // symmetry
+ if (result)
+ {
+ result = testKat(TV_KEY, TV_CT);
+ }
+ valid = new Boolean(result);
+ }
+ return valid.booleanValue();
+ }
+
+ // Inner classes.
+ // -----------------------------------------------------------------------
+
+ /** A simple wrapper for the P- and S-boxes. */
+ private class Context implements Cloneable
+ {
+
+ // Constants and variables.
+ // --------------------------------------------------------------------
+
+ /** The P-array. */
+ int[] p, s0, s1, s2, s3;
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ /** Default 0-arguments constructor. */
+ Context()
+ {
+ p = new int[18];
+ s0 = new int[256];
+ s1 = new int[256];
+ s2 = new int[256];
+ s3 = new int[256];
+ }
+
+ /**
+ * Private constructor for cloneing.
+ *
+ * @param that The instance being cloned.
+ */
+ private Context(Context that)
+ {
+ this.p = (int[]) that.p.clone();
+ this.s0 = (int[]) that.s0.clone();
+ this.s1 = (int[]) that.s1.clone();
+ this.s2 = (int[]) that.s2.clone();
+ this.s3 = (int[]) that.s3.clone();
+ }
+
+ // Clonable interface implementation.
+ // --------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new Context(this);
+ }
+ }
+
+ private class Block
+ {
+ int left, right;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/Cast5.java b/gnu/javax/crypto/cipher/Cast5.java
new file mode 100644
index 000000000..cbdfe61f5
--- /dev/null
+++ b/gnu/javax/crypto/cipher/Cast5.java
@@ -0,0 +1,1391 @@
+/* Cast5.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>An implmenetation of the <code>CAST5</code> (a.k.a. CAST-128) algorithm,
+ * as per <i>RFC-2144</i>, dated May 1997.</p>
+ *
+ * <p>In this RFC, <i>Carlisle Adams</i> (the CA in CAST, ST stands for
+ * <i>Stafford Tavares</i>) describes CAST5 as:</p>
+ *
+ * <blockquote>
+ * "...a DES-like Substitution-Permutation Network (SPN) cryptosystem which
+ * appears to have good resistance to differential cryptanalysis, linear
+ * cryptanalysis, and related-key cryptanalysis. This cipher also possesses
+ * a number of other desirable cryptographic properties, including avalanche,
+ * Strict Avalanche Criterion (SAC), Bit Independence Criterion (BIC), no
+ * complementation property, and an absence of weak and semi-weak keys."
+ * </blockquote>
+ *
+ * <p><code>CAST5</code> is a symmetric block cipher with a block-size of 8
+ * bytes and a variable key-size of up to 128 bits. Its authors, and their
+ * employer (Entrust Technologies, a Nortel majority-owned company), made it
+ * available worldwide on a royalty-free basis for commercial and non-commercial
+ * uses.</p>
+ *
+ * <p>The <code>CAST5</code> encryption algorithm has been designed to allow a
+ * key size that can vary from <code>40</code> bits to <code>128</code> bits,
+ * in 8-bit increments (that is, the allowable key sizes are <code>40, 48, 56,
+ * 64, ..., 112, 120,</code> and <code>128</code> bits. For variable keysize
+ * operation, the specification is as follows:</p>
+ *
+ * <ol>
+ * <li>For key sizes up to and including <code>80</code> bits (i.e.,
+ * <code>40, 48, 56, 64, 72,</code> and <code>80</code> bits), the algorithm
+ * is exactly as specified but uses <code>12</code> rounds instead of
+ * <code>16</code>;</li>
+ * <li>For key sizes greater than <code>80</code> bits, the algorithm uses
+ * the full <code>16</code> rounds;</li>
+ * <li>For key sizes less than <code>128</code> bits, the key is padded with
+ * zero bytes (in the rightmost, or least significant, positions) out to
+ * <code>128</code> bits (since the <code>CAST5</code> key schedule assumes
+ * an input key of <code>128</code> bits).</li>
+ * </ol>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc2144.txt">The CAST-128 Encryption
+ * Algorithm</a>.<br>
+ * <a href="mailto:cadams@entrust.com">Carlisle Adams</a>.</li>
+ * </ol>
+ */
+public class Cast5 extends BaseCipher
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_BLOCK_SIZE = 8; // in bytes
+
+ private static final int DEFAULT_KEY_SIZE = 5; // in bytes
+
+ /**
+ * KAT vector (from rfc-2144):
+ * 40-bit key = 01 23 45 67 12
+ * = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00
+ * plaintext = 01 23 45 67 89 AB CD EF
+ * ciphertext = 7A C8 16 D1 6E 9B 30 2E
+ */
+ private static final byte[] KAT_KEY = Util.toBytesFromString("0123456712");
+
+ private static final byte[] KAT_PT = Util.toBytesFromString("0123456789ABCDEF");
+
+ private static final byte[] KAT_CT = Util.toBytesFromString("7AC816D16E9B302E");
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ // CAST5 S-boxes
+ private static final int[] S1 = { 0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F,
+ 0x3F258C7A, 0x1E213F2F, 0x9C004DD3,
+ 0x6003E540, 0xCF9FC949, 0xBFD4AF27,
+ 0x88BBBDB5, 0xE2034090, 0x98D09675,
+ 0x6E63A0E0, 0x15C361D2, 0xC2E7661D,
+ 0x22D4FF8E, 0x28683B6F, 0xC07FD059,
+ 0xFF2379C8, 0x775F50E2, 0x43C340D3,
+ 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D,
+ 0xA1C9E0D6, 0x346C4819, 0x61B76D87,
+ 0x22540F2F, 0x2ABE32E1, 0xAA54166B,
+ 0x22568E3A, 0xA2D341D0, 0x66DB40C8,
+ 0xA784392F, 0x004DFF2F, 0x2DB9D2DE,
+ 0x97943FAC, 0x4A97C1D8, 0x527644B7,
+ 0xB5F437A7, 0xB82CBAEF, 0xD751D159,
+ 0x6FF7F0ED, 0x5A097A1F, 0x827B68D0,
+ 0x90ECF52E, 0x22B0C054, 0xBC8E5935,
+ 0x4B6D2F7F, 0x50BB64A2, 0xD2664910,
+ 0xBEE5812D, 0xB7332290, 0xE93B159F,
+ 0xB48EE411, 0x4BFF345D, 0xFD45C240,
+ 0xAD31973F, 0xC4F6D02E, 0x55FC8165,
+ 0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D,
+ 0xC19B0C50, 0x882240F2, 0x0C6E4F38,
+ 0xA4E4BFD7, 0x4F5BA272, 0x564C1D2F,
+ 0xC59C5319, 0xB949E354, 0xB04669FE,
+ 0xB1B6AB8A, 0xC71358DD, 0x6385C545,
+ 0x110F935D, 0x57538AD5, 0x6A390493,
+ 0xE63D37E0, 0x2A54F6B3, 0x3A787D5F,
+ 0x6276A0B5, 0x19A6FCDF, 0x7A42206A,
+ 0x29F9D4D5, 0xF61B1891, 0xBB72275E,
+ 0xAA508167, 0x38901091, 0xC6B505EB,
+ 0x84C7CB8C, 0x2AD75A0F, 0x874A1427,
+ 0xA2D1936B, 0x2AD286AF, 0xAA56D291,
+ 0xD7894360, 0x425C750D, 0x93B39E26,
+ 0x187184C9, 0x6C00B32D, 0x73E2BB14,
+ 0xA0BEBC3C, 0x54623779, 0x64459EAB,
+ 0x3F328B82, 0x7718CF82, 0x59A2CEA6,
+ 0x04EE002E, 0x89FE78E6, 0x3FAB0950,
+ 0x325FF6C2, 0x81383F05, 0x6963C5C8,
+ 0x76CB5AD6, 0xD49974C9, 0xCA180DCF,
+ 0x380782D5, 0xC7FA5CF6, 0x8AC31511,
+ 0x35E79E13, 0x47DA91D0, 0xF40F9086,
+ 0xA7E2419E, 0x31366241, 0x051EF495,
+ 0xAA573B04, 0x4A805D8D, 0x548300D0,
+ 0x00322A3C, 0xBF64CDDF, 0xBA57A68E,
+ 0x75C6372B, 0x50AFD341, 0xA7C13275,
+ 0x915A0BF5, 0x6B54BFAB, 0x2B0B1426,
+ 0xAB4CC9D7, 0x449CCD82, 0xF7FBF265,
+ 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324,
+ 0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02,
+ 0xC8BD25AC, 0xEADF55B3, 0xD5BD9E98,
+ 0xE31231B2, 0x2AD5AD6C, 0x954329DE,
+ 0xADBE4528, 0xD8710F69, 0xAA51C90F,
+ 0xAA786BF6, 0x22513F1E, 0xAA51A79B,
+ 0x2AD344CC, 0x7B5A41F0, 0xD37CFBAD,
+ 0x1B069505, 0x41ECE491, 0xB4C332E6,
+ 0x032268D4, 0xC9600ACC, 0xCE387E6D,
+ 0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9,
+ 0xD4DF39DE, 0xE01063DA, 0x4736F464,
+ 0x5AD328D8, 0xB347CC96, 0x75BB0FC3,
+ 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A,
+ 0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10,
+ 0xAC39570A, 0x3F04442F, 0x6188B153,
+ 0xE0397A2E, 0x5727CB79, 0x9CEB418F,
+ 0x1CACD68D, 0x2AD37C96, 0x0175CB9D,
+ 0xC69DFF09, 0xC75B65F0, 0xD9DB40D8,
+ 0xEC0E7779, 0x4744EAD4, 0xB11C3274,
+ 0xDD24CB9E, 0x7E1C54BD, 0xF01144F9,
+ 0xD2240EB1, 0x9675B3FD, 0xA3AC3755,
+ 0xD47C27AF, 0x51C85F4D, 0x56907596,
+ 0xA5BB15E6, 0x580304F0, 0xCA042CF1,
+ 0x011A37EA, 0x8DBFAADB, 0x35BA3E4A,
+ 0x3526FFA0, 0xC37B4D09, 0xBC306ED9,
+ 0x98A52666, 0x5648F725, 0xFF5E569D,
+ 0x0CED63D0, 0x7C63B2CF, 0x700B45E1,
+ 0xD5EA50F1, 0x85A92872, 0xAF1FBDA7,
+ 0xD4234870, 0xA7870BF3, 0x2D3B4D79,
+ 0x42E04198, 0x0CD0EDE7, 0x26470DB8,
+ 0xF881814C, 0x474D6AD7, 0x7C0C5E5C,
+ 0xD1231959, 0x381B7298, 0xF5D2F4DB,
+ 0xAB838653, 0x6E2F1E23, 0x83719C9E,
+ 0xBD91E046, 0x9A56456E, 0xDC39200C,
+ 0x20C8C571, 0x962BDA1C, 0xE1E696FF,
+ 0xB141AB08, 0x7CCA89B9, 0x1A69E783,
+ 0x02CC4843, 0xA2F7C579, 0x429EF47D,
+ 0x427B169C, 0x5AC9F049, 0xDD8F0F00,
+ 0x5C8165BF };
+
+ private static final int[] S2 = { 0x1F201094, 0xEF0BA75B, 0x69E3CF7E,
+ 0x393F4380, 0xFE61CF7A, 0xEEC5207A,
+ 0x55889C94, 0x72FC0651, 0xADA7EF79,
+ 0x4E1D7235, 0xD55A63CE, 0xDE0436BA,
+ 0x99C430EF, 0x5F0C0794, 0x18DCDB7D,
+ 0xA1D6EFF3, 0xA0B52F7B, 0x59E83605,
+ 0xEE15B094, 0xE9FFD909, 0xDC440086,
+ 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB,
+ 0xD1DA4181, 0x3B092AB1, 0xF997F1C1,
+ 0xA5E6CF7B, 0x01420DDB, 0xE4E7EF5B,
+ 0x25A1FF41, 0xE180F806, 0x1FC41080,
+ 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4,
+ 0x98DE8B7F, 0x77E83F4E, 0x79929269,
+ 0x24FA9F7B, 0xE113C85B, 0xACC40083,
+ 0xD7503525, 0xF7EA615F, 0x62143154,
+ 0x0D554B63, 0x5D681121, 0xC866C359,
+ 0x3D63CF73, 0xCEE234C0, 0xD4D87E87,
+ 0x5C672B21, 0x071F6181, 0x39F7627F,
+ 0x361E3084, 0xE4EB573B, 0x602F64A4,
+ 0xD63ACD9C, 0x1BBC4635, 0x9E81032D,
+ 0x2701F50C, 0x99847AB4, 0xA0E3DF79,
+ 0xBA6CF38C, 0x10843094, 0x2537A95E,
+ 0xF46F6FFE, 0xA1FF3B1F, 0x208CFB6A,
+ 0x8F458C74, 0xD9E0A227, 0x4EC73A34,
+ 0xFC884F69, 0x3E4DE8DF, 0xEF0E0088,
+ 0x3559648D, 0x8A45388C, 0x1D804366,
+ 0x721D9BFD, 0xA58684BB, 0xE8256333,
+ 0x844E8212, 0x128D8098, 0xFED33FB4,
+ 0xCE280AE1, 0x27E19BA5, 0xD5A6C252,
+ 0xE49754BD, 0xC5D655DD, 0xEB667064,
+ 0x77840B4D, 0xA1B6A801, 0x84DB26A9,
+ 0xE0B56714, 0x21F043B7, 0xE5D05860,
+ 0x54F03084, 0x066FF472, 0xA31AA153,
+ 0xDADC4755, 0xB5625DBF, 0x68561BE6,
+ 0x83CA6B94, 0x2D6ED23B, 0xECCF01DB,
+ 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709,
+ 0x33B4A34C, 0x397BC8D6, 0x5EE22B95,
+ 0x5F0E5304, 0x81ED6F61, 0x20E74364,
+ 0xB45E1378, 0xDE18639B, 0x881CA122,
+ 0xB96726D1, 0x8049A7E8, 0x22B7DA7B,
+ 0x5E552D25, 0x5272D237, 0x79D2951C,
+ 0xC60D894C, 0x488CB402, 0x1BA4FE5B,
+ 0xA4B09F6B, 0x1CA815CF, 0xA20C3005,
+ 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9,
+ 0x0BEEFF53, 0xE3214517, 0xB4542835,
+ 0x9F63293C, 0xEE41E729, 0x6E1D2D7C,
+ 0x50045286, 0x1E6685F3, 0xF33401C6,
+ 0x30A22C95, 0x31A70850, 0x60930F13,
+ 0x73F98417, 0xA1269859, 0xEC645C44,
+ 0x52C877A9, 0xCDFF33A6, 0xA02B1741,
+ 0x7CBAD9A2, 0x2180036F, 0x50D99C08,
+ 0xCB3F4861, 0xC26BD765, 0x64A3F6AB,
+ 0x80342676, 0x25A75E7B, 0xE4E6D1FC,
+ 0x20C710E6, 0xCDF0B680, 0x17844D3B,
+ 0x31EEF84D, 0x7E0824E4, 0x2CCB49EB,
+ 0x846A3BAE, 0x8FF77888, 0xEE5D60F6,
+ 0x7AF75673, 0x2FDD5CDB, 0xA11631C1,
+ 0x30F66F43, 0xB3FAEC54, 0x157FD7FA,
+ 0xEF8579CC, 0xD152DE58, 0xDB2FFD5E,
+ 0x8F32CE19, 0x306AF97A, 0x02F03EF8,
+ 0x99319AD5, 0xC242FA0F, 0xA7E3EBB0,
+ 0xC68E4906, 0xB8DA230C, 0x80823028,
+ 0xDCDEF3C8, 0xD35FB171, 0x088A1BC8,
+ 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D,
+ 0xC72FEFFA, 0x22822E99, 0x82C570B4,
+ 0xD8D94E89, 0x8B1C34BC, 0x301E16E6,
+ 0x273BE979, 0xB0FFEAA6, 0x61D9B8C6,
+ 0x00B24869, 0xB7FFCE3F, 0x08DC283B,
+ 0x43DAF65A, 0xF7E19798, 0x7619B72F,
+ 0x8F1C9BA4, 0xDC8637A0, 0x16A7D3B1,
+ 0x9FC393B7, 0xA7136EEB, 0xC6BCC63E,
+ 0x1A513742, 0xEF6828BC, 0x520365D6,
+ 0x2D6A77AB, 0x3527ED4B, 0x821FD216,
+ 0x095C6E2E, 0xDB92F2FB, 0x5EEA29CB,
+ 0x145892F5, 0x91584F7F, 0x5483697B,
+ 0x2667A8CC, 0x85196048, 0x8C4BACEA,
+ 0x833860D4, 0x0D23E0F9, 0x6C387E8A,
+ 0x0AE6D249, 0xB284600C, 0xD835731D,
+ 0xDCB1C647, 0xAC4C56EA, 0x3EBD81B3,
+ 0x230EABB0, 0x6438BC87, 0xF0B5B1FA,
+ 0x8F5EA2B3, 0xFC184642, 0x0A036B7A,
+ 0x4FB089BD, 0x649DA589, 0xA345415E,
+ 0x5C038323, 0x3E5D3BB9, 0x43D79572,
+ 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF,
+ 0x7160A539, 0x73BFBE70, 0x83877605,
+ 0x4523ECF1 };
+
+ private static final int[] S3 = { 0x8DEFC240, 0x25FA5D9F, 0xEB903DBF,
+ 0xE810C907, 0x47607FFF, 0x369FE44B,
+ 0x8C1FC644, 0xAECECA90, 0xBEB1F9BF,
+ 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE,
+ 0x920E8806, 0xF0AD0548, 0xE13C8D83,
+ 0x927010D5, 0x11107D9F, 0x07647DB9,
+ 0xB2E3E4D4, 0x3D4F285E, 0xB9AFA820,
+ 0xFADE82E0, 0xA067268B, 0x8272792E,
+ 0x553FB2C0, 0x489AE22B, 0xD4EF9794,
+ 0x125E3FBC, 0x21FFFCEE, 0x825B1BFD,
+ 0x9255C5ED, 0x1257A240, 0x4E1A8302,
+ 0xBAE07FFF, 0x528246E7, 0x8E57140E,
+ 0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8,
+ 0xC982B5A5, 0xA8C01DB7, 0x579FC264,
+ 0x67094F31, 0xF2BD3F5F, 0x40FFF7C1,
+ 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B,
+ 0x99B03DBF, 0xB5DBC64B, 0x638DC0E6,
+ 0x55819D99, 0xA197C81C, 0x4A012D6E,
+ 0xC5884A28, 0xCCC36F71, 0xB843C213,
+ 0x6C0743F1, 0x8309893C, 0x0FEDDD5F,
+ 0x2F7FE850, 0xD7C07F7E, 0x02507FBF,
+ 0x5AFB9A04, 0xA747D2D0, 0x1651192E,
+ 0xAF70BF3E, 0x58C31380, 0x5F98302E,
+ 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82,
+ 0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49,
+ 0x50DA88B8, 0x8427F4A0, 0x1EAC5790,
+ 0x796FB449, 0x8252DC15, 0xEFBD7D9B,
+ 0xA672597D, 0xADA840D8, 0x45F54504,
+ 0xFA5D7403, 0xE83EC305, 0x4F91751A,
+ 0x925669C2, 0x23EFE941, 0xA903F12E,
+ 0x60270DF2, 0x0276E4B6, 0x94FD6574,
+ 0x927985B2, 0x8276DBCB, 0x02778176,
+ 0xF8AF918D, 0x4E48F79E, 0x8F616DDF,
+ 0xE29D840E, 0x842F7D83, 0x340CE5C8,
+ 0x96BBB682, 0x93B4B148, 0xEF303CAB,
+ 0x984FAF28, 0x779FAF9B, 0x92DC560D,
+ 0x224D1E20, 0x8437AA88, 0x7D29DC96,
+ 0x2756D3DC, 0x8B907CEE, 0xB51FD240,
+ 0xE7C07CE3, 0xE566B4A1, 0xC3E9615E,
+ 0x3CF8209D, 0x6094D1E3, 0xCD9CA341,
+ 0x5C76460E, 0x00EA983B, 0xD4D67881,
+ 0xFD47572C, 0xF76CEDD9, 0xBDA8229C,
+ 0x127DADAA, 0x438A074E, 0x1F97C090,
+ 0x081BDB8A, 0x93A07EBE, 0xB938CA15,
+ 0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC,
+ 0x64380E51, 0x68CC7BFB, 0xD90F2788,
+ 0x12490181, 0x5DE5FFD4, 0xDD7EF86A,
+ 0x76A2E214, 0xB9A40368, 0x925D958F,
+ 0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B,
+ 0xFAF7933B, 0x6D498623, 0x193CBCFA,
+ 0x27627545, 0x825CF47A, 0x61BD8BA0,
+ 0xD11E42D1, 0xCEAD04F4, 0x127EA392,
+ 0x10428DB7, 0x8272A972, 0x9270C4A8,
+ 0x127DE50B, 0x285BA1C8, 0x3C62F44F,
+ 0x35C0EAA5, 0xE805D231, 0x428929FB,
+ 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B,
+ 0x1F081FAB, 0x108618AE, 0xFCFD086D,
+ 0xF9FF2889, 0x694BCC11, 0x236A5CAE,
+ 0x12DECA4D, 0x2C3F8CC5, 0xD2D02DFE,
+ 0xF8EF5896, 0xE4CF52DA, 0x95155B67,
+ 0x494A488C, 0xB9B6A80C, 0x5C8F82BC,
+ 0x89D36B45, 0x3A609437, 0xEC00C9A9,
+ 0x44715253, 0x0A874B49, 0xD773BC40,
+ 0x7C34671C, 0x02717EF6, 0x4FEB5536,
+ 0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0,
+ 0x50B4EF6D, 0x07478CD1, 0x006E1888,
+ 0xA2E53F55, 0xB9E6D4BC, 0xA2048016,
+ 0x97573833, 0xD7207D67, 0xDE0F8F3D,
+ 0x72F87B33, 0xABCC4F33, 0x7688C55D,
+ 0x7B00A6B0, 0x947B0001, 0x570075D2,
+ 0xF9BB88F8, 0x8942019E, 0x4264A5FF,
+ 0x856302E0, 0x72DBD92B, 0xEE971B69,
+ 0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D,
+ 0xE5C98767, 0xCF1FEBD2, 0x61EFC8C2,
+ 0xF1AC2571, 0xCC8239C2, 0x67214CB8,
+ 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE,
+ 0xF90A5C38, 0x0FF0443D, 0x606E6DC6,
+ 0x60543A49, 0x5727C148, 0x2BE98A1D,
+ 0x8AB41738, 0x20E1BE24, 0xAF96DA0F,
+ 0x68458425, 0x99833BE5, 0x600D457D,
+ 0x282F9350, 0x8334B362, 0xD91D1120,
+ 0x2B6D8DA0, 0x642B1E31, 0x9C305A00,
+ 0x52BCE688, 0x1B03588A, 0xF7BAEFD5,
+ 0x4142ED9C, 0xA4315C11, 0x83323EC5,
+ 0xDFEF4636, 0xA133C501, 0xE9D3531C,
+ 0xEE353783 };
+
+ private static final int[] S4 = { 0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF,
+ 0xD273A298, 0x4A4F7BDB, 0x64AD8C57,
+ 0x85510443, 0xFA020ED1, 0x7E287AFF,
+ 0xE60FB663, 0x095F35A1, 0x79EBF120,
+ 0xFD059D43, 0x6497B7B1, 0xF3641F63,
+ 0x241E4ADF, 0x28147F5F, 0x4FA2B8CD,
+ 0xC9430040, 0x0CC32220, 0xFDD30B30,
+ 0xC0A5374F, 0x1D2D00D9, 0x24147B15,
+ 0xEE4D111A, 0x0FCA5167, 0x71FF904C,
+ 0x2D195FFE, 0x1A05645F, 0x0C13FEFE,
+ 0x081B08CA, 0x05170121, 0x80530100,
+ 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701,
+ 0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A,
+ 0x7293EA25, 0xCE84FFDF, 0xF5718801,
+ 0x3DD64B04, 0xA26F263B, 0x7ED48400,
+ 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5,
+ 0x2649ABDF, 0xAEA0C7F5, 0x36338CC1,
+ 0x503F7E93, 0xD3772061, 0x11B638E1,
+ 0x72500E03, 0xF80EB2BB, 0xABE0502E,
+ 0xEC8D77DE, 0x57971E81, 0xE14F6746,
+ 0xC9335400, 0x6920318F, 0x081DBB99,
+ 0xFFC304A5, 0x4D351805, 0x7F3D5CE3,
+ 0xA6C866C6, 0x5D5BCCA9, 0xDAEC6FEA,
+ 0x9F926F91, 0x9F46222F, 0x3991467D,
+ 0xA5BF6D8E, 0x1143C44F, 0x43958302,
+ 0xD0214EEB, 0x022083B8, 0x3FB6180C,
+ 0x18F8931E, 0x281658E6, 0x26486E3E,
+ 0x8BD78A70, 0x7477E4C1, 0xB506E07C,
+ 0xF32D0A25, 0x79098B02, 0xE4EABB81,
+ 0x28123B23, 0x69DEAD38, 0x1574CA16,
+ 0xDF871B62, 0x211C40B7, 0xA51A9EF9,
+ 0x0014377B, 0x041E8AC8, 0x09114003,
+ 0xBD59E4D2, 0xE3D156D5, 0x4FE876D5,
+ 0x2F91A340, 0x557BE8DE, 0x00EAE4A7,
+ 0x0CE5C2EC, 0x4DB4BBA6, 0xE756BDFF,
+ 0xDD3369AC, 0xEC17B035, 0x06572327,
+ 0x99AFC8B0, 0x56C8C391, 0x6B65811C,
+ 0x5E146119, 0x6E85CB75, 0xBE07C002,
+ 0xC2325577, 0x893FF4EC, 0x5BBFC92D,
+ 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24,
+ 0x20C763EF, 0xC366A5FC, 0x9C382880,
+ 0x0ACE3205, 0xAAC9548A, 0xECA1D7C7,
+ 0x041AFA32, 0x1D16625A, 0x6701902C,
+ 0x9B757A54, 0x31D477F7, 0x9126B031,
+ 0x36CC6FDB, 0xC70B8B46, 0xD9E66A48,
+ 0x56E55A79, 0x026A4CEB, 0x52437EFF,
+ 0x2F8F76B4, 0x0DF980A5, 0x8674CDE3,
+ 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF,
+ 0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20,
+ 0x2E096B7C, 0x1741A254, 0xE5B6A035,
+ 0x213D42F6, 0x2C1C7C26, 0x61C2F50F,
+ 0x6552DAF9, 0xD2C231F8, 0x25130F69,
+ 0xD8167FA2, 0x0418F2C8, 0x001A96A6,
+ 0x0D1526AB, 0x63315C21, 0x5E0A72EC,
+ 0x49BAFEFD, 0x187908D9, 0x8D0DBD86,
+ 0x311170A7, 0x3E9B640C, 0xCC3E10D7,
+ 0xD5CAD3B6, 0x0CAEC388, 0xF73001E1,
+ 0x6C728AFF, 0x71EAE2A1, 0x1F9AF36E,
+ 0xCFCBD12F, 0xC1DE8417, 0xAC07BE6B,
+ 0xCB44A1D8, 0x8B9B0F56, 0x013988C3,
+ 0xB1C52FCA, 0xB4BE31CD, 0xD8782806,
+ 0x12A3A4E2, 0x6F7DE532, 0x58FD7EB6,
+ 0xD01EE900, 0x24ADFFC2, 0xF4990FC5,
+ 0x9711AAC5, 0x001D7B95, 0x82E5E7D2,
+ 0x109873F6, 0x00613096, 0xC32D9521,
+ 0xADA121FF, 0x29908415, 0x7FBB977F,
+ 0xAF9EB3DB, 0x29C9ED2A, 0x5CE2A465,
+ 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091,
+ 0xD49E2CE7, 0x0CE454A9, 0xD60ACD86,
+ 0x015F1919, 0x77079103, 0xDEA03AF6,
+ 0x78A8565E, 0xDEE356DF, 0x21F05CBE,
+ 0x8B75E387, 0xB3C50651, 0xB8A5C3EF,
+ 0xD8EEB6D2, 0xE523BE77, 0xC2154529,
+ 0x2F69EFDF, 0xAFE67AFB, 0xF470C4B2,
+ 0xF3E0EB5B, 0xD6CC9876, 0x39E4460C,
+ 0x1FDA8538, 0x1987832F, 0xCA007367,
+ 0xA99144F8, 0x296B299E, 0x492FC295,
+ 0x9266BEAB, 0xB5676E69, 0x9BD3DDDA,
+ 0xDF7E052F, 0xDB25701C, 0x1B5E51EE,
+ 0xF65324E6, 0x6AFCE36C, 0x0316CC04,
+ 0x8644213E, 0xB7DC59D0, 0x7965291F,
+ 0xCCD6FD43, 0x41823979, 0x932BCDF6,
+ 0xB657C34D, 0x4EDFD282, 0x7AE5290C,
+ 0x3CB9536B, 0x851E20FE, 0x9833557E,
+ 0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1,
+ 0x0AEF7ED2 };
+
+ private static final int[] S5 = { 0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF,
+ 0xA6337911, 0xB86A7FFF, 0x1DD358F5,
+ 0x44DD9D44, 0x1731167F, 0x08FBF1FA,
+ 0xE7F511CC, 0xD2051B00, 0x735ABA00,
+ 0x2AB722D8, 0x386381CB, 0xACF6243A,
+ 0x69BEFD7A, 0xE6A2E77F, 0xF0C720CD,
+ 0xC4494816, 0xCCF5C180, 0x38851640,
+ 0x15B0A848, 0xE68B18CB, 0x4CAADEFF,
+ 0x5F480A01, 0x0412B2AA, 0x259814FC,
+ 0x41D0EFE2, 0x4E40B48D, 0x248EB6FB,
+ 0x8DBA1CFE, 0x41A99B02, 0x1A550A04,
+ 0xBA8F65CB, 0x7251F4E7, 0x95A51725,
+ 0xC106ECD7, 0x97A5980A, 0xC539B9AA,
+ 0x4D79FE6A, 0xF2F3F763, 0x68AF8040,
+ 0xED0C9E56, 0x11B4958B, 0xE1EB5A88,
+ 0x8709E6B0, 0xD7E07156, 0x4E29FEA7,
+ 0x6366E52D, 0x02D1C000, 0xC4AC8E05,
+ 0x9377F571, 0x0C05372A, 0x578535F2,
+ 0x2261BE02, 0xD642A0C9, 0xDF13A280,
+ 0x74B55BD2, 0x682199C0, 0xD421E5EC,
+ 0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9,
+ 0x3D959981, 0x5C1FF900, 0xFE38D399,
+ 0x0C4EFF0B, 0x062407EA, 0xAA2F4FB1,
+ 0x4FB96976, 0x90C79505, 0xB0A8A774,
+ 0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27,
+ 0xE66A4263, 0xDF65001F, 0x0EC50966,
+ 0xDFDD55BC, 0x29DE0655, 0x911E739A,
+ 0x17AF8975, 0x32C7911C, 0x89F89468,
+ 0x0D01E980, 0x524755F4, 0x03B63CC9,
+ 0x0CC844B2, 0xBCF3F0AA, 0x87AC36E9,
+ 0xE53A7426, 0x01B3D82B, 0x1A9E7449,
+ 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910,
+ 0xB868BF80, 0x0D26F3FD, 0x9342EDE7,
+ 0x04A5C284, 0x636737B6, 0x50F5B616,
+ 0xF24766E3, 0x8ECA36C1, 0x136E05DB,
+ 0xFEF18391, 0xFB887A37, 0xD6E7F7D4,
+ 0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE,
+ 0xEC2941DA, 0x26E46695, 0xB7566419,
+ 0xF654EFC5, 0xD08D58B7, 0x48925401,
+ 0xC1BACB7F, 0xE5FF550F, 0xB6083049,
+ 0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1,
+ 0x223A66CE, 0xC62BF3CD, 0x9E0885F9,
+ 0x68CB3E47, 0x086C010F, 0xA21DE820,
+ 0xD18B69DE, 0xF3F65777, 0xFA02C3F6,
+ 0x407EDAC3, 0xCBB3D550, 0x1793084D,
+ 0xB0D70EBA, 0x0AB378D5, 0xD951FB0C,
+ 0xDED7DA56, 0x4124BBE4, 0x94CA0B56,
+ 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE,
+ 0x580A249F, 0x94F74BC0, 0xE327888E,
+ 0x9F7B5561, 0xC3DC0280, 0x05687715,
+ 0x646C6BD7, 0x44904DB3, 0x66B4F0A3,
+ 0xC0F1648A, 0x697ED5AF, 0x49E92FF6,
+ 0x309E374F, 0x2CB6356A, 0x85808573,
+ 0x4991F840, 0x76F0AE02, 0x083BE84D,
+ 0x28421C9A, 0x44489406, 0x736E4CB8,
+ 0xC1092910, 0x8BC95FC6, 0x7D869CF4,
+ 0x134F616F, 0x2E77118D, 0xB31B2BE1,
+ 0xAA90B472, 0x3CA5D717, 0x7D161BBA,
+ 0x9CAD9010, 0xAF462BA2, 0x9FE459D2,
+ 0x45D34559, 0xD9F2DA13, 0xDBC65487,
+ 0xF3E4F94E, 0x176D486F, 0x097C13EA,
+ 0x631DA5C7, 0x445F7382, 0x175683F4,
+ 0xCDC66A97, 0x70BE0288, 0xB3CDCF72,
+ 0x6E5DD2F3, 0x20936079, 0x459B80A5,
+ 0xBE60E2DB, 0xA9C23101, 0xEBA5315C,
+ 0x224E42F2, 0x1C5C1572, 0xF6721B2C,
+ 0x1AD2FFF3, 0x8C25404E, 0x324ED72F,
+ 0x4067B7FD, 0x0523138E, 0x5CA3BC78,
+ 0xDC0FD66E, 0x75922283, 0x784D6B17,
+ 0x58EBB16E, 0x44094F85, 0x3F481D87,
+ 0xFCFEAE7B, 0x77B5FF76, 0x8C2302BF,
+ 0xAAF47556, 0x5F46B02A, 0x2B092801,
+ 0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A,
+ 0x66D5E7C0, 0xDF3B0874, 0x95055110,
+ 0x1B5AD7A8, 0xF61ED5AD, 0x6CF6E479,
+ 0x20758184, 0xD0CEFA65, 0x88F7BE58,
+ 0x4A046826, 0x0FF6F8F3, 0xA09C7F70,
+ 0x5346ABA0, 0x5CE96C28, 0xE176EDA3,
+ 0x6BAC307F, 0x376829D2, 0x85360FA9,
+ 0x17E3FE2A, 0x24B79767, 0xF5A96B20,
+ 0xD6CD2595, 0x68FF1EBF, 0x7555442C,
+ 0xF19F06BE, 0xF9E0659A, 0xEEB9491D,
+ 0x34010718, 0xBB30CAB8, 0xE822FE15,
+ 0x88570983, 0x750E6249, 0xDA627E55,
+ 0x5E76FFA8, 0xB1534546, 0x6D47DE08,
+ 0xEFE9E7D4 };
+
+ private static final int[] S6 = { 0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867,
+ 0xE2337F7C, 0x95DB08E7, 0x016843B4,
+ 0xECED5CBC, 0x325553AC, 0xBF9F0960,
+ 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9,
+ 0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732,
+ 0x8989B138, 0x33F14961, 0xC01937BD,
+ 0xF506C6DA, 0xE4625E7E, 0xA308EA99,
+ 0x4E23E33C, 0x79CBD7CC, 0x48A14367,
+ 0xA3149619, 0xFEC94BD5, 0xA114174A,
+ 0xEAA01866, 0xA084DB2D, 0x09A8486F,
+ 0xA888614A, 0x2900AF98, 0x01665991,
+ 0xE1992863, 0xC8F30C60, 0x2E78EF3C,
+ 0xD0D51932, 0xCF0FEC14, 0xF7CA07D2,
+ 0xD0A82072, 0xFD41197E, 0x9305A6B0,
+ 0xE86BE3DA, 0x74BED3CD, 0x372DA53C,
+ 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3,
+ 0x083919A7, 0x9FBAEED9, 0x49DBCFB0,
+ 0x4E670C53, 0x5C3D9C01, 0x64BDB941,
+ 0x2C0E636A, 0xBA7DD9CD, 0xEA6F7388,
+ 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D,
+ 0xF0D48D8C, 0xB88153E2, 0x08A19866,
+ 0x1AE2EAC8, 0x284CAF89, 0xAA928223,
+ 0x9334BE53, 0x3B3A21BF, 0x16434BE3,
+ 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9,
+ 0x80226DAE, 0xC340A4A3, 0xDF7E9C09,
+ 0xA694A807, 0x5B7C5ECC, 0x221DB3A6,
+ 0x9A69A02F, 0x68818A54, 0xCEB2296F,
+ 0x53C0843A, 0xFE893655, 0x25BFE68A,
+ 0xB4628ABC, 0xCF222EBF, 0x25AC6F48,
+ 0xA9A99387, 0x53BDDB65, 0xE76FFBE7,
+ 0xE967FD78, 0x0BA93563, 0x8E342BC1,
+ 0xE8A11BE9, 0x4980740D, 0xC8087DFC,
+ 0x8DE4BF99, 0xA11101A0, 0x7FD37975,
+ 0xDA5A26C0, 0xE81F994F, 0x9528CD89,
+ 0xFD339FED, 0xB87834BF, 0x5F04456D,
+ 0x22258698, 0xC9C4C83B, 0x2DC156BE,
+ 0x4F628DAA, 0x57F55EC5, 0xE2220ABE,
+ 0xD2916EBF, 0x4EC75B95, 0x24F2C3C0,
+ 0x42D15D99, 0xCD0D7FA0, 0x7B6E27FF,
+ 0xA8DC8AF0, 0x7345C106, 0xF41E232F,
+ 0x35162386, 0xE6EA8926, 0x3333B094,
+ 0x157EC6F2, 0x372B74AF, 0x692573E4,
+ 0xE9A9D848, 0xF3160289, 0x3A62EF1D,
+ 0xA787E238, 0xF3A5F676, 0x74364853,
+ 0x20951063, 0x4576698D, 0xB6FAD407,
+ 0x592AF950, 0x36F73523, 0x4CFB6E87,
+ 0x7DA4CEC0, 0x6C152DAA, 0xCB0396A8,
+ 0xC50DFE5D, 0xFCD707AB, 0x0921C42F,
+ 0x89DFF0BB, 0x5FE2BE78, 0x448F4F33,
+ 0x754613C9, 0x2B05D08D, 0x48B9D585,
+ 0xDC049441, 0xC8098F9B, 0x7DEDE786,
+ 0xC39A3373, 0x42410005, 0x6A091751,
+ 0x0EF3C8A6, 0x890072D6, 0x28207682,
+ 0xA9A9F7BE, 0xBF32679D, 0xD45B5B75,
+ 0xB353FD00, 0xCBB0E358, 0x830F220A,
+ 0x1F8FB214, 0xD372CF08, 0xCC3C4A13,
+ 0x8CF63166, 0x061C87BE, 0x88C98F88,
+ 0x6062E397, 0x47CF8E7A, 0xB6C85283,
+ 0x3CC2ACFB, 0x3FC06976, 0x4E8F0252,
+ 0x64D8314D, 0xDA3870E3, 0x1E665459,
+ 0xC10908F0, 0x513021A5, 0x6C5B68B7,
+ 0x822F8AA0, 0x3007CD3E, 0x74719EEF,
+ 0xDC872681, 0x073340D4, 0x7E432FD9,
+ 0x0C5EC241, 0x8809286C, 0xF592D891,
+ 0x08A930F6, 0x957EF305, 0xB7FBFFBD,
+ 0xC266E96F, 0x6FE4AC98, 0xB173ECC0,
+ 0xBC60B42A, 0x953498DA, 0xFBA1AE12,
+ 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB,
+ 0xE2969123, 0x257F0C3D, 0x9348AF49,
+ 0x361400BC, 0xE8816F4A, 0x3814F200,
+ 0xA3F94043, 0x9C7A54C2, 0xBC704F57,
+ 0xDA41E7F9, 0xC25AD33A, 0x54F4A084,
+ 0xB17F5505, 0x59357CBE, 0xEDBD15C8,
+ 0x7F97C5AB, 0xBA5AC7B5, 0xB6F6DEAF,
+ 0x3A479C3A, 0x5302DA25, 0x653D7E6A,
+ 0x54268D49, 0x51A477EA, 0x5017D55B,
+ 0xD7D25D88, 0x44136C76, 0x0404A8C8,
+ 0xB8E5A121, 0xB81A928A, 0x60ED5869,
+ 0x97C55B96, 0xEAEC991B, 0x29935913,
+ 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5,
+ 0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35,
+ 0xA0E1D855, 0xD36B4CF1, 0xF544EDEB,
+ 0xB0E93524, 0xBEBB8FBD, 0xA2D762CF,
+ 0x49C92F54, 0x38B5F331, 0x7128A454,
+ 0x48392905, 0xA65B1DB8, 0x851C97BD,
+ 0xD675CF2F };
+
+ private static final int[] S7 = { 0x85E04019, 0x332BF567, 0x662DBFFF,
+ 0xCFC65693, 0x2A8D7F6F, 0xAB9BC912,
+ 0xDE6008A1, 0x2028DA1F, 0x0227BCE7,
+ 0x4D642916, 0x18FAC300, 0x50F18B82,
+ 0x2CB2CB11, 0xB232E75C, 0x4B3695F2,
+ 0xB28707DE, 0xA05FBCF6, 0xCD4181E9,
+ 0xE150210C, 0xE24EF1BD, 0xB168C381,
+ 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43,
+ 0x4D495001, 0x38BE4341, 0x913CEE1D,
+ 0x92A79C3F, 0x089766BE, 0xBAEEADF4,
+ 0x1286BECF, 0xB6EACB19, 0x2660C200,
+ 0x7565BDE4, 0x64241F7A, 0x8248DCA9,
+ 0xC3B3AD66, 0x28136086, 0x0BD8DFA8,
+ 0x356D1CF2, 0x107789BE, 0xB3B2E9CE,
+ 0x0502AA8F, 0x0BC0351E, 0x166BF52A,
+ 0xEB12FF82, 0xE3486911, 0xD34D7516,
+ 0x4E7B3AFF, 0x5F43671B, 0x9CF6E037,
+ 0x4981AC83, 0x334266CE, 0x8C9341B7,
+ 0xD0D854C0, 0xCB3A6C88, 0x47BC2829,
+ 0x4725BA37, 0xA66AD22B, 0x7AD61F1E,
+ 0x0C5CBAFA, 0x4437F107, 0xB6E79962,
+ 0x42D2D816, 0x0A961288, 0xE1A5C06E,
+ 0x13749E67, 0x72FC081A, 0xB1D139F7,
+ 0xF9583745, 0xCF19DF58, 0xBEC3F756,
+ 0xC06EBA30, 0x07211B24, 0x45C28829,
+ 0xC95E317F, 0xBC8EC511, 0x38BC46E9,
+ 0xC6E6FA14, 0xBAE8584A, 0xAD4EBC46,
+ 0x468F508B, 0x7829435F, 0xF124183B,
+ 0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D,
+ 0x16E39264, 0x92544A8B, 0x009B4FC3,
+ 0xABA68CED, 0x9AC96F78, 0x06A5B79A,
+ 0xB2856E6E, 0x1AEC3CA9, 0xBE838688,
+ 0x0E0804E9, 0x55F1BE56, 0xE7E5363B,
+ 0xB3A1F25D, 0xF7DEBB85, 0x61FE033C,
+ 0x16746233, 0x3C034C28, 0xDA6D0C74,
+ 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802,
+ 0x98F8F35A, 0x1626A49F, 0xEED82B29,
+ 0x1D382FE3, 0x0C4FB99A, 0xBB325778,
+ 0x3EC6D97B, 0x6E77A6A9, 0xCB658B5C,
+ 0xD45230C7, 0x2BD1408B, 0x60C03EB7,
+ 0xB9068D78, 0xA33754F4, 0xF430C87D,
+ 0xC8A71302, 0xB96D8C32, 0xEBD4E7BE,
+ 0xBE8B9D2D, 0x7979FB06, 0xE7225308,
+ 0x8B75CF77, 0x11EF8DA4, 0xE083C858,
+ 0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0,
+ 0x5DDA0033, 0xF28EBFB0, 0xF5B9C310,
+ 0xA0EAC280, 0x08B9767A, 0xA3D9D2B0,
+ 0x79D34217, 0x021A718D, 0x9AC6336A,
+ 0x2711FD60, 0x438050E3, 0x069908A8,
+ 0x3D7FEDC4, 0x826D2BEF, 0x4EEB8476,
+ 0x488DCF25, 0x36C9D566, 0x28E74E41,
+ 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF,
+ 0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6,
+ 0x9EA80509, 0xF22B017D, 0xA4173F70,
+ 0xDD1E16C3, 0x15E0D7F9, 0x50B1B887,
+ 0x2B9F4FD5, 0x625ABA82, 0x6A017962,
+ 0x2EC01B9C, 0x15488AA9, 0xD716E740,
+ 0x40055A2C, 0x93D29A22, 0xE32DBF9A,
+ 0x058745B9, 0x3453DC1E, 0xD699296E,
+ 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07,
+ 0xB87242D1, 0x19DE7EAE, 0x053E561A,
+ 0x15AD6F8C, 0x66626C1C, 0x7154C24C,
+ 0xEA082B2A, 0x93EB2939, 0x17DCB0F0,
+ 0x58D4F2AE, 0x9EA294FB, 0x52CF564C,
+ 0x9883FE66, 0x2EC40581, 0x763953C3,
+ 0x01D6692E, 0xD3A0C108, 0xA1E7160E,
+ 0xE4F2DFA6, 0x693ED285, 0x74904698,
+ 0x4C2B0EDD, 0x4F757656, 0x5D393378,
+ 0xA132234F, 0x3D321C5D, 0xC3F5E194,
+ 0x4B269301, 0xC79F022F, 0x3C997E7E,
+ 0x5E4F9504, 0x3FFAFBBD, 0x76F7AD0E,
+ 0x296693F4, 0x3D1FCE6F, 0xC61E45BE,
+ 0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0,
+ 0x4E72B567, 0x5592A33D, 0xB5229301,
+ 0xCFD2A87F, 0x60AEB767, 0x1814386B,
+ 0x30BCC33D, 0x38A0C07D, 0xFD1606F2,
+ 0xC363519B, 0x589DD390, 0x5479F8E6,
+ 0x1CB8D647, 0x97FD61A9, 0xEA7759F4,
+ 0x2D57539D, 0x569A58CF, 0xE84E63AD,
+ 0x462E1B78, 0x6580F87E, 0xF3817914,
+ 0x91DA55F4, 0x40A230F3, 0xD1988F35,
+ 0xB6E318D2, 0x3FFA50BC, 0x3D40F021,
+ 0xC3C0BDAE, 0x4958C24C, 0x518F36B2,
+ 0x84B1D370, 0x0FEDCE83, 0x878DDADA,
+ 0xF2A279C7, 0x94E01BE8, 0x90716F4B,
+ 0x954B8AA3 };
+
+ private static final int[] S8 = { 0xE216300D, 0xBBDDFFFC, 0xA7EBDABD,
+ 0x35648095, 0x7789F8B7, 0xE6C1121B,
+ 0x0E241600, 0x052CE8B5, 0x11A9CFB0,
+ 0xE5952F11, 0xECE7990A, 0x9386D174,
+ 0x2A42931C, 0x76E38111, 0xB12DEF3A,
+ 0x37DDDDFC, 0xDE9ADEB1, 0x0A0CC32C,
+ 0xBE197029, 0x84A00940, 0xBB243A0F,
+ 0xB4D137CF, 0xB44E79F0, 0x049EEDFD,
+ 0x0B15A15D, 0x480D3168, 0x8BBBDE5A,
+ 0x669DED42, 0xC7ECE831, 0x3F8F95E7,
+ 0x72DF191B, 0x7580330D, 0x94074251,
+ 0x5C7DCDFA, 0xABBE6D63, 0xAA402164,
+ 0xB301D40A, 0x02E7D1CA, 0x53571DAE,
+ 0x7A3182A2, 0x12A8DDEC, 0xFDAA335D,
+ 0x176F43E8, 0x71FB46D4, 0x38129022,
+ 0xCE949AD4, 0xB84769AD, 0x965BD862,
+ 0x82F3D055, 0x66FB9767, 0x15B80B4E,
+ 0x1D5B47A0, 0x4CFDE06F, 0xC28EC4B8,
+ 0x57E8726E, 0x647A78FC, 0x99865D44,
+ 0x608BD593, 0x6C200E03, 0x39DC5FF6,
+ 0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632,
+ 0x70108C0C, 0xBBD35049, 0x2998DF04,
+ 0x980CF42A, 0x9B6DF491, 0x9E7EDD53,
+ 0x06918548, 0x58CB7E07, 0x3B74EF2E,
+ 0x522FFFB1, 0xD24708CC, 0x1C7E27CD,
+ 0xA4EB215B, 0x3CF1D2E2, 0x19B47A38,
+ 0x424F7618, 0x35856039, 0x9D17DEE7,
+ 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8,
+ 0x09C467CD, 0xC18910B1, 0xE11DBF7B,
+ 0x06CD1AF8, 0x7170C608, 0x2D5E3354,
+ 0xD4DE495A, 0x64C6D006, 0xBCC0C62C,
+ 0x3DD00DB3, 0x708F8F34, 0x77D51B42,
+ 0x264F620F, 0x24B8D2BF, 0x15C1B79E,
+ 0x46A52564, 0xF8D7E54E, 0x3E378160,
+ 0x7895CDA5, 0x859C15A5, 0xE6459788,
+ 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB,
+ 0x7F229B1E, 0x31842E7B, 0x24259FD7,
+ 0xF8BEF472, 0x835FFCB8, 0x6DF4C1F2,
+ 0x96F5B195, 0xFD0AF0FC, 0xB0FE134C,
+ 0xE2506D3D, 0x4F9B12EA, 0xF215F225,
+ 0xA223736F, 0x9FB4C428, 0x25D04979,
+ 0x34C713F8, 0xC4618187, 0xEA7A6E98,
+ 0x7CD16EFC, 0x1436876C, 0xF1544107,
+ 0xBEDEEE14, 0x56E9AF27, 0xA04AA441,
+ 0x3CF7C899, 0x92ECBAE6, 0xDD67016D,
+ 0x151682EB, 0xA842EEDF, 0xFDBA60B4,
+ 0xF1907B75, 0x20E3030F, 0x24D8C29E,
+ 0xE139673B, 0xEFA63FB8, 0x71873054,
+ 0xB6F2CF3B, 0x9F326442, 0xCB15A4CC,
+ 0xB01A4504, 0xF1E47D8D, 0x844A1BE5,
+ 0xBAE7DFDC, 0x42CBDA70, 0xCD7DAE0A,
+ 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C,
+ 0xCEA4D428, 0x79D130A4, 0x3486EBFB,
+ 0x33D3CDDC, 0x77853B53, 0x37EFFCB5,
+ 0xC5068778, 0xE580B3E6, 0x4E68B8F4,
+ 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C,
+ 0x132A4F94, 0x43B7950E, 0x2FEE7D1C,
+ 0x223613BD, 0xDD06CAA2, 0x37DF932B,
+ 0xC4248289, 0xACF3EBC3, 0x5715F6B7,
+ 0xEF3478DD, 0xF267616F, 0xC148CBE4,
+ 0x9052815E, 0x5E410FAB, 0xB48A2465,
+ 0x2EDA7FA4, 0xE87B40E4, 0xE98EA084,
+ 0x5889E9E1, 0xEFD390FC, 0xDD07D35B,
+ 0xDB485694, 0x38D7E5B2, 0x57720101,
+ 0x730EDEBC, 0x5B643113, 0x94917E4F,
+ 0x503C2FBA, 0x646F1282, 0x7523D24A,
+ 0xE0779695, 0xF9C17A8F, 0x7A5B2121,
+ 0xD187B896, 0x29263A4D, 0xBA510CDF,
+ 0x81F47C9F, 0xAD1163ED, 0xEA7B5965,
+ 0x1A00726E, 0x11403092, 0x00DA6D77,
+ 0x4A0CDD61, 0xAD1F4603, 0x605BDFB0,
+ 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A,
+ 0xA0E736A0, 0x5564A6B9, 0x10853209,
+ 0xC7EB8F37, 0x2DE705CA, 0x8951570F,
+ 0xDF09822B, 0xBD691A6C, 0xAA12E4F2,
+ 0x87451C0F, 0xE0F6A27A, 0x3ADA4819,
+ 0x4CF1764F, 0x0D771C2B, 0x67CDB156,
+ 0x350D8384, 0x5938FA0F, 0x42399EF3,
+ 0x36997B07, 0x0E84093D, 0x4AA93E61,
+ 0x8360D87B, 0x1FA98B0C, 0x1149382C,
+ 0xE97625A5, 0x0614D1B7, 0x0E25244B,
+ 0x0C768347, 0x589E8D82, 0x0D2059D1,
+ 0xA466BB1E, 0xF8DA0A82, 0x04F19130,
+ 0xBA6E4EC0, 0x99265164, 0x1EE7230D,
+ 0x50B2AD80, 0xEAEE6801, 0x8DB2A283,
+ 0xEA8BF59E };
+
+ private static final int _12_ROUNDS = 12;
+
+ private static final int _16_ROUNDS = 16;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Cast5()
+ {
+ super(Registry.CAST5_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Assuming the input is a 32-bit block organised as: b31b30b29...b0, this
+ * method returns an array of 4 Java ints, containing from position 0 onward
+ * the values: {b31b30b29b28, b27b26b25b24, ... , b3b2b1b0}.
+ *
+ * @param x a 32-bit block.
+ * @return an array of 4 ints, each being the contents of an 8-bit block from
+ * the input.
+ */
+ private static final int[] unscramble(int x)
+ {
+ return new int[] { x >>> 24, (x >>> 16) & 0xFF, (x >>> 8) & 0xFF, x & 0xFF };
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ Cast5 result = new Cast5();
+ result.currentBlockSize = this.currentBlockSize;
+
+ return result;
+ }
+
+ // IBlockCipherSpi interface implementation --------------------------------
+
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(DEFAULT_BLOCK_SIZE));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ ArrayList al = new ArrayList();
+ for (int n = 5; n < 17; n++)
+ {
+ al.add(new Integer(n));
+ }
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Object makeKey(byte[] uk, int bs) throws InvalidKeyException
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (uk == null)
+ {
+ throw new InvalidKeyException("Empty key");
+ }
+ int len = uk.length;
+ if (len < 5 || len > 16)
+ {
+ throw new InvalidKeyException(
+ "Key size (in bytes) is not in the range [5..16]");
+ }
+
+ Cast5Key result = new Cast5Key();
+ result.rounds = (len < 11) ? _12_ROUNDS : _16_ROUNDS;
+ byte[] kk = new byte[16];
+ System.arraycopy(uk, 0, kk, 0, len);
+
+ int z0z1z2z3, z4z5z6z7, z8z9zAzB, zCzDzEzF;
+ int z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, zA, zB, zC, zD, zE, zF;
+ int x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, xA, xB, xC, xD, xE, xF;
+ int[] b;
+
+ int x0x1x2x3 = kk[0] << 24 | (kk[1] & 0xFF) << 16 | (kk[2] & 0xFF) << 8
+ | (kk[3] & 0xFF);
+ int x4x5x6x7 = kk[4] << 24 | (kk[5] & 0xFF) << 16 | (kk[6] & 0xFF) << 8
+ | (kk[7] & 0xFF);
+ int x8x9xAxB = kk[8] << 24 | (kk[9] & 0xFF) << 16 | (kk[10] & 0xFF) << 8
+ | (kk[11] & 0xFF);
+ int xCxDxExF = kk[12] << 24 | (kk[13] & 0xFF) << 16 | (kk[14] & 0xFF) << 8
+ | (kk[15] & 0xFF);
+
+ b = unscramble(x0x1x2x3);
+ x0 = b[0];
+ x1 = b[1];
+ x2 = b[2];
+ x3 = b[3];
+ b = unscramble(x4x5x6x7);
+ x4 = b[0];
+ x5 = b[1];
+ x6 = b[2];
+ x7 = b[3];
+ b = unscramble(x8x9xAxB);
+ x8 = b[0];
+ x9 = b[1];
+ xA = b[2];
+ xB = b[3];
+ b = unscramble(xCxDxExF);
+ xC = b[0];
+ xD = b[1];
+ xE = b[2];
+ xF = b[3];
+
+ z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8];
+ b = unscramble(z0z1z2z3);
+ z0 = b[0];
+ z1 = b[1];
+ z2 = b[2];
+ z3 = b[3];
+ z4z5z6z7 = x8x9xAxB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA];
+ b = unscramble(z4z5z6z7);
+ z4 = b[0];
+ z5 = b[1];
+ z6 = b[2];
+ z7 = b[3];
+ z8z9zAzB = xCxDxExF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9];
+ b = unscramble(z8z9zAzB);
+ z8 = b[0];
+ z9 = b[1];
+ zA = b[2];
+ zB = b[3];
+ zCzDzEzF = x4x5x6x7 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB];
+ b = unscramble(zCzDzEzF);
+ zC = b[0];
+ zD = b[1];
+ zE = b[2];
+ zF = b[3];
+
+ result.Km0 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2];
+ result.Km1 = S5[zA] ^ S6[zB] ^ S7[z5] ^ S8[z4] ^ S6[z6];
+ result.Km2 = S5[zC] ^ S6[zD] ^ S7[z3] ^ S8[z2] ^ S7[z9];
+ result.Km3 = S5[zE] ^ S6[zF] ^ S7[z1] ^ S8[z0] ^ S8[zC];
+
+ x0x1x2x3 = z8z9zAzB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0];
+ b = unscramble(x0x1x2x3);
+ x0 = b[0];
+ x1 = b[1];
+ x2 = b[2];
+ x3 = b[3];
+ x4x5x6x7 = z0z1z2z3 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2];
+ b = unscramble(x4x5x6x7);
+ x4 = b[0];
+ x5 = b[1];
+ x6 = b[2];
+ x7 = b[3];
+ x8x9xAxB = z4z5z6z7 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1];
+ b = unscramble(x8x9xAxB);
+ x8 = b[0];
+ x9 = b[1];
+ xA = b[2];
+ xB = b[3];
+ xCxDxExF = zCzDzEzF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3];
+ b = unscramble(xCxDxExF);
+ xC = b[0];
+ xD = b[1];
+ xE = b[2];
+ xF = b[3];
+
+ result.Km4 = S5[x3] ^ S6[x2] ^ S7[xC] ^ S8[xD] ^ S5[x8];
+ result.Km5 = S5[x1] ^ S6[x0] ^ S7[xE] ^ S8[xF] ^ S6[xD];
+ result.Km6 = S5[x7] ^ S6[x6] ^ S7[x8] ^ S8[x9] ^ S7[x3];
+ result.Km7 = S5[x5] ^ S6[x4] ^ S7[xA] ^ S8[xB] ^ S8[x7];
+
+ z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8];
+ b = unscramble(z0z1z2z3);
+ z0 = b[0];
+ z1 = b[1];
+ z2 = b[2];
+ z3 = b[3];
+ z4z5z6z7 = x8x9xAxB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA];
+ b = unscramble(z4z5z6z7);
+ z4 = b[0];
+ z5 = b[1];
+ z6 = b[2];
+ z7 = b[3];
+ z8z9zAzB = xCxDxExF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9];
+ b = unscramble(z8z9zAzB);
+ z8 = b[0];
+ z9 = b[1];
+ zA = b[2];
+ zB = b[3];
+ zCzDzEzF = x4x5x6x7 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB];
+ b = unscramble(zCzDzEzF);
+ zC = b[0];
+ zD = b[1];
+ zE = b[2];
+ zF = b[3];
+
+ result.Km8 = S5[z3] ^ S6[z2] ^ S7[zC] ^ S8[zD] ^ S5[z9];
+ result.Km9 = S5[z1] ^ S6[z0] ^ S7[zE] ^ S8[zF] ^ S6[zC];
+ result.Km10 = S5[z7] ^ S6[z6] ^ S7[z8] ^ S8[z9] ^ S7[z2];
+ result.Km11 = S5[z5] ^ S6[z4] ^ S7[zA] ^ S8[zB] ^ S8[z6];
+
+ x0x1x2x3 = z8z9zAzB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0];
+ b = unscramble(x0x1x2x3);
+ x0 = b[0];
+ x1 = b[1];
+ x2 = b[2];
+ x3 = b[3];
+ x4x5x6x7 = z0z1z2z3 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2];
+ b = unscramble(x4x5x6x7);
+ x4 = b[0];
+ x5 = b[1];
+ x6 = b[2];
+ x7 = b[3];
+ x8x9xAxB = z4z5z6z7 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1];
+ b = unscramble(x8x9xAxB);
+ x8 = b[0];
+ x9 = b[1];
+ xA = b[2];
+ xB = b[3];
+ xCxDxExF = zCzDzEzF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3];
+ b = unscramble(xCxDxExF);
+ xC = b[0];
+ xD = b[1];
+ xE = b[2];
+ xF = b[3];
+
+ result.Km12 = S5[x8] ^ S6[x9] ^ S7[x7] ^ S8[x6] ^ S5[x3];
+ result.Km13 = S5[xA] ^ S6[xB] ^ S7[x5] ^ S8[x4] ^ S6[x7];
+ result.Km14 = S5[xC] ^ S6[xD] ^ S7[x3] ^ S8[x2] ^ S7[x8];
+ result.Km15 = S5[xE] ^ S6[xF] ^ S7[x1] ^ S8[x0] ^ S8[xD];
+
+ // The remaining half is identical to what is given above, carrying on
+ // from the last created x0..xF to generate keys K17 - K32. These keys
+ // will be used as the 'rotation' keys and as such only the five least
+ // significant bits are to be considered.
+
+ z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8];
+ b = unscramble(z0z1z2z3);
+ z0 = b[0];
+ z1 = b[1];
+ z2 = b[2];
+ z3 = b[3];
+ z4z5z6z7 = x8x9xAxB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA];
+ b = unscramble(z4z5z6z7);
+ z4 = b[0];
+ z5 = b[1];
+ z6 = b[2];
+ z7 = b[3];
+ z8z9zAzB = xCxDxExF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9];
+ b = unscramble(z8z9zAzB);
+ z8 = b[0];
+ z9 = b[1];
+ zA = b[2];
+ zB = b[3];
+ zCzDzEzF = x4x5x6x7 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB];
+ b = unscramble(zCzDzEzF);
+ zC = b[0];
+ zD = b[1];
+ zE = b[2];
+ zF = b[3];
+
+ result.Kr0 = (S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]) & 0x1F;
+ result.Kr1 = (S5[zA] ^ S6[zB] ^ S7[z5] ^ S8[z4] ^ S6[z6]) & 0x1F;
+ result.Kr2 = (S5[zC] ^ S6[zD] ^ S7[z3] ^ S8[z2] ^ S7[z9]) & 0x1F;
+ result.Kr3 = (S5[zE] ^ S6[zF] ^ S7[z1] ^ S8[z0] ^ S8[zC]) & 0x1F;
+
+ x0x1x2x3 = z8z9zAzB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0];
+ b = unscramble(x0x1x2x3);
+ x0 = b[0];
+ x1 = b[1];
+ x2 = b[2];
+ x3 = b[3];
+ x4x5x6x7 = z0z1z2z3 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2];
+ b = unscramble(x4x5x6x7);
+ x4 = b[0];
+ x5 = b[1];
+ x6 = b[2];
+ x7 = b[3];
+ x8x9xAxB = z4z5z6z7 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1];
+ b = unscramble(x8x9xAxB);
+ x8 = b[0];
+ x9 = b[1];
+ xA = b[2];
+ xB = b[3];
+ xCxDxExF = zCzDzEzF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3];
+ b = unscramble(xCxDxExF);
+ xC = b[0];
+ xD = b[1];
+ xE = b[2];
+ xF = b[3];
+
+ result.Kr4 = (S5[x3] ^ S6[x2] ^ S7[xC] ^ S8[xD] ^ S5[x8]) & 0x1F;
+ result.Kr5 = (S5[x1] ^ S6[x0] ^ S7[xE] ^ S8[xF] ^ S6[xD]) & 0x1F;
+ result.Kr6 = (S5[x7] ^ S6[x6] ^ S7[x8] ^ S8[x9] ^ S7[x3]) & 0x1F;
+ result.Kr7 = (S5[x5] ^ S6[x4] ^ S7[xA] ^ S8[xB] ^ S8[x7]) & 0x1F;
+
+ z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8];
+ b = unscramble(z0z1z2z3);
+ z0 = b[0];
+ z1 = b[1];
+ z2 = b[2];
+ z3 = b[3];
+ z4z5z6z7 = x8x9xAxB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA];
+ b = unscramble(z4z5z6z7);
+ z4 = b[0];
+ z5 = b[1];
+ z6 = b[2];
+ z7 = b[3];
+ z8z9zAzB = xCxDxExF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9];
+ b = unscramble(z8z9zAzB);
+ z8 = b[0];
+ z9 = b[1];
+ zA = b[2];
+ zB = b[3];
+ zCzDzEzF = x4x5x6x7 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB];
+ b = unscramble(zCzDzEzF);
+ zC = b[0];
+ zD = b[1];
+ zE = b[2];
+ zF = b[3];
+
+ result.Kr8 = (S5[z3] ^ S6[z2] ^ S7[zC] ^ S8[zD] ^ S5[z9]) & 0x1F;
+ result.Kr9 = (S5[z1] ^ S6[z0] ^ S7[zE] ^ S8[zF] ^ S6[zC]) & 0x1F;
+ result.Kr10 = (S5[z7] ^ S6[z6] ^ S7[z8] ^ S8[z9] ^ S7[z2]) & 0x1F;
+ result.Kr11 = (S5[z5] ^ S6[z4] ^ S7[zA] ^ S8[zB] ^ S8[z6]) & 0x1F;
+
+ x0x1x2x3 = z8z9zAzB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0];
+ b = unscramble(x0x1x2x3);
+ x0 = b[0];
+ x1 = b[1];
+ x2 = b[2];
+ x3 = b[3];
+ x4x5x6x7 = z0z1z2z3 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2];
+ b = unscramble(x4x5x6x7);
+ x4 = b[0];
+ x5 = b[1];
+ x6 = b[2];
+ x7 = b[3];
+ x8x9xAxB = z4z5z6z7 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1];
+ b = unscramble(x8x9xAxB);
+ x8 = b[0];
+ x9 = b[1];
+ xA = b[2];
+ xB = b[3];
+ xCxDxExF = zCzDzEzF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3];
+ b = unscramble(xCxDxExF);
+ xC = b[0];
+ xD = b[1];
+ xE = b[2];
+ xF = b[3];
+
+ result.Kr12 = (S5[x8] ^ S6[x9] ^ S7[x7] ^ S8[x6] ^ S5[x3]) & 0x1F;
+ result.Kr13 = (S5[xA] ^ S6[xB] ^ S7[x5] ^ S8[x4] ^ S6[x7]) & 0x1F;
+ result.Kr14 = (S5[xC] ^ S6[xD] ^ S7[x3] ^ S8[x2] ^ S7[x8]) & 0x1F;
+ result.Kr15 = (S5[xE] ^ S6[xF] ^ S7[x1] ^ S8[x0] ^ S8[xD]) & 0x1F;
+
+ return result;
+ }
+
+ /**
+ * <p>The full encryption algorithm is given in the following four steps.</p>
+ *
+ * <pre>
+ * INPUT: plaintext m1...m64; key K = k1...k128.
+ * OUTPUT: ciphertext c1...c64.
+ * </pre>
+ *
+ * <ol>
+ * <li>(key schedule) Compute 16 pairs of subkeys {Kmi, Kri} from a user
+ * key (see makeKey() method).</li>
+ * <li>(L0,R0) <-- (m1...m64). (Split the plaintext into left and right
+ * 32-bit halves L0 = m1...m32 and R0 = m33...m64.).</li>
+ * <li>(16 rounds) for i from 1 to 16, compute Li and Ri as follows:
+ * <ul>
+ * <li>Li = Ri-1;</li>
+ * <li>Ri = Li-1 ^ F(Ri-1,Kmi,Kri), where F is defined in method F() --
+ * f is of Type 1, Type 2, or Type 3, depending on i, and ^ being the
+ * bitwise XOR function.</li>
+ * </ul>
+ * <li>c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and
+ * concatenate to form the ciphertext.)</li>
+ * </ol>
+ *
+ * <p>Decryption is identical to the encryption algorithm given above, except
+ * that the rounds (and therefore the subkey pairs) are used in reverse order
+ * to compute (L0,R0) from (R16,L16).</p>
+ *
+ * <p>Looking at the iterations/rounds in pairs we have:</p>
+ *
+ * <pre>
+ * (1a) Li = Ri-1;
+ * (1b) Ri = Li-1 ^ Fi(Ri-1);
+ * (2a) Li+1 = Ri;
+ * (2b) Ri+1 = Li ^ Fi+1(Ri);
+ * </pre>
+ * which by substituting (2a) in (2b) becomes
+ * <pre>
+ * (2c) Ri+1 = Li ^ Fi+1(Li+1);
+ * </pre>
+ * by substituting (1b) in (2a) and (1a) in (2c), we get:
+ * <pre>
+ * (3a) Li+1 = Li-1 ^ Fi(Ri-1);
+ * (3b) Ri+1 = Ri-1 ^ Fi+1(Li+1);
+ * </pre>
+ * Using only one couple of variables L and R, initialised to L0 and R0
+ * respectively, the assignments for each pair of rounds become:
+ * <pre>
+ * (4a) L ^= Fi(R);
+ * (4b) R ^= Fi+1(L);
+ * </pre>
+ *
+ * @param in contains the plain-text 64-bit block.
+ * @param i start index within input where data is considered.
+ * @param out will contain the cipher-text block.
+ * @param j index in out where cipher-text starts.
+ * @param k the session key object.
+ * @param bs the desired block size.
+ */
+ public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+ Cast5Key K = (Cast5Key) k;
+
+ int L = (in[i++] & 0xFF) << 24 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 8 | in[i++] & 0xFF;
+ int R = (in[i++] & 0xFF) << 24 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 8 | in[i] & 0xFF;
+
+ L ^= f1(R, K.Km0, K.Kr0);
+ R ^= f2(L, K.Km1, K.Kr1); // round 2
+ L ^= f3(R, K.Km2, K.Kr2);
+ R ^= f1(L, K.Km3, K.Kr3); // round 4
+ L ^= f2(R, K.Km4, K.Kr4);
+ R ^= f3(L, K.Km5, K.Kr5); // round 6
+ L ^= f1(R, K.Km6, K.Kr6);
+ R ^= f2(L, K.Km7, K.Kr7); // round 8
+ L ^= f3(R, K.Km8, K.Kr8);
+ R ^= f1(L, K.Km9, K.Kr9); // round 10
+ L ^= f2(R, K.Km10, K.Kr10);
+ R ^= f3(L, K.Km11, K.Kr11); // round 12
+ if (K.rounds == _16_ROUNDS)
+ {
+ L ^= f1(R, K.Km12, K.Kr12);
+ R ^= f2(L, K.Km13, K.Kr13); // round 14
+ L ^= f3(R, K.Km14, K.Kr14);
+ R ^= f1(L, K.Km15, K.Kr15); // round 16
+ }
+
+ out[j++] = (byte) (R >>> 24);
+ out[j++] = (byte) (R >>> 16);
+ out[j++] = (byte) (R >>> 8);
+ out[j++] = (byte) R;
+ out[j++] = (byte) (L >>> 24);
+ out[j++] = (byte) (L >>> 16);
+ out[j++] = (byte) (L >>> 8);
+ out[j] = (byte) L;
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+ Cast5Key K = (Cast5Key) k;
+
+ int L = (in[i++] & 0xFF) << 24 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 8 | in[i++] & 0xFF;
+ int R = (in[i++] & 0xFF) << 24 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 8 | in[i] & 0xFF;
+
+ if (K.rounds == _16_ROUNDS)
+ {
+ L ^= f1(R, K.Km15, K.Kr15);
+ R ^= f3(L, K.Km14, K.Kr14);
+ L ^= f2(R, K.Km13, K.Kr13);
+ R ^= f1(L, K.Km12, K.Kr12);
+ }
+ L ^= f3(R, K.Km11, K.Kr11);
+ R ^= f2(L, K.Km10, K.Kr10);
+ L ^= f1(R, K.Km9, K.Kr9);
+ R ^= f3(L, K.Km8, K.Kr8);
+ L ^= f2(R, K.Km7, K.Kr7);
+ R ^= f1(L, K.Km6, K.Kr6);
+ L ^= f3(R, K.Km5, K.Kr5);
+ R ^= f2(L, K.Km4, K.Kr4);
+ L ^= f1(R, K.Km3, K.Kr3);
+ R ^= f3(L, K.Km2, K.Kr2);
+ L ^= f2(R, K.Km1, K.Kr1);
+ R ^= f1(L, K.Km0, K.Kr0);
+
+ out[j++] = (byte) (R >>> 24);
+ out[j++] = (byte) (R >>> 16);
+ out[j++] = (byte) (R >>> 8);
+ out[j++] = (byte) R;
+ out[j++] = (byte) (L >>> 24);
+ out[j++] = (byte) (L >>> 16);
+ out[j++] = (byte) (L >>> 8);
+ out[j] = (byte) L;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ boolean result = super.selfTest(); // do symmetry tests
+ if (result)
+ {
+ result = testKat(KAT_KEY, KAT_CT, KAT_PT);
+ }
+ valid = new Boolean(result);
+ }
+ return valid.booleanValue();
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ private final int f1(int I, int m, int r)
+ {
+ I = m + I;
+ I = I << r | I >>> (32 - r);
+ return (((S1[(I >>> 24) & 0xFF]) ^ S2[(I >>> 16) & 0xFF]) - S3[(I >>> 8) & 0xFF])
+ + S4[I & 0xFF];
+ }
+
+ private final int f2(int I, int m, int r)
+ {
+ I = m ^ I;
+ I = I << r | I >>> (32 - r);
+ return (((S1[(I >>> 24) & 0xFF]) - S2[(I >>> 16) & 0xFF]) + S3[(I >>> 8) & 0xFF])
+ ^ S4[I & 0xFF];
+ }
+
+ private final int f3(int I, int m, int r)
+ {
+ I = m - I;
+ I = I << r | I >>> (32 - r);
+ return (((S1[(I >>> 24) & 0xFF]) + S2[(I >>> 16) & 0xFF]) ^ S3[(I >>> 8) & 0xFF])
+ - S4[I & 0xFF];
+ }
+
+ // Inner class(es)
+ // =========================================================================
+
+ /** An opaque CAST5 key object. */
+ private class Cast5Key
+ {
+ int rounds;
+
+ /** Masking session keys. */
+ int Km0, Km1, Km2, Km3, Km4, Km5, Km6, Km7, Km8, Km9, Km10, Km11, Km12,
+ Km13, Km14, Km15;
+
+ /** Rotation session keys. */
+ int Kr0, Kr1, Kr2, Kr3, Kr4, Kr5, Kr6, Kr7, Kr8, Kr9, Kr10, Kr11, Kr12,
+ Kr13, Kr14, Kr15;
+ }
+}
diff --git a/gnu/javax/crypto/cipher/CipherFactory.java b/gnu/javax/crypto/cipher/CipherFactory.java
new file mode 100644
index 000000000..082bfb8fa
--- /dev/null
+++ b/gnu/javax/crypto/cipher/CipherFactory.java
@@ -0,0 +1,169 @@
+/* CipherFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>A <i>Factory</i> to instantiate symmetric block cipher instances.</p>
+ */
+public class CipherFactory implements Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private CipherFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a block cipher given its name.</p>
+ *
+ * @param name the case-insensitive name of the symmetric-key block cipher
+ * algorithm.
+ * @return an instance of the designated cipher algorithm, or
+ * <code>null</code> if none is found.
+ * @exception InternalError if the implementation does not pass its
+ * self-test.
+ */
+ public static final IBlockCipher getInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ IBlockCipher result = null;
+ if (name.equalsIgnoreCase(ANUBIS_CIPHER))
+ {
+ result = new Anubis();
+ }
+ else if (name.equalsIgnoreCase(BLOWFISH_CIPHER))
+ {
+ result = new Blowfish();
+ }
+ else if (name.equalsIgnoreCase(DES_CIPHER))
+ {
+ result = new DES();
+ }
+ else if (name.equalsIgnoreCase(KHAZAD_CIPHER))
+ {
+ result = new Khazad();
+ }
+ else if (name.equalsIgnoreCase(RIJNDAEL_CIPHER)
+ || name.equalsIgnoreCase(AES_CIPHER))
+ {
+ result = new Rijndael();
+ }
+ else if (name.equalsIgnoreCase(SERPENT_CIPHER))
+ {
+ result = new Serpent();
+ }
+ else if (name.equalsIgnoreCase(SQUARE_CIPHER))
+ {
+ result = new Square();
+ }
+ else if (name.equalsIgnoreCase(TRIPLEDES_CIPHER)
+ || name.equalsIgnoreCase(DESEDE_CIPHER))
+ {
+ result = new TripleDES();
+ }
+ else if (name.equalsIgnoreCase(TWOFISH_CIPHER))
+ {
+ result = new Twofish();
+ }
+ else if (name.equalsIgnoreCase(CAST5_CIPHER)
+ || (name.equalsIgnoreCase(CAST128_CIPHER) || (name.equalsIgnoreCase(CAST_128_CIPHER))))
+ {
+ result = new Cast5();
+ }
+ else if (name.equalsIgnoreCase(NULL_CIPHER))
+ {
+ result = new NullCipher();
+ }
+
+ if (result != null && !result.selfTest())
+ {
+ throw new InternalError(result.name());
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of symmetric key block cipher implementation
+ * names supported by this <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of block cipher names (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(ANUBIS_CIPHER);
+ hs.add(BLOWFISH_CIPHER);
+ hs.add(DES_CIPHER);
+ hs.add(KHAZAD_CIPHER);
+ hs.add(RIJNDAEL_CIPHER);
+ hs.add(SERPENT_CIPHER);
+ hs.add(SQUARE_CIPHER);
+ hs.add(TRIPLEDES_CIPHER);
+ hs.add(TWOFISH_CIPHER);
+ hs.add(CAST5_CIPHER);
+ hs.add(NULL_CIPHER);
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/DES.java b/gnu/javax/crypto/cipher/DES.java
new file mode 100644
index 000000000..8b7627cea
--- /dev/null
+++ b/gnu/javax/crypto/cipher/DES.java
@@ -0,0 +1,894 @@
+/* DES.java --
+ Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.Properties;
+import gnu.java.security.util.Util;
+
+import java.security.InvalidKeyException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>The Data Encryption Standard. DES is a 64-bit block cipher with a 56-bit
+ * key, developed by IBM in the 1970's for the standardization process begun by
+ * the National Bureau of Standards (now NIST).</p>
+ *
+ * <p>New applications should not use DES except for compatibility.</p>
+ *
+ * <p>This version is based upon the description and sample implementation in
+ * [1].</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms, and
+ * Source Code in C, Second Edition</i>. (1996 John Wiley and Sons) ISBN
+ * 0-471-11709-9. Pages 265--301, 623--632.</li>
+ * </ol>
+ */
+public class DES extends BaseCipher
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** DES operates on 64 bit blocks. */
+ public static final int BLOCK_SIZE = 8;
+
+ /** DES uses 56 bits of a 64 bit parity-adjusted key. */
+ public static final int KEY_SIZE = 8;
+
+ // S-Boxes 1 through 8.
+ private static final int[] SP1 = new int[] { 0x01010400, 0x00000000,
+ 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404,
+ 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400,
+ 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004,
+ 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400,
+ 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000,
+ 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004,
+ 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404,
+ 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404,
+ 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000,
+ 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000,
+ 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004,
+ 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004,
+ 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404,
+ 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400,
+ 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400,
+ 0x00000000, 0x01010004 };
+
+ private static final int[] SP2 = new int[] { 0x80108020, 0x80008000,
+ 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020,
+ 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020,
+ 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000,
+ 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020,
+ 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000,
+ 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020,
+ 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000,
+ 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020,
+ 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000,
+ 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000,
+ 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020,
+ 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000,
+ 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020,
+ 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000,
+ 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020,
+ 0x80108020, 0x00108000 };
+
+ private static final int[] SP3 = new int[] { 0x00000208, 0x08020200,
+ 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000,
+ 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008,
+ 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008,
+ 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008,
+ 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000,
+ 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200,
+ 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208,
+ 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000,
+ 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200,
+ 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008,
+ 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200,
+ 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000,
+ 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208,
+ 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208,
+ 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008,
+ 0x08020008, 0x00020200 };
+
+ private static final int[] SP4 = new int[] { 0x00802001, 0x00002081,
+ 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081,
+ 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000,
+ 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000,
+ 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000,
+ 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000,
+ 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001,
+ 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080,
+ 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001,
+ 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000,
+ 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080,
+ 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081,
+ 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081,
+ 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001,
+ 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080,
+ 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000,
+ 0x00002000, 0x00802080 };
+
+ private static final int[] SP5 = new int[] { 0x00000100, 0x02080100,
+ 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100,
+ 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000,
+ 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000,
+ 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000,
+ 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100,
+ 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100,
+ 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000,
+ 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100,
+ 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000,
+ 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000,
+ 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100,
+ 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100,
+ 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000,
+ 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100,
+ 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000,
+ 0x02080100, 0x40000100 };
+
+ private static final int[] SP6 = new int[] { 0x20000010, 0x20400000,
+ 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010,
+ 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010,
+ 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000,
+ 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010,
+ 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010,
+ 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000,
+ 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000,
+ 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010,
+ 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000,
+ 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000,
+ 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010,
+ 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000,
+ 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000,
+ 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010,
+ 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000,
+ 0x00400010, 0x20004010 };
+
+ private static final int[] SP7 = new int[] { 0x00200000, 0x04200002,
+ 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802,
+ 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000,
+ 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000,
+ 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802,
+ 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000,
+ 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800,
+ 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002,
+ 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800,
+ 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002,
+ 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000,
+ 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802,
+ 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002,
+ 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000,
+ 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802,
+ 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800,
+ 0x00000800, 0x00200002 };
+
+ private static final int[] SP8 = new int[] { 0x10001040, 0x00001000,
+ 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040,
+ 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000,
+ 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040,
+ 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040,
+ 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040,
+ 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000,
+ 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000,
+ 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000,
+ 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040,
+ 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040,
+ 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000,
+ 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040,
+ 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000,
+ 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000,
+ 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040,
+ 0x10000000, 0x10041000 };
+
+ /**
+ * Constants that help in determining whether or not a byte array is parity
+ * adjusted.
+ */
+ private static final byte[] PARITY = { 8, 1, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0, 8,
+ 0, 2, 8, 0, 8, 8, 0, 8, 0, 0, 8, 8, 0,
+ 0, 8, 0, 8, 8, 3, 0, 8, 8, 0, 8, 0, 0,
+ 8, 8, 0, 0, 8, 0, 8, 8, 0, 8, 0, 0, 8,
+ 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8, 0,
+ 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8,
+ 8, 0, 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8,
+ 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0,
+ 0, 8, 8, 0, 8, 0, 0, 8, 0, 8, 8, 0, 8,
+ 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, 0, 8,
+ 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8,
+ 0, 8, 0, 0, 8, 0, 8, 8, 0, 0, 8, 8, 0,
+ 8, 0, 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, 0,
+ 8, 8, 0, 8, 0, 0, 8, 0, 8, 8, 0, 8, 0,
+ 0, 8, 8, 0, 0, 8, 0, 8, 8, 0, 8, 0, 0,
+ 8, 0, 8, 8, 0, 0, 8, 8, 0, 8, 0, 0, 8,
+ 0, 8, 8, 0, 8, 0, 0, 8, 8, 0, 0, 8, 0,
+ 8, 8, 0, 4, 8, 8, 0, 8, 0, 0, 8, 8, 0,
+ 0, 8, 0, 8, 8, 0, 8, 5, 0, 8, 0, 8, 8,
+ 0, 0, 8, 8, 0, 8, 0, 6, 8 };
+
+ // Key schedule constants.
+
+ private static final byte[] ROTARS = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19,
+ 21, 23, 25, 27, 28 };
+
+ private static final byte[] PC1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41,
+ 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30,
+ 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5,
+ 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11,
+ 3 };
+
+ private static final byte[] PC2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20,
+ 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19,
+ 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50,
+ 44, 32, 47, 43, 48, 38, 55, 33, 52, 45,
+ 41, 49, 35, 28, 31 };
+
+ /**
+ * Weak keys (parity adjusted): If all the bits in each half are either 0
+ * or 1, then the key used for any cycle of the algorithm is the same as
+ * all other cycles.
+ */
+ public static final byte[][] WEAK_KEYS = {
+ Util.toBytesFromString("0101010101010101"),
+ Util.toBytesFromString("01010101FEFEFEFE"),
+ Util.toBytesFromString("FEFEFEFE01010101"),
+ Util.toBytesFromString("FEFEFEFEFEFEFEFE") };
+
+ /**
+ * Semi-weak keys (parity adjusted): Some pairs of keys encrypt plain text
+ * to identical cipher text. In other words, one key in the pair can decrypt
+ * messages that were encrypted with the other key. These keys are called
+ * semi-weak keys. This occurs because instead of 16 different sub-keys being
+ * generated, these semi-weak keys produce only two different sub-keys.
+ */
+ public static final byte[][] SEMIWEAK_KEYS = {
+ Util.toBytesFromString("01FE01FE01FE01FE"),
+ Util.toBytesFromString("FE01FE01FE01FE01"),
+ Util.toBytesFromString("1FE01FE00EF10EF1"),
+ Util.toBytesFromString("E01FE01FF10EF10E"),
+ Util.toBytesFromString("01E001E001F101F1"),
+ Util.toBytesFromString("E001E001F101F101"),
+ Util.toBytesFromString("1FFE1FFE0EFE0EFE"),
+ Util.toBytesFromString("FE1FFE1FFE0EFE0E"),
+ Util.toBytesFromString("011F011F010E010E"),
+ Util.toBytesFromString("1F011F010E010E01"),
+ Util.toBytesFromString("E0FEE0FEF1FEF1FE"),
+ Util.toBytesFromString("FEE0FEE0FEF1FEF1") };
+
+ /** Possible weak keys (parity adjusted) --produce 4 instead of 16 subkeys. */
+ public static final byte[][] POSSIBLE_WEAK_KEYS = {
+ Util.toBytesFromString("1F1F01010E0E0101"),
+ Util.toBytesFromString("011F1F01010E0E01"),
+ Util.toBytesFromString("1F01011F0E01010E"),
+ Util.toBytesFromString("01011F1F01010E0E"),
+ Util.toBytesFromString("E0E00101F1F10101"),
+ Util.toBytesFromString("FEFE0101FEFE0101"),
+ Util.toBytesFromString("FEE01F01FEF10E01"),
+ Util.toBytesFromString("E0FE1F01F1FE0E01"),
+ Util.toBytesFromString("FEE0011FFEF1010E"),
+ Util.toBytesFromString("E0FE011FF1FE010E"),
+ Util.toBytesFromString("E0E01F1FF1F10E0E"),
+ Util.toBytesFromString("FEFE1F1FFEFE0E0E"),
+ Util.toBytesFromString("1F1F01010E0E0101"),
+ Util.toBytesFromString("011F1F01010E0E01"),
+ Util.toBytesFromString("1F01011F0E01010E"),
+ Util.toBytesFromString("01011F1F01010E0E"),
+ Util.toBytesFromString("01E0E00101F1F101"),
+ Util.toBytesFromString("1FFEE0010EFEF001"),
+ Util.toBytesFromString("1FE0FE010EF1FE01"),
+ Util.toBytesFromString("01FEFE0101FEFE01"),
+ Util.toBytesFromString("1FE0E01F0EF1F10E"),
+ Util.toBytesFromString("01FEE01F01FEF10E"),
+ Util.toBytesFromString("01E0FE1F01F1FE0E"),
+ Util.toBytesFromString("1FFEFE1F0EFEFE0E"),
+
+ Util.toBytesFromString("E00101E0F10101F1"),
+ Util.toBytesFromString("FE1F01E0FE0E0EF1"),
+ Util.toBytesFromString("FE011FE0FE010EF1"),
+ Util.toBytesFromString("E01F1FE0F10E0EF1"),
+ Util.toBytesFromString("FE0101FEFE0101FE"),
+ Util.toBytesFromString("E01F01FEF10E01FE"),
+ Util.toBytesFromString("E0011FFEF1010EFE"),
+ Util.toBytesFromString("FE1F1FFEFE0E0EFE"),
+ Util.toBytesFromString("1FFE01E00EFE01F1"),
+ Util.toBytesFromString("01FE1FE001FE0EF1"),
+ Util.toBytesFromString("1FE001FE0EF101FE"),
+ Util.toBytesFromString("01E01FFE01F10EFE"),
+ Util.toBytesFromString("0101E0E00101F1F1"),
+ Util.toBytesFromString("1F1FE0E00E0EF1F1"),
+ Util.toBytesFromString("1F01FEE00E01FEF1"),
+ Util.toBytesFromString("011FFEE0010EFEF1"),
+ Util.toBytesFromString("1F01E0FE0E01F1FE"),
+ Util.toBytesFromString("011FE0FE010EF1FE"),
+ Util.toBytesFromString("0101FEFE0001FEFE"),
+ Util.toBytesFromString("1F1FFEFE0E0EFEFE"),
+ Util.toBytesFromString("FEFEE0E0FEFEF1F1"),
+ Util.toBytesFromString("E0FEFEE0F1FEFEF1"),
+ Util.toBytesFromString("FEE0E0FEFEF1F1FE"),
+ Util.toBytesFromString("E0E0FEFEF1F1FEFE") };
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Default 0-argument constructor. */
+ public DES()
+ {
+ super(Registry.DES_CIPHER, BLOCK_SIZE, KEY_SIZE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Adjust the parity for a raw key array. This essentially means that each
+ * byte in the array will have an odd number of '1' bits (the last bit in
+ * each byte is unused.</p>
+ *
+ * @param kb The key array, to be parity-adjusted.
+ * @param offset The starting index into the key bytes.
+ */
+ public static void adjustParity(byte[] kb, int offset)
+ {
+ for (int i = offset; i < KEY_SIZE; i++)
+ {
+ kb[i] ^= (PARITY[kb[i] & 0xff] == 8) ? 1 : 0;
+ }
+ }
+
+ /**
+ * <p>Test if a byte array, which must be at least 8 bytes long, is parity
+ * adjusted.</p>
+ *
+ * @param kb The key bytes.
+ * @param offset The starting index into the key bytes.
+ * @return <code>true</code> if the first 8 bytes of <i>kb</i> have been
+ * parity adjusted. <code>false</code> otherwise.
+ */
+ public static boolean isParityAdjusted(byte[] kb, int offset)
+ {
+ int w = 0x88888888;
+ int n = PARITY[kb[offset + 0] & 0xff];
+ n <<= 4;
+ n |= PARITY[kb[offset + 1] & 0xff];
+ n <<= 4;
+ n |= PARITY[kb[offset + 2] & 0xff];
+ n <<= 4;
+ n |= PARITY[kb[offset + 3] & 0xff];
+ n <<= 4;
+ n |= PARITY[kb[offset + 4] & 0xff];
+ n <<= 4;
+ n |= PARITY[kb[offset + 5] & 0xff];
+ n <<= 4;
+ n |= PARITY[kb[offset + 6] & 0xff];
+ n <<= 4;
+ n |= PARITY[kb[offset + 7] & 0xff];
+ return (n & w) == 0;
+ }
+
+ /**
+ * <p>Test if a key is a weak key.</p>
+ *
+ * @param kb The key to test.
+ * @return <code>true</code> if the key is weak.
+ */
+ public static boolean isWeak(byte[] kb)
+ {
+ // return Arrays.equals(kb, WEAK_KEYS[0]) || Arrays.equals(kb, WEAK_KEYS[1])
+ // || Arrays.equals(kb, WEAK_KEYS[2]) || Arrays.equals(kb, WEAK_KEYS[3])
+ // || Arrays.equals(kb, WEAK_KEYS[4]) || Arrays.equals(kb, WEAK_KEYS[5])
+ // || Arrays.equals(kb, WEAK_KEYS[6]) || Arrays.equals(kb, WEAK_KEYS[7]);
+ for (int i = 0; i < WEAK_KEYS.length; i++)
+ {
+ if (Arrays.equals(WEAK_KEYS[i], kb))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * <p>Test if a key is a semi-weak key.</p>
+ *
+ * @param kb The key to test.
+ * @return <code>true</code> if this key is semi-weak.
+ */
+ public static boolean isSemiWeak(byte[] kb)
+ {
+ // return Arrays.equals(kb, SEMIWEAK_KEYS[0])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[1])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[2])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[3])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[4])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[5])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[6])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[7])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[8])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[9])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[10])
+ // || Arrays.equals(kb, SEMIWEAK_KEYS[11]);
+ for (int i = 0; i < SEMIWEAK_KEYS.length; i++)
+ {
+ if (Arrays.equals(SEMIWEAK_KEYS[i], kb))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * <p>Test if the designated byte array represents a possibly weak key.</p>
+ *
+ * @param kb the byte array to test.
+ * @return <code>true</code> if <code>kb</code>represents a possibly weak key.
+ * Returns <code>false</code> otherwise.
+ */
+ public static boolean isPossibleWeak(byte[] kb)
+ {
+ for (int i = 0; i < POSSIBLE_WEAK_KEYS.length; i++)
+ {
+ if (Arrays.equals(POSSIBLE_WEAK_KEYS[i], kb))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * <p>The core DES function. This is used for both encryption and decryption,
+ * the only difference being the key.</p>
+ *
+ * @param in The input bytes.
+ * @param i The starting offset into the input bytes.
+ * @param out The output bytes.
+ * @param o The starting offset into the output bytes.
+ * @param key The working key.
+ */
+ private static void desFunc(byte[] in, int i, byte[] out, int o, int[] key)
+ {
+ int right, left, work;
+
+ // Load.
+ left = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16
+ | (in[i++] & 0xff) << 8 | in[i++] & 0xff;
+ right = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16
+ | (in[i++] & 0xff) << 8 | in[i] & 0xff;
+
+ // Initial permutation.
+ work = ((left >>> 4) ^ right) & 0x0F0F0F0F;
+ left ^= work << 4;
+ right ^= work;
+
+ work = ((left >>> 16) ^ right) & 0x0000FFFF;
+ left ^= work << 16;
+ right ^= work;
+
+ work = ((right >>> 2) ^ left) & 0x33333333;
+ right ^= work << 2;
+ left ^= work;
+
+ work = ((right >>> 8) ^ left) & 0x00FF00FF;
+ right ^= work << 8;
+ left ^= work;
+
+ right = ((right << 1) | ((right >>> 31) & 1)) & 0xFFFFFFFF;
+ work = (left ^ right) & 0xAAAAAAAA;
+ left ^= work;
+ right ^= work;
+ left = ((left << 1) | ((left >>> 31) & 1)) & 0xFFFFFFFF;
+
+ int k = 0, t;
+ for (int round = 0; round < 8; round++)
+ {
+ work = right >>> 4 | right << 28;
+ work ^= key[k++];
+ t = SP7[work & 0x3F];
+ work >>>= 8;
+ t |= SP5[work & 0x3F];
+ work >>>= 8;
+ t |= SP3[work & 0x3F];
+ work >>>= 8;
+ t |= SP1[work & 0x3F];
+ work = right ^ key[k++];
+ t |= SP8[work & 0x3F];
+ work >>>= 8;
+ t |= SP6[work & 0x3F];
+ work >>>= 8;
+ t |= SP4[work & 0x3F];
+ work >>>= 8;
+ t |= SP2[work & 0x3F];
+ left ^= t;
+
+ work = left >>> 4 | left << 28;
+ work ^= key[k++];
+ t = SP7[work & 0x3F];
+ work >>>= 8;
+ t |= SP5[work & 0x3F];
+ work >>>= 8;
+ t |= SP3[work & 0x3F];
+ work >>>= 8;
+ t |= SP1[work & 0x3F];
+ work = left ^ key[k++];
+ t |= SP8[work & 0x3F];
+ work >>>= 8;
+ t |= SP6[work & 0x3F];
+ work >>>= 8;
+ t |= SP4[work & 0x3F];
+ work >>>= 8;
+ t |= SP2[work & 0x3F];
+ right ^= t;
+ }
+
+ // The final permutation.
+ right = (right << 31) | (right >>> 1);
+ work = (left ^ right) & 0xAAAAAAAA;
+ left ^= work;
+ right ^= work;
+ left = (left << 31) | (left >>> 1);
+
+ work = ((left >>> 8) ^ right) & 0x00FF00FF;
+ left ^= work << 8;
+ right ^= work;
+
+ work = ((left >>> 2) ^ right) & 0x33333333;
+ left ^= work << 2;
+ right ^= work;
+
+ work = ((right >>> 16) ^ left) & 0x0000FFFF;
+ right ^= work << 16;
+ left ^= work;
+
+ work = ((right >>> 4) ^ left) & 0x0F0F0F0F;
+ right ^= work << 4;
+ left ^= work;
+
+ out[o++] = (byte) (right >>> 24);
+ out[o++] = (byte) (right >>> 16);
+ out[o++] = (byte) (right >>> 8);
+ out[o++] = (byte) right;
+ out[o++] = (byte) (left >>> 24);
+ out[o++] = (byte) (left >>> 16);
+ out[o++] = (byte) (left >>> 8);
+ out[o] = (byte) left;
+ }
+
+ // Instance methods implementing BaseCipher
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new DES();
+ }
+
+ public Iterator blockSizes()
+ {
+ return Collections.singleton(new Integer(BLOCK_SIZE)).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ return Collections.singleton(new Integer(KEY_SIZE)).iterator();
+ }
+
+ public Object makeKey(byte[] kb, int bs) throws InvalidKeyException
+ {
+ if (kb == null || kb.length != KEY_SIZE)
+ throw new InvalidKeyException("DES keys must be 8 bytes long");
+
+ if (Properties.checkForWeakKeys()
+ && (isWeak(kb) || isSemiWeak(kb) || isPossibleWeak(kb)))
+ {
+ throw new WeakKeyException();
+ }
+
+ int i, j, l, m, n;
+ long pc1m = 0, pcr = 0;
+
+ for (i = 0; i < 56; i++)
+ {
+ l = PC1[i];
+ pc1m |= ((kb[l >>> 3] & (0x80 >>> (l & 7))) != 0) ? (1L << (55 - i))
+ : 0;
+ }
+
+ Context ctx = new Context();
+
+ // Encryption key first.
+ for (i = 0; i < 16; i++)
+ {
+ pcr = 0;
+ m = i << 1;
+ n = m + 1;
+ for (j = 0; j < 28; j++)
+ {
+ l = j + ROTARS[i];
+ if (l < 28)
+ pcr |= ((pc1m & 1L << (55 - l)) != 0) ? (1L << (55 - j)) : 0;
+ else
+ pcr |= ((pc1m & 1L << (55 - (l - 28))) != 0) ? (1L << (55 - j))
+ : 0;
+ }
+ for (j = 28; j < 56; j++)
+ {
+ l = j + ROTARS[i];
+ if (l < 56)
+ pcr |= ((pc1m & 1L << (55 - l)) != 0) ? (1L << (55 - j)) : 0;
+ else
+ pcr |= ((pc1m & 1L << (55 - (l - 28))) != 0) ? (1L << (55 - j))
+ : 0;
+ }
+ for (j = 0; j < 24; j++)
+ {
+ if ((pcr & 1L << (55 - PC2[j])) != 0)
+ ctx.ek[m] |= 1 << (23 - j);
+ if ((pcr & 1L << (55 - PC2[j + 24])) != 0)
+ ctx.ek[n] |= 1 << (23 - j);
+ }
+ }
+
+ // The decryption key is the same, but in reversed order.
+ for (i = 0; i < Context.EXPANDED_KEY_SIZE; i += 2)
+ {
+ ctx.dk[30 - i] = ctx.ek[i];
+ ctx.dk[31 - i] = ctx.ek[i + 1];
+ }
+
+ // "Cook" the keys.
+ for (i = 0; i < 32; i += 2)
+ {
+ int x, y;
+
+ x = ctx.ek[i];
+ y = ctx.ek[i + 1];
+
+ ctx.ek[i] = ((x & 0x00FC0000) << 6) | ((x & 0x00000FC0) << 10)
+ | ((y & 0x00FC0000) >>> 10) | ((y & 0x00000FC0) >>> 6);
+ ctx.ek[i + 1] = ((x & 0x0003F000) << 12) | ((x & 0x0000003F) << 16)
+ | ((y & 0x0003F000) >>> 4) | (y & 0x0000003F);
+
+ x = ctx.dk[i];
+ y = ctx.dk[i + 1];
+
+ ctx.dk[i] = ((x & 0x00FC0000) << 6) | ((x & 0x00000FC0) << 10)
+ | ((y & 0x00FC0000) >>> 10) | ((y & 0x00000FC0) >>> 6);
+ ctx.dk[i + 1] = ((x & 0x0003F000) << 12) | ((x & 0x0000003F) << 16)
+ | ((y & 0x0003F000) >>> 4) | (y & 0x0000003F);
+ }
+
+ return ctx;
+ }
+
+ public void encrypt(byte[] in, int i, byte[] out, int o, Object K, int bs)
+ {
+ desFunc(in, i, out, o, ((Context) K).ek);
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int o, Object K, int bs)
+ {
+ desFunc(in, i, out, o, ((Context) K).dk);
+ }
+
+ // Inner classe(s)
+ // =========================================================================
+
+ /**
+ * Simple wrapper class around the session keys. Package-private so TripleDES
+ * can see it.
+ */
+ final class Context
+ {
+
+ // Constants and variables
+ // ----------------------------------------------------------------------
+
+ private static final int EXPANDED_KEY_SIZE = 32;
+
+ /** The encryption key. */
+ int[] ek;
+
+ /** The decryption key. */
+ int[] dk;
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ /** Default 0-arguments constructor. */
+ Context()
+ {
+ ek = new int[EXPANDED_KEY_SIZE];
+ dk = new int[EXPANDED_KEY_SIZE];
+ }
+
+ // Class methods
+ // ----------------------------------------------------------------------
+
+ // Instance methods
+ // ----------------------------------------------------------------------
+
+ byte[] getEncryptionKeyBytes()
+ {
+ return toByteArray(ek);
+ }
+
+ byte[] getDecryptionKeyBytes()
+ {
+ return toByteArray(dk);
+ }
+
+ byte[] toByteArray(int[] k)
+ {
+ byte[] result = new byte[4 * k.length];
+ for (int i = 0, j = 0; i < k.length; i++)
+ {
+ result[j++] = (byte) (k[i] >>> 24);
+ result[j++] = (byte) (k[i] >>> 16);
+ result[j++] = (byte) (k[i] >>> 8);
+ result[j++] = (byte) k[i];
+ }
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/IBlockCipher.java b/gnu/javax/crypto/cipher/IBlockCipher.java
new file mode 100644
index 000000000..238ee280f
--- /dev/null
+++ b/gnu/javax/crypto/cipher/IBlockCipher.java
@@ -0,0 +1,205 @@
+/* IBlockCipher.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import java.security.InvalidKeyException;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * <p>The basic visible methods of any symmetric key block cipher.</p>
+ *
+ * <p>A symmetric key block cipher is a function that maps n-bit plaintext
+ * blocks to n-bit ciphertext blocks; n being the cipher's <i>block size</i>.
+ * This encryption function is parameterised by a k-bit key, and is invertible.
+ * Its inverse is the decryption function.</p>
+ *
+ * <p>Possible initialisation values for an instance of this type are:</p>
+ *
+ * <ul>
+ * <li>The block size in which to operate this block cipher instance. This
+ * value is <b>optional</b>, if unspecified, the block cipher's default
+ * block size shall be used.</li>
+ *
+ * <li>The byte array containing the user supplied key material to use for
+ * generating the cipher's session key(s). This value is <b>mandatory</b>
+ * and should be included in the initialisation parameters. If it isn't,
+ * an {@link IllegalStateException} will be thrown if any method, other than
+ * <code>reset()</code> is invoked on the instance. Furthermore, the size of
+ * this key material shall be taken as an indication on the key size in which
+ * to operate this instance.</li>
+ * </ul>
+ *
+ * <p><b>IMPLEMENTATION NOTE</b>: Although all the concrete classes in this
+ * package implement the {@link Cloneable} interface, it is important to note
+ * here that such an operation <b>DOES NOT</b> clone any session key material
+ * that may have been used in initialising the source cipher (the instance to be
+ * cloned). Instead a clone of an already initialised cipher is another instance
+ * that operates with the <b>same block size</b> but without any knowledge of
+ * neither key material nor key size.</p>
+ */
+public interface IBlockCipher extends Cloneable
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Property name of the block size in which to operate a block cipher.
+ * The value associated with this property name is taken to be an
+ * {@link Integer}.</p>
+ */
+ String CIPHER_BLOCK_SIZE = "gnu.crypto.cipher.block.size";
+
+ /**
+ * <p>Property name of the user-supplied key material. The value associated
+ * to this property name is taken to be a byte array.</p>
+ */
+ String KEY_MATERIAL = "gnu.crypto.cipher.key.material";
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of this instance.</p>
+ *
+ * @return the canonical name of this instance.
+ */
+ String name();
+
+ /**
+ * <p>Returns the default value, in bytes, of the algorithm's block size.</p>
+ *
+ * @return the default value, in bytes, of the algorithm's block size.
+ */
+ int defaultBlockSize();
+
+ /**
+ * <p>Returns the default value, in bytes, of the algorithm's key size.</p>
+ *
+ * @return the default value, in bytes, of the algorithm's key size.
+ */
+ int defaultKeySize();
+
+ /**
+ * <p>Returns an {@link Iterator} over the supported block sizes. Each
+ * element returned by this object is an {@link Integer}.</p>
+ *
+ * @return an {@link Iterator} over the supported block sizes.
+ */
+ Iterator blockSizes();
+
+ /**
+ * <p>Returns an {@link Iterator} over the supported key sizes. Each element
+ * returned by this object is an {@link Integer}.</p>
+ *
+ * @return an {@link Iterator} over the supported key sizes.
+ */
+ Iterator keySizes();
+
+ /**
+ * <p>Returns a clone of this instance.</p>
+ *
+ * @return a clone copy of this instance.
+ */
+ Object clone();
+
+ /**
+ * <p>Initialises the algorithm with designated attributes. Permissible names
+ * and values are described in the class documentation above.</p>
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @exception InvalidKeyException if the key data is invalid.
+ * @exception IllegalStateException if the instance is already initialised.
+ * @see #KEY_MATERIAL
+ * @see #CIPHER_BLOCK_SIZE
+ */
+ void init(Map attributes) throws InvalidKeyException, IllegalStateException;
+
+ /**
+ * <p>Returns the currently set block size for this instance.</p>
+ *
+ * @return the current block size for this instance.
+ * @exception IllegalStateException if the instance is not initialised.
+ */
+ int currentBlockSize() throws IllegalStateException;
+
+ /**
+ * <p>Resets the algorithm instance for re-initialisation and use with other
+ * characteristics. This method always succeeds.</p>
+ */
+ void reset();
+
+ /**
+ * <p>Encrypts exactly one block of plaintext.</p>
+ *
+ * @param in the plaintext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the ciphertext.
+ * @param outOffset index of <code>out</code> from which to store result.
+ * @exception IllegalStateException if the instance is not initialised.
+ */
+ void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ throws IllegalStateException;
+
+ /**
+ * <p>Decrypts exactly one block of ciphertext.</p>
+ *
+ * @param in the plaintext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the ciphertext.
+ * @param outOffset index of <code>out</code> from which to store result.
+ * @exception IllegalStateException if the instance is not initialised.
+ */
+ void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ throws IllegalStateException;
+
+ /**
+ * <p>A <i>correctness</i> test that consists of basic symmetric encryption /
+ * decryption test(s) for all supported block and key sizes, as well as one
+ * (1) variable key Known Answer Test (KAT).</p>
+ *
+ * @return <code>true</code> if the implementation passes simple
+ * <i>correctness</i> tests. Returns <code>false</code> otherwise.
+ */
+ boolean selfTest();
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/IBlockCipherSpi.java b/gnu/javax/crypto/cipher/IBlockCipherSpi.java
new file mode 100644
index 000000000..6fe07ca7f
--- /dev/null
+++ b/gnu/javax/crypto/cipher/IBlockCipherSpi.java
@@ -0,0 +1,128 @@
+/* IBlockCipherSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import java.security.InvalidKeyException;
+import java.util.Iterator;
+
+/**
+ * <p>Package-private interface exposing mandatory methods to be implemented by
+ * concrete {@link gnu.crypto.cipher.BaseCipher} sub-classes.</p>
+ */
+interface IBlockCipherSpi extends Cloneable
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an {@link java.util.Iterator} over the supported block sizes.
+ * Each element returned by this object is a {@link java.lang.Integer}.</p>
+ *
+ * @return an <code>Iterator</code> over the supported block sizes.
+ */
+ Iterator blockSizes();
+
+ /**
+ * <p>Returns an {@link java.util.Iterator} over the supported key sizes.
+ * Each element returned by this object is a {@link java.lang.Integer}.</p>
+ *
+ * @return an <code>Iterator</code> over the supported key sizes.
+ */
+ Iterator keySizes();
+
+ /**
+ * <p>Expands a user-supplied key material into a session key for a
+ * designated <i>block size</i>.</p>
+ *
+ * @param k the user-supplied key material.
+ * @param bs the desired block size in bytes.
+ * @return an Object encapsulating the session key.
+ * @exception IllegalArgumentException if the block size is invalid.
+ * @exception InvalidKeyException if the key data is invalid.
+ */
+ Object makeKey(byte[] k, int bs) throws InvalidKeyException;
+
+ /**
+ * <p>Encrypts exactly one block of plaintext.</p>
+ *
+ * @param in the plaintext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the ciphertext.
+ * @param outOffset index of <code>out</code> from which to store the result.
+ * @param k the session key to use.
+ * @param bs the block size to use.
+ * @exception IllegalArgumentException if the block size is invalid.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough room in
+ * either the plaintext or ciphertext buffers.
+ */
+ void encrypt(byte[] in, int inOffset, byte[] out, int outOffset, Object k,
+ int bs);
+
+ /**
+ * <p>Decrypts exactly one block of ciphertext.</p>
+ *
+ * @param in the ciphertext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the plaintext.
+ * @param outOffset index of <code>out</code> from which to store the result.
+ * @param k the session key to use.
+ * @param bs the block size to use.
+ * @exception IllegalArgumentException if the block size is invalid.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough room in
+ * either the plaintext or ciphertext buffers.
+ */
+ void decrypt(byte[] in, int inOffset, byte[] out, int outOffset, Object k,
+ int bs);
+
+ /**
+ * <p>A <i>correctness</i> test that consists of basic symmetric encryption /
+ * decryption test(s) for all supported block and key sizes, as well as one
+ * (1) variable key Known Answer Test (KAT).</p>
+ *
+ * @return <code>true</code> if the implementation passes simple
+ * <i>correctness</i> tests. Returns <code>false</code> otherwise.
+ */
+ boolean selfTest();
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/Khazad.java b/gnu/javax/crypto/cipher/Khazad.java
new file mode 100644
index 000000000..b6c27833e
--- /dev/null
+++ b/gnu/javax/crypto/cipher/Khazad.java
@@ -0,0 +1,521 @@
+/* Khazad.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+//import java.io.PrintWriter;
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>Khazad is a 64-bit (legacy-level) block cipher that accepts a 128-bit key.
+ * The cipher is a uniform substitution-permutation network whose inverse only
+ * differs from the forward operation in the key schedule. The overall cipher
+ * design follows the Wide Trail strategy, favours component reuse, and permits
+ * a wide variety of implementation trade-offs.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://planeta.terra.com.br/informatica/paulobarreto/KhazadPage.html">The
+ * Khazad Block Cipher</a>.<br>
+ * <a href="mailto:paulo.barreto@terra.com.br">Paulo S.L.M. Barreto</a> and
+ * <a href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a>.</li>
+ * </ol>
+ */
+public final class Khazad extends BaseCipher
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ // private static final String NAME = "khazad";
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 9;
+
+ // private static final PrintWriter err = new PrintWriter(System.out, true);
+ // private static void debug(String s) {
+ // err.println(">>> "+NAME+": "+s);
+ // }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_BLOCK_SIZE = 8; // in bytes
+
+ private static final int DEFAULT_KEY_SIZE = 16; // in bytes
+
+ private static final int R = 8; // standard number of rounds; para. 3.7
+
+ private static final String Sd = // p. 20 [KHAZAD]
+ "\uBA54\u2F74\u53D3\uD24D\u50AC\u8DBF\u7052\u9A4C"
+ + "\uEAD5\u97D1\u3351\u5BA6\uDE48\uA899\uDB32\uB7FC"
+ + "\uE39E\u919B\uE2BB\u416E\uA5CB\u6B95\uA1F3\uB102"
+ + "\uCCC4\u1D14\uC363\uDA5D\u5FDC\u7DCD\u7F5A\u6C5C"
+ + "\uF726\uFFED\uE89D\u6F8E\u19A0\uF089\u0F07\uAFFB"
+ + "\u0815\u0D04\u0164\uDF76\u79DD\u3D16\u3F37\u6D38"
+ + "\uB973\uE935\u5571\u7B8C\u7288\uF62A\u3E5E\u2746"
+ + "\u0C65\u6861\u03C1\u57D6\uD958\uD866\uD73A\uC83C"
+ + "\uFA96\uA798\uECB8\uC7AE\u694B\uABA9\u670A\u47F2"
+ + "\uB522\uE5EE\uBE2B\u8112\u831B\u0E23\uF545\u21CE"
+ + "\u492C\uF9E6\uB628\u1782\u1A8B\uFE8A\u09C9\u874E"
+ + "\uE12E\uE4E0\uEB90\uA41E\u8560\u0025\uF4F1\u940B"
+ + "\uE775\uEF34\u31D4\uD086\u7EAD\uFD29\u303B\u9FF8"
+ + "\uC613\u0605\uC511\u777C\u7A78\u361C\u3959\u1856"
+ + "\uB3B0\u2420\uB292\uA3C0\u4462\u10B4\u8443\u93C2"
+ + "\u4ABD\u8F2D\uBC9C\u6A40\uCFA2\u804F\u1FCA\uAA42";
+
+ private static final byte[] S = new byte[256];
+
+ private static final int[] T0 = new int[256];
+
+ private static final int[] T1 = new int[256];
+
+ private static final int[] T2 = new int[256];
+
+ private static final int[] T3 = new int[256];
+
+ private static final int[] T4 = new int[256];
+
+ private static final int[] T5 = new int[256];
+
+ private static final int[] T6 = new int[256];
+
+ private static final int[] T7 = new int[256];
+
+ private static final int[][] rc = new int[R + 1][2]; // round constants
+
+ /**
+ * KAT vector (from ecb_vk):
+ * I=120
+ * KEY=00000000000000000000000000000100
+ * CT=A0C86A1BBE2CBF4C
+ */
+ private static final byte[] KAT_KEY = Util.toBytesFromString("00000000000000000000000000000100");
+
+ private static final byte[] KAT_CT = Util.toBytesFromString("A0C86A1BBE2CBF4C");
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ // Static code - to intialise lookup tables --------------------------------
+
+ static
+ {
+ long time = System.currentTimeMillis();
+
+ long ROOT = 0x11d; // para. 2.1 [KHAZAD]
+ int i, j;
+ int s, s2, s3, s4, s5, s6, s7, s8, sb;
+ char c;
+ for (i = 0; i < 256; i++)
+ {
+ c = Sd.charAt(i >>> 1);
+ s = ((i & 1) == 0 ? c >>> 8 : c) & 0xFF;
+ S[i] = (byte) s;
+
+ s2 = s << 1;
+ if (s2 > 0xFF)
+ s2 ^= ROOT;
+
+ s3 = s2 ^ s;
+ s4 = s2 << 1;
+ if (s4 > 0xFF)
+ s4 ^= ROOT;
+
+ s5 = s4 ^ s;
+ s6 = s4 ^ s2;
+ s7 = s6 ^ s;
+ s8 = s4 << 1;
+ if (s8 > 0xFF)
+ s8 ^= ROOT;
+
+ sb = s8 ^ s2 ^ s;
+
+ T0[i] = s << 24 | s3 << 16 | s4 << 8 | s5;
+ T1[i] = s3 << 24 | s << 16 | s5 << 8 | s4;
+ T2[i] = s4 << 24 | s5 << 16 | s << 8 | s3;
+ T3[i] = s5 << 24 | s4 << 16 | s3 << 8 | s;
+ T4[i] = s6 << 24 | s8 << 16 | sb << 8 | s7;
+ T5[i] = s8 << 24 | s6 << 16 | s7 << 8 | sb;
+ T6[i] = sb << 24 | s7 << 16 | s6 << 8 | s8;
+ T7[i] = s7 << 24 | sb << 16 | s8 << 8 | s6;
+ }
+
+ for (i = 0, j = 0; i < R + 1; i++)
+ {
+ // compute round constant
+ rc[i][0] = S[j++] << 24 | (S[j++] & 0xFF) << 16
+ | (S[j++] & 0xFF) << 8 | (S[j++] & 0xFF);
+ rc[i][1] = S[j++] << 24 | (S[j++] & 0xFF) << 16
+ | (S[j++] & 0xFF) << 8 | (S[j++] & 0xFF);
+ }
+
+ time = System.currentTimeMillis() - time;
+
+ if (DEBUG && debuglevel > 8)
+ {
+ System.out.println("==========");
+ System.out.println();
+ System.out.println("Static data");
+ System.out.println();
+
+ System.out.println();
+ System.out.println("T0[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(T0[i * 4 + j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T1[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(T1[i * 4 + j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T2[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(T2[i * 4 + j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T3[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(T3[i * 4 + j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T4[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(T4[i * 4 + j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T5[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(T5[i * 4 + j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T6[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(T6[i * 4 + j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T7[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ System.out.print("0x" + Util.toString(T7[i * 4 + j]) + ", ");
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("rc[]:");
+ for (i = 0; i < R + 1; i++)
+ System.out.print("0x" + Util.toString(rc[i][0])
+ + Util.toString(rc[i][1]));
+ System.out.println();
+
+ System.out.println("Total initialization time: " + time + " ms.");
+ System.out.println();
+ }
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Khazad()
+ {
+ super(Registry.KHAZAD_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ private static void khazad(byte[] in, int i, byte[] out, int j, int[][] K)
+ {
+ // sigma(K[0])
+ int k0 = K[0][0];
+ int k1 = K[0][1];
+ int a0 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ k0;
+ int a1 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i] & 0xFF))
+ ^ k1;
+
+ int b0, b1;
+ // round function
+ for (int r = 1; r < R; r++)
+ {
+ k0 = K[r][0];
+ k1 = K[r][1];
+ b0 = T0[a0 >>> 24] ^ T1[(a0 >>> 16) & 0xFF] ^ T2[(a0 >>> 8) & 0xFF]
+ ^ T3[a0 & 0xFF] ^ T4[a1 >>> 24] ^ T5[(a1 >>> 16) & 0xFF]
+ ^ T6[(a1 >>> 8) & 0xFF] ^ T7[a1 & 0xFF] ^ k0;
+ b1 = T0[a1 >>> 24] ^ T1[(a1 >>> 16) & 0xFF] ^ T2[(a1 >>> 8) & 0xFF]
+ ^ T3[a1 & 0xFF] ^ T4[a0 >>> 24] ^ T5[(a0 >>> 16) & 0xFF]
+ ^ T6[(a0 >>> 8) & 0xFF] ^ T7[a0 & 0xFF] ^ k1;
+ a0 = b0;
+ a1 = b1;
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("T" + r + "=" + Util.toString(a0)
+ + Util.toString(a1));
+ }
+ }
+
+ // sigma(K[R]) o gamma applied to previous output
+ k0 = K[R][0];
+ k1 = K[R][1];
+
+ out[j++] = (byte) (S[a0 >>> 24] ^ (k0 >>> 24));
+ out[j++] = (byte) (S[(a0 >>> 16) & 0xFF] ^ (k0 >>> 16));
+ out[j++] = (byte) (S[(a0 >>> 8) & 0xFF] ^ (k0 >>> 8));
+ out[j++] = (byte) (S[a0 & 0xFF] ^ k0);
+ out[j++] = (byte) (S[a1 >>> 24] ^ (k1 >>> 24));
+ out[j++] = (byte) (S[(a1 >>> 16) & 0xFF] ^ (k1 >>> 16));
+ out[j++] = (byte) (S[(a1 >>> 8) & 0xFF] ^ (k1 >>> 8));
+ out[j] = (byte) (S[a1 & 0xFF] ^ k1);
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("T=" + Util.toString(out, j - 7, 8));
+ System.out.println();
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ Khazad result = new Khazad();
+ result.currentBlockSize = this.currentBlockSize;
+
+ return result;
+ }
+
+ // IBlockCipherSpi interface implementation --------------------------------
+
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(DEFAULT_BLOCK_SIZE));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(DEFAULT_KEY_SIZE));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ /**
+ * <p>Expands a user-supplied key material into a session key for a
+ * designated <i>block size</i>.</p>
+ *
+ * @param uk the 128-bit user-supplied key material.
+ * @param bs the desired block size in bytes.
+ * @return an Object encapsulating the session key.
+ * @exception IllegalArgumentException if the block size is not 16 (128-bit).
+ * @exception InvalidKeyException if the key data is invalid.
+ */
+ public Object makeKey(byte[] uk, int bs) throws InvalidKeyException
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (uk == null)
+ {
+ throw new InvalidKeyException("Empty key");
+ }
+ if (uk.length != 16)
+ {
+ throw new InvalidKeyException("Key is not 128-bit.");
+ }
+ int[][] Ke = new int[R + 1][2]; // encryption round keys
+ int[][] Kd = new int[R + 1][2]; // decryption round keys
+
+ int r, i;
+ int k20, k21, k10, k11, rc0, rc1, kr0, kr1;
+
+ i = 0;
+ k20 = uk[i++] << 24 | (uk[i++] & 0xFF) << 16 | (uk[i++] & 0xFF) << 8
+ | (uk[i++] & 0xFF);
+ k21 = uk[i++] << 24 | (uk[i++] & 0xFF) << 16 | (uk[i++] & 0xFF) << 8
+ | (uk[i++] & 0xFF);
+ k10 = uk[i++] << 24 | (uk[i++] & 0xFF) << 16 | (uk[i++] & 0xFF) << 8
+ | (uk[i++] & 0xFF);
+ k11 = uk[i++] << 24 | (uk[i++] & 0xFF) << 16 | (uk[i++] & 0xFF) << 8
+ | (uk[i++] & 0xFF);
+
+ for (r = 0, i = 0; r <= R; r++)
+ {
+ rc0 = rc[r][0];
+ rc1 = rc[r][1];
+
+ kr0 = T0[k10 >>> 24] ^ T1[(k10 >>> 16) & 0xFF] ^ T2[(k10 >>> 8) & 0xFF]
+ ^ T3[k10 & 0xFF] ^ T4[(k11 >>> 24) & 0xFF]
+ ^ T5[(k11 >>> 16) & 0xFF] ^ T6[(k11 >>> 8) & 0xFF]
+ ^ T7[k11 & 0xFF] ^ rc0 ^ k20;
+ kr1 = T0[k11 >>> 24] ^ T1[(k11 >>> 16) & 0xFF] ^ T2[(k11 >>> 8) & 0xFF]
+ ^ T3[k11 & 0xFF] ^ T4[(k10 >>> 24) & 0xFF]
+ ^ T5[(k10 >>> 16) & 0xFF] ^ T6[(k10 >>> 8) & 0xFF]
+ ^ T7[k10 & 0xFF] ^ rc1 ^ k21;
+
+ Ke[r][0] = kr0;
+ Ke[r][1] = kr1;
+ k20 = k10;
+ k21 = k11;
+ k10 = kr0;
+ k11 = kr1;
+
+ if (r == 0 || r == R)
+ {
+ Kd[R - r][0] = kr0;
+ Kd[R - r][1] = kr1;
+ }
+ else
+ {
+ Kd[R - r][0] = T0[S[kr0 >>> 24] & 0xFF]
+ ^ T1[S[(kr0 >>> 16) & 0xFF] & 0xFF]
+ ^ T2[S[(kr0 >>> 8) & 0xFF] & 0xFF]
+ ^ T3[S[kr0 & 0xFF] & 0xFF]
+ ^ T4[S[kr1 >>> 24] & 0xFF]
+ ^ T5[S[(kr1 >>> 16) & 0xFF] & 0xFF]
+ ^ T6[S[(kr1 >>> 8) & 0xFF] & 0xFF]
+ ^ T7[S[kr1 & 0xFF] & 0xFF];
+ Kd[R - r][1] = T0[S[kr1 >>> 24] & 0xFF]
+ ^ T1[S[(kr1 >>> 16) & 0xFF] & 0xFF]
+ ^ T2[S[(kr1 >>> 8) & 0xFF] & 0xFF]
+ ^ T3[S[kr1 & 0xFF] & 0xFF]
+ ^ T4[S[kr0 >>> 24] & 0xFF]
+ ^ T5[S[(kr0 >>> 16) & 0xFF] & 0xFF]
+ ^ T6[S[(kr0 >>> 8) & 0xFF] & 0xFF]
+ ^ T7[S[kr0 & 0xFF] & 0xFF];
+ }
+ }
+
+ if (DEBUG && debuglevel > 8)
+ {
+ System.out.println();
+ System.out.println("Key schedule");
+ System.out.println();
+ System.out.println("Ke[]:");
+ for (r = 0; r < R + 1; r++)
+ {
+ System.out.println("#" + r + ": 0x" + Util.toString(Ke[r][0])
+ + Util.toString(Ke[r][1]));
+ }
+ System.out.println();
+ System.out.println("Kd[]:");
+ for (r = 0; r < R + 1; r++)
+ {
+ System.out.println("#" + r + ": 0x" + Util.toString(Kd[r][0])
+ + Util.toString(Kd[r][1]));
+ }
+ System.out.println();
+ }
+
+ return new Object[] { Ke, Kd };
+ }
+
+ public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[][] K = (int[][]) ((Object[]) k)[0];
+ khazad(in, i, out, j, K);
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[][] K = (int[][]) ((Object[]) k)[1];
+ khazad(in, i, out, j, K);
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ boolean result = super.selfTest(); // do symmetry tests
+ if (result)
+ {
+ result = testKat(KAT_KEY, KAT_CT);
+ }
+ valid = new Boolean(result);
+ }
+ return valid.booleanValue();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/NullCipher.java b/gnu/javax/crypto/cipher/NullCipher.java
new file mode 100644
index 000000000..09252db90
--- /dev/null
+++ b/gnu/javax/crypto/cipher/NullCipher.java
@@ -0,0 +1,129 @@
+/* NullCipher.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>The implementation of a Null block cipher.</p>
+ *
+ * <p>This cipher does not alter its input at all, claims to process block sizes
+ * 128-, 192- and 256-bit long, and key sizes from 64- to 512-bit in 8-bit
+ * increments.</p>
+ */
+public final class NullCipher extends BaseCipher
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public NullCipher()
+ {
+ super(Registry.NULL_CIPHER, 16, 16);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ NullCipher result = new NullCipher();
+ result.currentBlockSize = this.currentBlockSize;
+
+ return result;
+ }
+
+ // IBlockCipherSpi interface implementation --------------------------------
+
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(64 / 8));
+ al.add(new Integer(128 / 8));
+ al.add(new Integer(192 / 8));
+ al.add(new Integer(256 / 8));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ ArrayList al = new ArrayList();
+ for (int n = 8; n < 64; n++)
+ {
+ al.add(new Integer(n));
+ }
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Object makeKey(byte[] uk, int bs) throws InvalidKeyException
+ {
+ return new Object();
+ }
+
+ public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ System.arraycopy(in, i, out, j, bs);
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ System.arraycopy(in, i, out, j, bs);
+ }
+
+ public boolean selfTest()
+ {
+ return true;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/Rijndael.java b/gnu/javax/crypto/cipher/Rijndael.java
new file mode 100644
index 000000000..058c8b346
--- /dev/null
+++ b/gnu/javax/crypto/cipher/Rijndael.java
@@ -0,0 +1,859 @@
+/* Rijndael.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+//import java.io.PrintWriter;
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>Rijndael --pronounced Reindaal-- is the AES. It is a variable block-size
+ * (128-, 192- and 256-bit), variable key-size (128-, 192- and 256-bit)
+ * symmetric key block cipher.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.esat.kuleuven.ac.be/~rijmen/rijndael/">The
+ * Rijndael Block Cipher - AES Proposal</a>.<br>
+ * <a href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a> and
+ * <a href="mailto:daemen.j@protonworld.com">Joan Daemen</a>.</li>
+ * </ol>
+ */
+public final class Rijndael extends BaseCipher
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ // private static final String NAME = "rijndael";
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 9;
+
+ // private static final PrintWriter err = new PrintWriter(System.out, true);
+ // private static void debug(String s) {
+ // err.println(">>> "+NAME+": "+s);
+ // }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes
+
+ private static final int DEFAULT_KEY_SIZE = 16; // in bytes
+
+ private static final String SS = "\u637C\u777B\uF26B\u6FC5\u3001\u672B\uFED7\uAB76"
+ + "\uCA82\uC97D\uFA59\u47F0\uADD4\uA2AF\u9CA4\u72C0"
+ + "\uB7FD\u9326\u363F\uF7CC\u34A5\uE5F1\u71D8\u3115"
+ + "\u04C7\u23C3\u1896\u059A\u0712\u80E2\uEB27\uB275"
+ + "\u0983\u2C1A\u1B6E\u5AA0\u523B\uD6B3\u29E3\u2F84"
+ + "\u53D1\u00ED\u20FC\uB15B\u6ACB\uBE39\u4A4C\u58CF"
+ + "\uD0EF\uAAFB\u434D\u3385\u45F9\u027F\u503C\u9FA8"
+ + "\u51A3\u408F\u929D\u38F5\uBCB6\uDA21\u10FF\uF3D2"
+ + "\uCD0C\u13EC\u5F97\u4417\uC4A7\u7E3D\u645D\u1973"
+ + "\u6081\u4FDC\u222A\u9088\u46EE\uB814\uDE5E\u0BDB"
+ + "\uE032\u3A0A\u4906\u245C\uC2D3\uAC62\u9195\uE479"
+ + "\uE7C8\u376D\u8DD5\u4EA9\u6C56\uF4EA\u657A\uAE08"
+ + "\uBA78\u252E\u1CA6\uB4C6\uE8DD\u741F\u4BBD\u8B8A"
+ + "\u703E\uB566\u4803\uF60E\u6135\u57B9\u86C1\u1D9E"
+ + "\uE1F8\u9811\u69D9\u8E94\u9B1E\u87E9\uCE55\u28DF"
+ + "\u8CA1\u890D\uBFE6\u4268\u4199\u2D0F\uB054\uBB16";
+
+ private static final byte[] S = new byte[256];
+
+ private static final byte[] Si = new byte[256];
+
+ private static final int[] T1 = new int[256];
+
+ private static final int[] T2 = new int[256];
+
+ private static final int[] T3 = new int[256];
+
+ private static final int[] T4 = new int[256];
+
+ private static final int[] T5 = new int[256];
+
+ private static final int[] T6 = new int[256];
+
+ private static final int[] T7 = new int[256];
+
+ private static final int[] T8 = new int[256];
+
+ private static final int[] U1 = new int[256];
+
+ private static final int[] U2 = new int[256];
+
+ private static final int[] U3 = new int[256];
+
+ private static final int[] U4 = new int[256];
+
+ private static final byte[] rcon = new byte[30];
+
+ private static final int[][][] shifts = new int[][][] {
+ { { 0, 0 }, { 1, 3 },
+ { 2, 2 }, { 3, 1 } },
+ { { 0, 0 }, { 1, 5 },
+ { 2, 4 }, { 3, 3 } },
+ { { 0, 0 }, { 1, 7 },
+ { 3, 5 }, { 4, 4 } } };
+
+ /**
+ * KAT vector (from ecb_vk):
+ * I=96
+ * KEY=0000000000000000000000010000000000000000000000000000000000000000
+ * CT=E44429474D6FC3084EB2A6B8B46AF754
+ */
+ private static final byte[] KAT_KEY = Util.toBytesFromString("0000000000000000000000010000000000000000000000000000000000000000");
+
+ private static final byte[] KAT_CT = Util.toBytesFromString("E44429474D6FC3084EB2A6B8B46AF754");
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ // Static code - to intialise lookup tables --------------------------------
+
+ static
+ {
+ long time = System.currentTimeMillis();
+
+ int ROOT = 0x11B;
+ int i, j = 0;
+
+ // S-box, inverse S-box, T-boxes, U-boxes
+ int s, s2, s3, i2, i4, i8, i9, ib, id, ie, t;
+ char c;
+ for (i = 0; i < 256; i++)
+ {
+ c = SS.charAt(i >>> 1);
+ S[i] = (byte) (((i & 1) == 0) ? c >>> 8 : c & 0xFF);
+ s = S[i] & 0xFF;
+ Si[s] = (byte) i;
+ s2 = s << 1;
+ if (s2 >= 0x100)
+ {
+ s2 ^= ROOT;
+ }
+ s3 = s2 ^ s;
+ i2 = i << 1;
+ if (i2 >= 0x100)
+ {
+ i2 ^= ROOT;
+ }
+ i4 = i2 << 1;
+ if (i4 >= 0x100)
+ {
+ i4 ^= ROOT;
+ }
+ i8 = i4 << 1;
+ if (i8 >= 0x100)
+ {
+ i8 ^= ROOT;
+ }
+ i9 = i8 ^ i;
+ ib = i9 ^ i2;
+ id = i9 ^ i4;
+ ie = i8 ^ i4 ^ i2;
+
+ T1[i] = t = (s2 << 24) | (s << 16) | (s << 8) | s3;
+ T2[i] = (t >>> 8) | (t << 24);
+ T3[i] = (t >>> 16) | (t << 16);
+ T4[i] = (t >>> 24) | (t << 8);
+
+ T5[s] = U1[i] = t = (ie << 24) | (i9 << 16) | (id << 8) | ib;
+ T6[s] = U2[i] = (t >>> 8) | (t << 24);
+ T7[s] = U3[i] = (t >>> 16) | (t << 16);
+ T8[s] = U4[i] = (t >>> 24) | (t << 8);
+ }
+ //
+ // round constants
+ //
+ int r = 1;
+ rcon[0] = 1;
+ for (i = 1; i < 30; i++)
+ {
+ r <<= 1;
+ if (r >= 0x100)
+ {
+ r ^= ROOT;
+ }
+ rcon[i] = (byte) r;
+ }
+
+ time = System.currentTimeMillis() - time;
+
+ if (DEBUG && debuglevel > 8)
+ {
+ System.out.println("==========");
+ System.out.println();
+ System.out.println("Static Data");
+ System.out.println();
+ System.out.println("S[]:");
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ System.out.print("0x" + Util.toString(S[i * 16 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("Si[]:");
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ System.out.print("0x" + Util.toString(Si[i * 16 + j]) + ", ");
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ System.out.println("T1[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T1[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T2[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T2[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T3[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T3[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T4[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T4[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T5[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T5[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T6[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T6[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T7[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T7[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T8[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T8[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ System.out.println("U1[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(U1[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("U2[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(U2[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("U3[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(U3[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("U4[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.println("0x" + Util.toString(U4[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ System.out.println("rcon[]:");
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 0; j < 6; j++)
+ {
+ System.out.print("0x" + Util.toString(rcon[i * 6 + j]) + ", ");
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ System.out.println("Total initialization time: " + time + " ms.");
+ System.out.println();
+ }
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Rijndael()
+ {
+ super(Registry.RIJNDAEL_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the number of rounds for a given Rijndael's key and block
+ * sizes.</p>
+ *
+ * @param ks the size of the user key material in bytes.
+ * @param bs the desired block size in bytes.
+ * @return the number of rounds for a given Rijndael's key and block sizes.
+ */
+ public static int getRounds(int ks, int bs)
+ {
+ switch (ks)
+ {
+ case 16:
+ return bs == 16 ? 10 : (bs == 24 ? 12 : 14);
+ case 24:
+ return bs != 32 ? 12 : 14;
+ default: // 32 bytes = 256 bits
+ return 14;
+ }
+ }
+
+ private static void rijndaelEncrypt(byte[] in, int inOffset, byte[] out,
+ int outOffset, Object sessionKey, int bs)
+ {
+ Object[] sKey = (Object[]) sessionKey; // extract encryption round keys
+ int[][] Ke = (int[][]) sKey[0];
+
+ int BC = bs / 4;
+ int ROUNDS = Ke.length - 1;
+ int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
+ int s1 = shifts[SC][1][0];
+ int s2 = shifts[SC][2][0];
+ int s3 = shifts[SC][3][0];
+ int[] a = new int[BC];
+ int[] t = new int[BC]; // temporary work array
+ int i, tt;
+
+ for (i = 0; i < BC; i++)
+ { // plaintext to ints + key
+ t[i] = (in[inOffset++] << 24 | (in[inOffset++] & 0xFF) << 16
+ | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
+ ^ Ke[0][i];
+ }
+
+ for (int r = 1; r < ROUNDS; r++)
+ { // apply round transforms
+ for (i = 0; i < BC; i++)
+ {
+ a[i] = (T1[(t[i] >>> 24)] ^ T2[(t[(i + s1) % BC] >>> 16) & 0xFF]
+ ^ T3[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ T4[t[(i + s3) % BC] & 0xFF])
+ ^ Ke[r][i];
+ }
+
+ System.arraycopy(a, 0, t, 0, BC);
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CT" + r + "=" + Util.toString(t));
+ }
+ }
+
+ for (i = 0; i < BC; i++)
+ { // last round is special
+ tt = Ke[ROUNDS][i];
+ out[outOffset++] = (byte) (S[(t[i] >>> 24)] ^ (tt >>> 24));
+ out[outOffset++] = (byte) (S[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[outOffset++] = (byte) (S[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[outOffset++] = (byte) (S[t[(i + s3) % BC] & 0xFF] ^ tt);
+ }
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CT=" + Util.toString(out, outOffset - bs + 1, bs));
+ System.out.println();
+ }
+ }
+
+ private static void rijndaelDecrypt(byte[] in, int inOffset, byte[] out,
+ int outOffset, Object sessionKey, int bs)
+ {
+ Object[] sKey = (Object[]) sessionKey; // extract decryption round keys
+ int[][] Kd = (int[][]) sKey[1];
+
+ int BC = bs / 4;
+ int ROUNDS = Kd.length - 1;
+ int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
+ int s1 = shifts[SC][1][1];
+ int s2 = shifts[SC][2][1];
+ int s3 = shifts[SC][3][1];
+ int[] a = new int[BC];
+ int[] t = new int[BC]; // temporary work array
+ int i, tt;
+
+ for (i = 0; i < BC; i++)
+ { // ciphertext to ints + key
+ t[i] = (in[inOffset++] << 24 | (in[inOffset++] & 0xFF) << 16
+ | (in[inOffset++] & 0xFF) << 8 | (in[inOffset++] & 0xFF))
+ ^ Kd[0][i];
+ }
+
+ for (int r = 1; r < ROUNDS; r++)
+ { // apply round transforms
+ for (i = 0; i < BC; i++)
+ {
+ a[i] = (T5[(t[i] >>> 24)] ^ T6[(t[(i + s1) % BC] >>> 16) & 0xFF]
+ ^ T7[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ T8[t[(i + s3) % BC] & 0xFF])
+ ^ Kd[r][i];
+ }
+
+ System.arraycopy(a, 0, t, 0, BC);
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PT" + r + "=" + Util.toString(t));
+ }
+ }
+
+ for (i = 0; i < BC; i++)
+ { // last round is special
+ tt = Kd[ROUNDS][i];
+ out[outOffset++] = (byte) (Si[(t[i] >>> 24)] ^ (tt >>> 24));
+ out[outOffset++] = (byte) (Si[(t[(i + s1) % BC] >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[outOffset++] = (byte) (Si[(t[(i + s2) % BC] >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[outOffset++] = (byte) (Si[t[(i + s3) % BC] & 0xFF] ^ tt);
+ }
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PT=" + Util.toString(out, outOffset - bs + 1, bs));
+ System.out.println();
+ }
+ }
+
+ private static void aesEncrypt(byte[] in, int i, byte[] out, int j, Object key)
+ {
+ int[][] Ke = (int[][]) ((Object[]) key)[0]; // extract encryption round keys
+ int ROUNDS = Ke.length - 1;
+ int[] Ker = Ke[0];
+
+ // plaintext to ints + key
+ int t0 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Ker[0];
+ int t1 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Ker[1];
+ int t2 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Ker[2];
+ int t3 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Ker[3];
+
+ int a0, a1, a2, a3;
+ for (int r = 1; r < ROUNDS; r++)
+ { // apply round transforms
+ Ker = Ke[r];
+ a0 = (T1[(t0 >>> 24)] ^ T2[(t1 >>> 16) & 0xFF] ^ T3[(t2 >>> 8) & 0xFF] ^ T4[t3 & 0xFF])
+ ^ Ker[0];
+ a1 = (T1[(t1 >>> 24)] ^ T2[(t2 >>> 16) & 0xFF] ^ T3[(t3 >>> 8) & 0xFF] ^ T4[t0 & 0xFF])
+ ^ Ker[1];
+ a2 = (T1[(t2 >>> 24)] ^ T2[(t3 >>> 16) & 0xFF] ^ T3[(t0 >>> 8) & 0xFF] ^ T4[t1 & 0xFF])
+ ^ Ker[2];
+ a3 = (T1[(t3 >>> 24)] ^ T2[(t0 >>> 16) & 0xFF] ^ T3[(t1 >>> 8) & 0xFF] ^ T4[t2 & 0xFF])
+ ^ Ker[3];
+ t0 = a0;
+ t1 = a1;
+ t2 = a2;
+ t3 = a3;
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CT" + r + "=" + Util.toString(t0)
+ + Util.toString(t1) + Util.toString(t2)
+ + Util.toString(t3));
+ }
+ }
+
+ // last round is special
+ Ker = Ke[ROUNDS];
+ int tt = Ker[0];
+ out[j++] = (byte) (S[(t0 >>> 24)] ^ (tt >>> 24));
+ out[j++] = (byte) (S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (S[t3 & 0xFF] ^ tt);
+ tt = Ker[1];
+ out[j++] = (byte) (S[(t1 >>> 24)] ^ (tt >>> 24));
+ out[j++] = (byte) (S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (S[t0 & 0xFF] ^ tt);
+ tt = Ker[2];
+ out[j++] = (byte) (S[(t2 >>> 24)] ^ (tt >>> 24));
+ out[j++] = (byte) (S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (S[t1 & 0xFF] ^ tt);
+ tt = Ker[3];
+ out[j++] = (byte) (S[(t3 >>> 24)] ^ (tt >>> 24));
+ out[j++] = (byte) (S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (S[t2 & 0xFF] ^ tt);
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CT=" + Util.toString(out, j - 15, 16));
+ System.out.println();
+ }
+ }
+
+ private static void aesDecrypt(byte[] in, int i, byte[] out, int j, Object key)
+ {
+ int[][] Kd = (int[][]) ((Object[]) key)[1]; // extract decryption round keys
+ int ROUNDS = Kd.length - 1;
+ int[] Kdr = Kd[0];
+
+ // ciphertext to ints + key
+ int t0 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Kdr[0];
+ int t1 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Kdr[1];
+ int t2 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Kdr[2];
+ int t3 = (in[i++] << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ Kdr[3];
+
+ int a0, a1, a2, a3;
+ for (int r = 1; r < ROUNDS; r++)
+ { // apply round transforms
+ Kdr = Kd[r];
+ a0 = (T5[(t0 >>> 24)] ^ T6[(t3 >>> 16) & 0xFF] ^ T7[(t2 >>> 8) & 0xFF] ^ T8[t1 & 0xFF])
+ ^ Kdr[0];
+ a1 = (T5[(t1 >>> 24)] ^ T6[(t0 >>> 16) & 0xFF] ^ T7[(t3 >>> 8) & 0xFF] ^ T8[t2 & 0xFF])
+ ^ Kdr[1];
+ a2 = (T5[(t2 >>> 24)] ^ T6[(t1 >>> 16) & 0xFF] ^ T7[(t0 >>> 8) & 0xFF] ^ T8[t3 & 0xFF])
+ ^ Kdr[2];
+ a3 = (T5[(t3 >>> 24)] ^ T6[(t2 >>> 16) & 0xFF] ^ T7[(t1 >>> 8) & 0xFF] ^ T8[t0 & 0xFF])
+ ^ Kdr[3];
+ t0 = a0;
+ t1 = a1;
+ t2 = a2;
+ t3 = a3;
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PT" + r + "=" + Util.toString(t0)
+ + Util.toString(t1) + Util.toString(t2)
+ + Util.toString(t3));
+ }
+ }
+
+ // last round is special
+ Kdr = Kd[ROUNDS];
+ int tt = Kdr[0];
+ out[j++] = (byte) (Si[(t0 >>> 24)] ^ (tt >>> 24));
+ out[j++] = (byte) (Si[(t3 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (Si[(t2 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (Si[t1 & 0xFF] ^ tt);
+ tt = Kdr[1];
+ out[j++] = (byte) (Si[(t1 >>> 24)] ^ (tt >>> 24));
+ out[j++] = (byte) (Si[(t0 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (Si[(t3 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (Si[t2 & 0xFF] ^ tt);
+ tt = Kdr[2];
+ out[j++] = (byte) (Si[(t2 >>> 24)] ^ (tt >>> 24));
+ out[j++] = (byte) (Si[(t1 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (Si[(t0 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (Si[t3 & 0xFF] ^ tt);
+ tt = Kdr[3];
+ out[j++] = (byte) (Si[(t3 >>> 24)] ^ (tt >>> 24));
+ out[j++] = (byte) (Si[(t2 >>> 16) & 0xFF] ^ (tt >>> 16));
+ out[j++] = (byte) (Si[(t1 >>> 8) & 0xFF] ^ (tt >>> 8));
+ out[j++] = (byte) (Si[t0 & 0xFF] ^ tt);
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PT=" + Util.toString(out, j - 15, 16));
+ System.out.println();
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ Rijndael result = new Rijndael();
+ result.currentBlockSize = this.currentBlockSize;
+
+ return result;
+ }
+
+ // IBlockCipherSpi interface implementation --------------------------------
+
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(128 / 8));
+ al.add(new Integer(192 / 8));
+ al.add(new Integer(256 / 8));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(128 / 8));
+ al.add(new Integer(192 / 8));
+ al.add(new Integer(256 / 8));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ /**
+ * Expands a user-supplied key material into a session key for a designated
+ * <i>block size</i>.
+ *
+ * @param k the 128/192/256-bit user-key to use.
+ * @param bs the block size in bytes of this Rijndael.
+ * @return an Object encapsulating the session key.
+ * @exception IllegalArgumentException if the block size is not 16, 24 or 32.
+ * @exception InvalidKeyException if the key data is invalid.
+ */
+ public Object makeKey(byte[] k, int bs) throws InvalidKeyException
+ {
+ if (k == null)
+ {
+ throw new InvalidKeyException("Empty key");
+ }
+ if (!(k.length == 16 || k.length == 24 || k.length == 32))
+ {
+ throw new InvalidKeyException("Incorrect key length");
+ }
+ if (!(bs == 16 || bs == 24 || bs == 32))
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int ROUNDS = getRounds(k.length, bs);
+ int BC = bs / 4;
+ int[][] Ke = new int[ROUNDS + 1][BC]; // encryption round keys
+ int[][] Kd = new int[ROUNDS + 1][BC]; // decryption round keys
+ int ROUND_KEY_COUNT = (ROUNDS + 1) * BC;
+ int KC = k.length / 4;
+ int[] tk = new int[KC];
+ int i, j;
+
+ // copy user material bytes into temporary ints
+ for (i = 0, j = 0; i < KC;)
+ {
+ tk[i++] = k[j++] << 24 | (k[j++] & 0xFF) << 16 | (k[j++] & 0xFF) << 8
+ | (k[j++] & 0xFF);
+ }
+ // copy values into round key arrays
+ int t = 0;
+ for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
+ {
+ Ke[t / BC][t % BC] = tk[j];
+ Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
+ }
+ int tt, rconpointer = 0;
+ while (t < ROUND_KEY_COUNT)
+ {
+ // extrapolate using phi (the round key evolution function)
+ tt = tk[KC - 1];
+ tk[0] ^= (S[(tt >>> 16) & 0xFF] & 0xFF) << 24
+ ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 16
+ ^ (S[tt & 0xFF] & 0xFF) << 8 ^ (S[(tt >>> 24)] & 0xFF)
+ ^ rcon[rconpointer++] << 24;
+ if (KC != 8)
+ {
+ for (i = 1, j = 0; i < KC;)
+ {
+ tk[i++] ^= tk[j++];
+ }
+ }
+ else
+ {
+ for (i = 1, j = 0; i < KC / 2;)
+ {
+ tk[i++] ^= tk[j++];
+ }
+ tt = tk[KC / 2 - 1];
+ tk[KC / 2] ^= (S[tt & 0xFF] & 0xFF)
+ ^ (S[(tt >>> 8) & 0xFF] & 0xFF) << 8
+ ^ (S[(tt >>> 16) & 0xFF] & 0xFF) << 16
+ ^ S[(tt >>> 24) & 0xFF] << 24;
+ for (j = KC / 2, i = j + 1; i < KC;)
+ {
+ tk[i++] ^= tk[j++];
+ }
+ }
+ // copy values into round key arrays
+ for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++)
+ {
+ Ke[t / BC][t % BC] = tk[j];
+ Kd[ROUNDS - (t / BC)][t % BC] = tk[j];
+ }
+ }
+ for (int r = 1; r < ROUNDS; r++)
+ { // inverse MixColumn where needed
+ for (j = 0; j < BC; j++)
+ {
+ tt = Kd[r][j];
+ Kd[r][j] = U1[(tt >>> 24)] ^ U2[(tt >>> 16) & 0xFF]
+ ^ U3[(tt >>> 8) & 0xFF] ^ U4[tt & 0xFF];
+ }
+ }
+
+ return new Object[] { Ke, Kd };
+ }
+
+ public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (!(bs == 16 || bs == 24 || bs == 32))
+ {
+ throw new IllegalArgumentException();
+ }
+
+ if (bs == DEFAULT_BLOCK_SIZE)
+ {
+ aesEncrypt(in, i, out, j, k);
+ }
+ else
+ {
+ rijndaelEncrypt(in, i, out, j, k, bs);
+ }
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (!(bs == 16 || bs == 24 || bs == 32))
+ {
+ throw new IllegalArgumentException();
+ }
+
+ if (bs == DEFAULT_BLOCK_SIZE)
+ {
+ aesDecrypt(in, i, out, j, k);
+ }
+ else
+ {
+ rijndaelDecrypt(in, i, out, j, k, bs);
+ }
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ boolean result = super.selfTest(); // do symmetry tests
+ if (result)
+ {
+ result = testKat(KAT_KEY, KAT_CT);
+ }
+ valid = new Boolean(result);
+ }
+ return valid.booleanValue();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/Serpent.java b/gnu/javax/crypto/cipher/Serpent.java
new file mode 100644
index 000000000..b323b5017
--- /dev/null
+++ b/gnu/javax/crypto/cipher/Serpent.java
@@ -0,0 +1,1830 @@
+/* Serpent.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>Serpent is a 32-round substitution-permutation network block cipher,
+ * operating on 128-bit blocks and accepting keys of 128, 192, and 256 bits in
+ * length. At each round the plaintext is XORed with a 128 bit portion of the
+ * session key -- a 4224 bit key computed from the input key -- then one of
+ * eight S-boxes are applied, and finally a simple linear transformation is
+ * done. Decryption does the exact same thing in reverse order, and using the
+ * eight inverses of the S-boxes.</p>
+ *
+ * <p>Serpent was designed by Ross Anderson, Eli Biham, and Lars Knudsen as a
+ * proposed cipher for the Advanced Encryption Standard.</p>
+ *
+ * <p>Serpent can be sped up greatly by replacing S-box substitution with a
+ * sequence of binary operations, and the optimal implementation depends
+ * upon finding the fastest sequence of binary operations that reproduce this
+ * substitution. This implementation uses the S-boxes discovered by
+ * <a href="http://www.ii.uib.no/~osvik/">Dag Arne Osvik</a>, which are
+ * optimized for the Pentium family of processors.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.cl.cam.ac.uk/~rja14/serpent.html">Serpent: A
+ * Candidate Block Cipher for the Advanced Encryption Standard.</a></li>
+ * </ol>
+ */
+public class Serpent extends BaseCipher
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_KEY_SIZE = 16;
+
+ private static final int DEFAULT_BLOCK_SIZE = 16;
+
+ private static final int ROUNDS = 32;
+
+ /** The fractional part of the golden ratio, (sqrt(5)+1)/2. */
+ private static final int PHI = 0x9e3779b9;
+
+ /**
+ * KAT vector (from ecb_vk):
+ * I=9
+ * KEY=008000000000000000000000000000000000000000000000
+ * CT=5587B5BCB9EE5A28BA2BACC418005240
+ */
+ private static final byte[] KAT_KEY = Util.toReversedBytesFromString("008000000000000000000000000000000000000000000000");
+
+ private static final byte[] KAT_CT = Util.toReversedBytesFromString("5587B5BCB9EE5A28BA2BACC418005240");
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ private int x0, x1, x2, x3, x4;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial zero-argument constructor. */
+ public Serpent()
+ {
+ super(Registry.SERPENT_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ Serpent result = new Serpent();
+ result.currentBlockSize = this.currentBlockSize;
+ return result;
+ }
+
+ // IBlockCipherSpi interface implementation --------------------------------
+
+ public Iterator blockSizes()
+ {
+ return Collections.singleton(new Integer(DEFAULT_BLOCK_SIZE)).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ ArrayList keySizes = new ArrayList();
+ keySizes.add(new Integer(16));
+ keySizes.add(new Integer(24));
+ keySizes.add(new Integer(32));
+
+ return Collections.unmodifiableList(keySizes).iterator();
+ }
+
+ public Object makeKey(byte[] kb, int blockSize) throws InvalidKeyException
+ {
+ // Not strictly true, but here to conform with the AES proposal.
+ // This restriction can be removed if deemed necessary.
+ if (kb.length != 16 && kb.length != 24 && kb.length != 32)
+ {
+ throw new InvalidKeyException("Key length is not 16, 24, or 32 bytes");
+ }
+ Key key = new Key();
+
+ // Here w is our "pre-key".
+ int[] w = new int[4 * (ROUNDS + 1)];
+ int i, j;
+ for (i = 0, j = 0; i < 8 && j < kb.length; i++)
+ {
+ w[i] = (kb[j++] & 0xff) | (kb[j++] & 0xff) << 8
+ | (kb[j++] & 0xff) << 16 | (kb[j++] & 0xff) << 24;
+ }
+ // Pad key if < 256 bits.
+ if (i != 8)
+ {
+ w[i] = 1;
+ }
+ // Transform using w_i-8 ... w_i-1
+ for (i = 8, j = 0; i < 16; i++)
+ {
+ int t = w[j] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ j++;
+ w[i] = t << 11 | t >>> 21;
+ }
+ // Translate by 8.
+ for (i = 0; i < 8; i++)
+ {
+ w[i] = w[i + 8];
+ }
+ // Transform the rest of the key.
+ for (; i < w.length; i++)
+ {
+ int t = w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i;
+ w[i] = t << 11 | t >>> 21;
+ }
+
+ // After these s-boxes the pre-key (w, above) will become the
+ // session key (key, below).
+ sbox3(w[0], w[1], w[2], w[3]);
+ key.k0 = x0;
+ key.k1 = x1;
+ key.k2 = x2;
+ key.k3 = x3;
+ sbox2(w[4], w[5], w[6], w[7]);
+ key.k4 = x0;
+ key.k5 = x1;
+ key.k6 = x2;
+ key.k7 = x3;
+ sbox1(w[8], w[9], w[10], w[11]);
+ key.k8 = x0;
+ key.k9 = x1;
+ key.k10 = x2;
+ key.k11 = x3;
+ sbox0(w[12], w[13], w[14], w[15]);
+ key.k12 = x0;
+ key.k13 = x1;
+ key.k14 = x2;
+ key.k15 = x3;
+ sbox7(w[16], w[17], w[18], w[19]);
+ key.k16 = x0;
+ key.k17 = x1;
+ key.k18 = x2;
+ key.k19 = x3;
+ sbox6(w[20], w[21], w[22], w[23]);
+ key.k20 = x0;
+ key.k21 = x1;
+ key.k22 = x2;
+ key.k23 = x3;
+ sbox5(w[24], w[25], w[26], w[27]);
+ key.k24 = x0;
+ key.k25 = x1;
+ key.k26 = x2;
+ key.k27 = x3;
+ sbox4(w[28], w[29], w[30], w[31]);
+ key.k28 = x0;
+ key.k29 = x1;
+ key.k30 = x2;
+ key.k31 = x3;
+ sbox3(w[32], w[33], w[34], w[35]);
+ key.k32 = x0;
+ key.k33 = x1;
+ key.k34 = x2;
+ key.k35 = x3;
+ sbox2(w[36], w[37], w[38], w[39]);
+ key.k36 = x0;
+ key.k37 = x1;
+ key.k38 = x2;
+ key.k39 = x3;
+ sbox1(w[40], w[41], w[42], w[43]);
+ key.k40 = x0;
+ key.k41 = x1;
+ key.k42 = x2;
+ key.k43 = x3;
+ sbox0(w[44], w[45], w[46], w[47]);
+ key.k44 = x0;
+ key.k45 = x1;
+ key.k46 = x2;
+ key.k47 = x3;
+ sbox7(w[48], w[49], w[50], w[51]);
+ key.k48 = x0;
+ key.k49 = x1;
+ key.k50 = x2;
+ key.k51 = x3;
+ sbox6(w[52], w[53], w[54], w[55]);
+ key.k52 = x0;
+ key.k53 = x1;
+ key.k54 = x2;
+ key.k55 = x3;
+ sbox5(w[56], w[57], w[58], w[59]);
+ key.k56 = x0;
+ key.k57 = x1;
+ key.k58 = x2;
+ key.k59 = x3;
+ sbox4(w[60], w[61], w[62], w[63]);
+ key.k60 = x0;
+ key.k61 = x1;
+ key.k62 = x2;
+ key.k63 = x3;
+ sbox3(w[64], w[65], w[66], w[67]);
+ key.k64 = x0;
+ key.k65 = x1;
+ key.k66 = x2;
+ key.k67 = x3;
+ sbox2(w[68], w[69], w[70], w[71]);
+ key.k68 = x0;
+ key.k69 = x1;
+ key.k70 = x2;
+ key.k71 = x3;
+ sbox1(w[72], w[73], w[74], w[75]);
+ key.k72 = x0;
+ key.k73 = x1;
+ key.k74 = x2;
+ key.k75 = x3;
+ sbox0(w[76], w[77], w[78], w[79]);
+ key.k76 = x0;
+ key.k77 = x1;
+ key.k78 = x2;
+ key.k79 = x3;
+ sbox7(w[80], w[81], w[82], w[83]);
+ key.k80 = x0;
+ key.k81 = x1;
+ key.k82 = x2;
+ key.k83 = x3;
+ sbox6(w[84], w[85], w[86], w[87]);
+ key.k84 = x0;
+ key.k85 = x1;
+ key.k86 = x2;
+ key.k87 = x3;
+ sbox5(w[88], w[89], w[90], w[91]);
+ key.k88 = x0;
+ key.k89 = x1;
+ key.k90 = x2;
+ key.k91 = x3;
+ sbox4(w[92], w[93], w[94], w[95]);
+ key.k92 = x0;
+ key.k93 = x1;
+ key.k94 = x2;
+ key.k95 = x3;
+ sbox3(w[96], w[97], w[98], w[99]);
+ key.k96 = x0;
+ key.k97 = x1;
+ key.k98 = x2;
+ key.k99 = x3;
+ sbox2(w[100], w[101], w[102], w[103]);
+ key.k100 = x0;
+ key.k101 = x1;
+ key.k102 = x2;
+ key.k103 = x3;
+ sbox1(w[104], w[105], w[106], w[107]);
+ key.k104 = x0;
+ key.k105 = x1;
+ key.k106 = x2;
+ key.k107 = x3;
+ sbox0(w[108], w[109], w[110], w[111]);
+ key.k108 = x0;
+ key.k109 = x1;
+ key.k110 = x2;
+ key.k111 = x3;
+ sbox7(w[112], w[113], w[114], w[115]);
+ key.k112 = x0;
+ key.k113 = x1;
+ key.k114 = x2;
+ key.k115 = x3;
+ sbox6(w[116], w[117], w[118], w[119]);
+ key.k116 = x0;
+ key.k117 = x1;
+ key.k118 = x2;
+ key.k119 = x3;
+ sbox5(w[120], w[121], w[122], w[123]);
+ key.k120 = x0;
+ key.k121 = x1;
+ key.k122 = x2;
+ key.k123 = x3;
+ sbox4(w[124], w[125], w[126], w[127]);
+ key.k124 = x0;
+ key.k125 = x1;
+ key.k126 = x2;
+ key.k127 = x3;
+ sbox3(w[128], w[129], w[130], w[131]);
+ key.k128 = x0;
+ key.k129 = x1;
+ key.k130 = x2;
+ key.k131 = x3;
+
+ return key;
+ }
+
+ public synchronized void encrypt(byte[] in, int i, byte[] out, int o,
+ Object K, int bs)
+ {
+ Key key = (Key) K;
+
+ x0 = (in[i] & 0xff) | (in[i + 1] & 0xff) << 8 | (in[i + 2] & 0xff) << 16
+ | (in[i + 3] & 0xff) << 24;
+ x1 = (in[i + 4] & 0xff) | (in[i + 5] & 0xff) << 8
+ | (in[i + 6] & 0xff) << 16 | (in[i + 7] & 0xff) << 24;
+ x2 = (in[i + 8] & 0xff) | (in[i + 9] & 0xff) << 8
+ | (in[i + 10] & 0xff) << 16 | (in[i + 11] & 0xff) << 24;
+ x3 = (in[i + 12] & 0xff) | (in[i + 13] & 0xff) << 8
+ | (in[i + 14] & 0xff) << 16 | (in[i + 15] & 0xff) << 24;
+
+ x0 ^= key.k0;
+ x1 ^= key.k1;
+ x2 ^= key.k2;
+ x3 ^= key.k3;
+ sbox0();
+ x1 ^= key.k4;
+ x4 ^= key.k5;
+ x2 ^= key.k6;
+ x0 ^= key.k7;
+ sbox1();
+ x0 ^= key.k8;
+ x4 ^= key.k9;
+ x2 ^= key.k10;
+ x1 ^= key.k11;
+ sbox2();
+ x2 ^= key.k12;
+ x1 ^= key.k13;
+ x4 ^= key.k14;
+ x3 ^= key.k15;
+ sbox3();
+ x1 ^= key.k16;
+ x4 ^= key.k17;
+ x3 ^= key.k18;
+ x0 ^= key.k19;
+ sbox4();
+ x4 ^= key.k20;
+ x2 ^= key.k21;
+ x1 ^= key.k22;
+ x0 ^= key.k23;
+ sbox5();
+ x2 ^= key.k24;
+ x0 ^= key.k25;
+ x4 ^= key.k26;
+ x1 ^= key.k27;
+ sbox6();
+ x2 ^= key.k28;
+ x0 ^= key.k29;
+ x3 ^= key.k30;
+ x4 ^= key.k31;
+ sbox7();
+ x0 = x3;
+ x3 = x2;
+ x2 = x4;
+
+ x0 ^= key.k32;
+ x1 ^= key.k33;
+ x2 ^= key.k34;
+ x3 ^= key.k35;
+ sbox0();
+ x1 ^= key.k36;
+ x4 ^= key.k37;
+ x2 ^= key.k38;
+ x0 ^= key.k39;
+ sbox1();
+ x0 ^= key.k40;
+ x4 ^= key.k41;
+ x2 ^= key.k42;
+ x1 ^= key.k43;
+ sbox2();
+ x2 ^= key.k44;
+ x1 ^= key.k45;
+ x4 ^= key.k46;
+ x3 ^= key.k47;
+ sbox3();
+ x1 ^= key.k48;
+ x4 ^= key.k49;
+ x3 ^= key.k50;
+ x0 ^= key.k51;
+ sbox4();
+ x4 ^= key.k52;
+ x2 ^= key.k53;
+ x1 ^= key.k54;
+ x0 ^= key.k55;
+ sbox5();
+ x2 ^= key.k56;
+ x0 ^= key.k57;
+ x4 ^= key.k58;
+ x1 ^= key.k59;
+ sbox6();
+ x2 ^= key.k60;
+ x0 ^= key.k61;
+ x3 ^= key.k62;
+ x4 ^= key.k63;
+ sbox7();
+ x0 = x3;
+ x3 = x2;
+ x2 = x4;
+
+ x0 ^= key.k64;
+ x1 ^= key.k65;
+ x2 ^= key.k66;
+ x3 ^= key.k67;
+ sbox0();
+ x1 ^= key.k68;
+ x4 ^= key.k69;
+ x2 ^= key.k70;
+ x0 ^= key.k71;
+ sbox1();
+ x0 ^= key.k72;
+ x4 ^= key.k73;
+ x2 ^= key.k74;
+ x1 ^= key.k75;
+ sbox2();
+ x2 ^= key.k76;
+ x1 ^= key.k77;
+ x4 ^= key.k78;
+ x3 ^= key.k79;
+ sbox3();
+ x1 ^= key.k80;
+ x4 ^= key.k81;
+ x3 ^= key.k82;
+ x0 ^= key.k83;
+ sbox4();
+ x4 ^= key.k84;
+ x2 ^= key.k85;
+ x1 ^= key.k86;
+ x0 ^= key.k87;
+ sbox5();
+ x2 ^= key.k88;
+ x0 ^= key.k89;
+ x4 ^= key.k90;
+ x1 ^= key.k91;
+ sbox6();
+ x2 ^= key.k92;
+ x0 ^= key.k93;
+ x3 ^= key.k94;
+ x4 ^= key.k95;
+ sbox7();
+ x0 = x3;
+ x3 = x2;
+ x2 = x4;
+
+ x0 ^= key.k96;
+ x1 ^= key.k97;
+ x2 ^= key.k98;
+ x3 ^= key.k99;
+ sbox0();
+ x1 ^= key.k100;
+ x4 ^= key.k101;
+ x2 ^= key.k102;
+ x0 ^= key.k103;
+ sbox1();
+ x0 ^= key.k104;
+ x4 ^= key.k105;
+ x2 ^= key.k106;
+ x1 ^= key.k107;
+ sbox2();
+ x2 ^= key.k108;
+ x1 ^= key.k109;
+ x4 ^= key.k110;
+ x3 ^= key.k111;
+ sbox3();
+ x1 ^= key.k112;
+ x4 ^= key.k113;
+ x3 ^= key.k114;
+ x0 ^= key.k115;
+ sbox4();
+ x4 ^= key.k116;
+ x2 ^= key.k117;
+ x1 ^= key.k118;
+ x0 ^= key.k119;
+ sbox5();
+ x2 ^= key.k120;
+ x0 ^= key.k121;
+ x4 ^= key.k122;
+ x1 ^= key.k123;
+ sbox6();
+ x2 ^= key.k124;
+ x0 ^= key.k125;
+ x3 ^= key.k126;
+ x4 ^= key.k127;
+ sbox7noLT();
+ x0 = x3;
+ x3 = x2;
+ x2 = x4;
+ x0 ^= key.k128;
+ x1 ^= key.k129;
+ x2 ^= key.k130;
+ x3 ^= key.k131;
+
+ out[o] = (byte) x0;
+ out[o + 1] = (byte) (x0 >>> 8);
+ out[o + 2] = (byte) (x0 >>> 16);
+ out[o + 3] = (byte) (x0 >>> 24);
+ out[o + 4] = (byte) x1;
+ out[o + 5] = (byte) (x1 >>> 8);
+ out[o + 6] = (byte) (x1 >>> 16);
+ out[o + 7] = (byte) (x1 >>> 24);
+ out[o + 8] = (byte) x2;
+ out[o + 9] = (byte) (x2 >>> 8);
+ out[o + 10] = (byte) (x2 >>> 16);
+ out[o + 11] = (byte) (x2 >>> 24);
+ out[o + 12] = (byte) x3;
+ out[o + 13] = (byte) (x3 >>> 8);
+ out[o + 14] = (byte) (x3 >>> 16);
+ out[o + 15] = (byte) (x3 >>> 24);
+ }
+
+ public synchronized void decrypt(byte[] in, int i, byte[] out, int o,
+ Object K, int bs)
+ {
+ Key key = (Key) K;
+
+ x0 = (in[i] & 0xff) | (in[i + 1] & 0xff) << 8 | (in[i + 2] & 0xff) << 16
+ | (in[i + 3] & 0xff) << 24;
+ x1 = (in[i + 4] & 0xff) | (in[i + 5] & 0xff) << 8
+ | (in[i + 6] & 0xff) << 16 | (in[i + 7] & 0xff) << 24;
+ x2 = (in[i + 8] & 0xff) | (in[i + 9] & 0xff) << 8
+ | (in[i + 10] & 0xff) << 16 | (in[i + 11] & 0xff) << 24;
+ x3 = (in[i + 12] & 0xff) | (in[i + 13] & 0xff) << 8
+ | (in[i + 14] & 0xff) << 16 | (in[i + 15] & 0xff) << 24;
+
+ x0 ^= key.k128;
+ x1 ^= key.k129;
+ x2 ^= key.k130;
+ x3 ^= key.k131;
+ sboxI7noLT();
+ x3 ^= key.k124;
+ x0 ^= key.k125;
+ x1 ^= key.k126;
+ x4 ^= key.k127;
+ sboxI6();
+ x0 ^= key.k120;
+ x1 ^= key.k121;
+ x2 ^= key.k122;
+ x4 ^= key.k123;
+ sboxI5();
+ x1 ^= key.k116;
+ x3 ^= key.k117;
+ x4 ^= key.k118;
+ x2 ^= key.k119;
+ sboxI4();
+ x1 ^= key.k112;
+ x2 ^= key.k113;
+ x4 ^= key.k114;
+ x0 ^= key.k115;
+ sboxI3();
+ x0 ^= key.k108;
+ x1 ^= key.k109;
+ x4 ^= key.k110;
+ x2 ^= key.k111;
+ sboxI2();
+ x1 ^= key.k104;
+ x3 ^= key.k105;
+ x4 ^= key.k106;
+ x2 ^= key.k107;
+ sboxI1();
+ x0 ^= key.k100;
+ x1 ^= key.k101;
+ x2 ^= key.k102;
+ x4 ^= key.k103;
+ sboxI0();
+ x0 ^= key.k96;
+ x3 ^= key.k97;
+ x1 ^= key.k98;
+ x4 ^= key.k99;
+ sboxI7();
+ x1 = x3;
+ x3 = x4;
+ x4 = x2;
+
+ x3 ^= key.k92;
+ x0 ^= key.k93;
+ x1 ^= key.k94;
+ x4 ^= key.k95;
+ sboxI6();
+ x0 ^= key.k88;
+ x1 ^= key.k89;
+ x2 ^= key.k90;
+ x4 ^= key.k91;
+ sboxI5();
+ x1 ^= key.k84;
+ x3 ^= key.k85;
+ x4 ^= key.k86;
+ x2 ^= key.k87;
+ sboxI4();
+ x1 ^= key.k80;
+ x2 ^= key.k81;
+ x4 ^= key.k82;
+ x0 ^= key.k83;
+ sboxI3();
+ x0 ^= key.k76;
+ x1 ^= key.k77;
+ x4 ^= key.k78;
+ x2 ^= key.k79;
+ sboxI2();
+ x1 ^= key.k72;
+ x3 ^= key.k73;
+ x4 ^= key.k74;
+ x2 ^= key.k75;
+ sboxI1();
+ x0 ^= key.k68;
+ x1 ^= key.k69;
+ x2 ^= key.k70;
+ x4 ^= key.k71;
+ sboxI0();
+ x0 ^= key.k64;
+ x3 ^= key.k65;
+ x1 ^= key.k66;
+ x4 ^= key.k67;
+ sboxI7();
+ x1 = x3;
+ x3 = x4;
+ x4 = x2;
+
+ x3 ^= key.k60;
+ x0 ^= key.k61;
+ x1 ^= key.k62;
+ x4 ^= key.k63;
+ sboxI6();
+ x0 ^= key.k56;
+ x1 ^= key.k57;
+ x2 ^= key.k58;
+ x4 ^= key.k59;
+ sboxI5();
+ x1 ^= key.k52;
+ x3 ^= key.k53;
+ x4 ^= key.k54;
+ x2 ^= key.k55;
+ sboxI4();
+ x1 ^= key.k48;
+ x2 ^= key.k49;
+ x4 ^= key.k50;
+ x0 ^= key.k51;
+ sboxI3();
+ x0 ^= key.k44;
+ x1 ^= key.k45;
+ x4 ^= key.k46;
+ x2 ^= key.k47;
+ sboxI2();
+ x1 ^= key.k40;
+ x3 ^= key.k41;
+ x4 ^= key.k42;
+ x2 ^= key.k43;
+ sboxI1();
+ x0 ^= key.k36;
+ x1 ^= key.k37;
+ x2 ^= key.k38;
+ x4 ^= key.k39;
+ sboxI0();
+ x0 ^= key.k32;
+ x3 ^= key.k33;
+ x1 ^= key.k34;
+ x4 ^= key.k35;
+ sboxI7();
+ x1 = x3;
+ x3 = x4;
+ x4 = x2;
+
+ x3 ^= key.k28;
+ x0 ^= key.k29;
+ x1 ^= key.k30;
+ x4 ^= key.k31;
+ sboxI6();
+ x0 ^= key.k24;
+ x1 ^= key.k25;
+ x2 ^= key.k26;
+ x4 ^= key.k27;
+ sboxI5();
+ x1 ^= key.k20;
+ x3 ^= key.k21;
+ x4 ^= key.k22;
+ x2 ^= key.k23;
+ sboxI4();
+ x1 ^= key.k16;
+ x2 ^= key.k17;
+ x4 ^= key.k18;
+ x0 ^= key.k19;
+ sboxI3();
+ x0 ^= key.k12;
+ x1 ^= key.k13;
+ x4 ^= key.k14;
+ x2 ^= key.k15;
+ sboxI2();
+ x1 ^= key.k8;
+ x3 ^= key.k9;
+ x4 ^= key.k10;
+ x2 ^= key.k11;
+ sboxI1();
+ x0 ^= key.k4;
+ x1 ^= key.k5;
+ x2 ^= key.k6;
+ x4 ^= key.k7;
+ sboxI0();
+ x2 = x1;
+ x1 = x3;
+ x3 = x4;
+
+ x0 ^= key.k0;
+ x1 ^= key.k1;
+ x2 ^= key.k2;
+ x3 ^= key.k3;
+
+ out[o] = (byte) x0;
+ out[o + 1] = (byte) (x0 >>> 8);
+ out[o + 2] = (byte) (x0 >>> 16);
+ out[o + 3] = (byte) (x0 >>> 24);
+ out[o + 4] = (byte) x1;
+ out[o + 5] = (byte) (x1 >>> 8);
+ out[o + 6] = (byte) (x1 >>> 16);
+ out[o + 7] = (byte) (x1 >>> 24);
+ out[o + 8] = (byte) x2;
+ out[o + 9] = (byte) (x2 >>> 8);
+ out[o + 10] = (byte) (x2 >>> 16);
+ out[o + 11] = (byte) (x2 >>> 24);
+ out[o + 12] = (byte) x3;
+ out[o + 13] = (byte) (x3 >>> 8);
+ out[o + 14] = (byte) (x3 >>> 16);
+ out[o + 15] = (byte) (x3 >>> 24);
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ boolean result = super.selfTest(); // do symmetry tests
+ if (result)
+ {
+ result = testKat(KAT_KEY, KAT_CT);
+ }
+ valid = new Boolean(result);
+ }
+ return valid.booleanValue();
+ }
+
+ // Own methods. ----------------------------------------------------------
+
+ // These first few S-boxes operate directly on the "registers",
+ // x0..x4, and perform the linear transform.
+
+ private void sbox0()
+ {
+ x3 ^= x0;
+ x4 = x1;
+ x1 &= x3;
+ x4 ^= x2;
+ x1 ^= x0;
+ x0 |= x3;
+ x0 ^= x4;
+ x4 ^= x3;
+ x3 ^= x2;
+ x2 |= x1;
+ x2 ^= x4;
+ x4 ^= -1;
+ x4 |= x1;
+ x1 ^= x3;
+ x1 ^= x4;
+ x3 |= x0;
+ x1 ^= x3;
+ x4 ^= x3;
+
+ x1 = (x1 << 13) | (x1 >>> 19);
+ x4 ^= x1;
+ x3 = x1 << 3;
+ x2 = (x2 << 3) | (x2 >>> 29);
+ x4 ^= x2;
+ x0 ^= x2;
+ x4 = (x4 << 1) | (x4 >>> 31);
+ x0 ^= x3;
+ x0 = (x0 << 7) | (x0 >>> 25);
+ x3 = x4;
+ x1 ^= x4;
+ x3 <<= 7;
+ x1 ^= x0;
+ x2 ^= x0;
+ x2 ^= x3;
+ x1 = (x1 << 5) | (x1 >>> 27);
+ x2 = (x2 << 22) | (x2 >>> 10);
+ }
+
+ private void sbox1()
+ {
+ x4 = ~x4;
+ x3 = x1;
+ x1 ^= x4;
+ x3 |= x4;
+ x3 ^= x0;
+ x0 &= x1;
+ x2 ^= x3;
+ x0 ^= x4;
+ x0 |= x2;
+ x1 ^= x3;
+ x0 ^= x1;
+ x4 &= x2;
+ x1 |= x4;
+ x4 ^= x3;
+ x1 ^= x2;
+ x3 |= x0;
+ x1 ^= x3;
+ x3 = ~x3;
+ x4 ^= x0;
+ x3 &= x2;
+ x4 = ~x4;
+ x3 ^= x1;
+ x4 ^= x3;
+
+ x0 = (x0 << 13) | (x0 >>> 19);
+ x4 ^= x0;
+ x3 = x0 << 3;
+ x2 = (x2 << 3) | (x2 >>> 29);
+ x4 ^= x2;
+ x1 ^= x2;
+ x4 = (x4 << 1) | (x4 >>> 31);
+ x1 ^= x3;
+ x1 = (x1 << 7) | (x1 >>> 25);
+ x3 = x4;
+ x0 ^= x4;
+ x3 <<= 7;
+ x0 ^= x1;
+ x2 ^= x1;
+ x2 ^= x3;
+ x0 = (x0 << 5) | (x0 >>> 27);
+ x2 = (x2 << 22) | (x2 >>> 10);
+ }
+
+ private void sbox2()
+ {
+ x3 = x0;
+ x0 = x0 & x2;
+ x0 = x0 ^ x1;
+ x2 = x2 ^ x4;
+ x2 = x2 ^ x0;
+ x1 = x1 | x3;
+ x1 = x1 ^ x4;
+ x3 = x3 ^ x2;
+ x4 = x1;
+ x1 = x1 | x3;
+ x1 = x1 ^ x0;
+ x0 = x0 & x4;
+ x3 = x3 ^ x0;
+ x4 = x4 ^ x1;
+ x4 = x4 ^ x3;
+ x3 = ~x3;
+
+ x2 = (x2 << 13) | (x2 >>> 19);
+ x1 ^= x2;
+ x0 = x2 << 3;
+ x4 = (x4 << 3) | (x4 >>> 29);
+ x1 ^= x4;
+ x3 ^= x4;
+ x1 = (x1 << 1) | (x1 >>> 31);
+ x3 ^= x0;
+ x3 = (x3 << 7) | (x3 >>> 25);
+ x0 = x1;
+ x2 ^= x1;
+ x0 <<= 7;
+ x2 ^= x3;
+ x4 ^= x3;
+ x4 ^= x0;
+ x2 = (x2 << 5) | (x2 >>> 27);
+ x4 = (x4 << 22) | (x4 >>> 10);
+ }
+
+ private void sbox3()
+ {
+ x0 = x2;
+ x2 = x2 | x3;
+ x3 = x3 ^ x1;
+ x1 = x1 & x0;
+ x0 = x0 ^ x4;
+ x4 = x4 ^ x3;
+ x3 = x3 & x2;
+ x0 = x0 | x1;
+ x3 = x3 ^ x0;
+ x2 = x2 ^ x1;
+ x0 = x0 & x2;
+ x1 = x1 ^ x3;
+ x0 = x0 ^ x4;
+ x1 = x1 | x2;
+ x1 = x1 ^ x4;
+ x2 = x2 ^ x3;
+ x4 = x1;
+ x1 = x1 | x3;
+ x1 = x1 ^ x2;
+
+ x1 = (x1 << 13) | (x1 >>> 19);
+ x4 ^= x1;
+ x2 = x1 << 3;
+ x3 = (x3 << 3) | (x3 >>> 29);
+ x4 ^= x3;
+ x0 ^= x3;
+ x4 = (x4 << 1) | (x4 >>> 31);
+ x0 ^= x2;
+ x0 = (x0 << 7) | (x0 >>> 25);
+ x2 = x4;
+ x1 ^= x4;
+ x2 <<= 7;
+ x1 ^= x0;
+ x3 ^= x0;
+ x3 ^= x2;
+ x1 = (x1 << 5) | (x1 >>> 27);
+ x3 = (x3 << 22) | (x3 >>> 10);
+ }
+
+ private void sbox4()
+ {
+ x4 = x4 ^ x0;
+ x0 = ~x0;
+ x3 = x3 ^ x0;
+ x0 = x0 ^ x1;
+ x2 = x4;
+ x4 = x4 & x0;
+ x4 = x4 ^ x3;
+ x2 = x2 ^ x0;
+ x1 = x1 ^ x2;
+ x3 = x3 & x2;
+ x3 = x3 ^ x1;
+ x1 = x1 & x4;
+ x0 = x0 ^ x1;
+ x2 = x2 | x4;
+ x2 = x2 ^ x1;
+ x1 = x1 | x0;
+ x1 = x1 ^ x3;
+ x3 = x3 & x0;
+ x1 = ~x1;
+ x2 = x2 ^ x3;
+
+ x4 = (x4 << 13) | (x4 >>> 19);
+ x2 ^= x4;
+ x3 = x4 << 3;
+ x1 = (x1 << 3) | (x1 >>> 29);
+ x2 ^= x1;
+ x0 ^= x1;
+ x2 = (x2 << 1) | (x2 >>> 31);
+ x0 ^= x3;
+ x0 = (x0 << 7) | (x0 >>> 25);
+ x3 = x2;
+ x4 ^= x2;
+ x3 <<= 7;
+ x4 ^= x0;
+ x1 ^= x0;
+ x1 ^= x3;
+ x4 = (x4 << 5) | (x4 >>> 27);
+ x1 = (x1 << 22) | (x1 >>> 10);
+ }
+
+ private void sbox5()
+ {
+ x4 = x4 ^ x2;
+ x2 = x2 ^ x0;
+ x0 = ~x0;
+ x3 = x2;
+ x2 = x2 & x4;
+ x1 = x1 ^ x0;
+ x2 = x2 ^ x1;
+ x1 = x1 | x3;
+ x3 = x3 ^ x0;
+ x0 = x0 & x2;
+ x0 = x0 ^ x4;
+ x3 = x3 ^ x2;
+ x3 = x3 ^ x1;
+ x1 = x1 ^ x4;
+ x4 = x4 & x0;
+ x1 = ~x1;
+ x4 = x4 ^ x3;
+ x3 = x3 | x0;
+ x1 = x1 ^ x3;
+
+ x2 = (x2 << 13) | (x2 >>> 19);
+ x0 ^= x2;
+ x3 = x2 << 3;
+ x4 = (x4 << 3) | (x4 >>> 29);
+ x0 ^= x4;
+ x1 ^= x4;
+ x0 = (x0 << 1) | (x0 >>> 31);
+ x1 ^= x3;
+ x1 = (x1 << 7) | (x1 >>> 25);
+ x3 = x0;
+ x2 ^= x0;
+ x3 <<= 7;
+ x2 ^= x1;
+ x4 ^= x1;
+ x4 ^= x3;
+ x2 = (x2 << 5) | (x2 >>> 27);
+ x4 = (x4 << 22) | (x4 >>> 10);
+ }
+
+ private void sbox6()
+ {
+ x4 = ~x4;
+ x3 = x1;
+ x1 = x1 & x2;
+ x2 = x2 ^ x3;
+ x1 = x1 ^ x4;
+ x4 = x4 | x3;
+ x0 = x0 ^ x1;
+ x4 = x4 ^ x2;
+ x2 = x2 | x0;
+ x4 = x4 ^ x0;
+ x3 = x3 ^ x2;
+ x2 = x2 | x1;
+ x2 = x2 ^ x4;
+ x3 = x3 ^ x1;
+ x3 = x3 ^ x2;
+ x1 = ~x1;
+ x4 = x4 & x3;
+ x4 = x4 ^ x1;
+ x2 = (x2 << 13) | (x2 >>> 19);
+ x0 ^= x2;
+ x1 = x2 << 3;
+ x3 = (x3 << 3) | (x3 >>> 29);
+ x0 ^= x3;
+ x4 ^= x3;
+ x0 = (x0 << 1) | (x0 >>> 31);
+ x4 ^= x1;
+ x4 = (x4 << 7) | (x4 >>> 25);
+ x1 = x0;
+ x2 ^= x0;
+ x1 <<= 7;
+ x2 ^= x4;
+ x3 ^= x4;
+ x3 ^= x1;
+ x2 = (x2 << 5) | (x2 >>> 27);
+ x3 = (x3 << 22) | (x3 >>> 10);
+ }
+
+ private void sbox7()
+ {
+ x1 = x3;
+ x3 = x3 & x0;
+ x3 = x3 ^ x4;
+ x4 = x4 & x0;
+ x1 = x1 ^ x3;
+ x3 = x3 ^ x0;
+ x0 = x0 ^ x2;
+ x2 = x2 | x1;
+ x2 = x2 ^ x3;
+ x4 = x4 ^ x0;
+ x3 = x3 ^ x4;
+ x4 = x4 & x2;
+ x4 = x4 ^ x1;
+ x1 = x1 ^ x3;
+ x3 = x3 & x2;
+ x1 = ~x1;
+ x3 = x3 ^ x1;
+ x1 = x1 & x2;
+ x0 = x0 ^ x4;
+ x1 = x1 ^ x0;
+ x3 = (x3 << 13) | (x3 >>> 19);
+ x1 ^= x3;
+ x0 = x3 << 3;
+ x4 = (x4 << 3) | (x4 >>> 29);
+ x1 ^= x4;
+ x2 ^= x4;
+ x1 = (x1 << 1) | (x1 >>> 31);
+ x2 ^= x0;
+ x2 = (x2 << 7) | (x2 >>> 25);
+ x0 = x1;
+ x3 ^= x1;
+ x0 <<= 7;
+ x3 ^= x2;
+ x4 ^= x2;
+ x4 ^= x0;
+ x3 = (x3 << 5) | (x3 >>> 27);
+ x4 = (x4 << 22) | (x4 >>> 10);
+ }
+
+ /** The final S-box, with no transform. */
+ private void sbox7noLT()
+ {
+ x1 = x3;
+ x3 = x3 & x0;
+ x3 = x3 ^ x4;
+ x4 = x4 & x0;
+ x1 = x1 ^ x3;
+ x3 = x3 ^ x0;
+ x0 = x0 ^ x2;
+ x2 = x2 | x1;
+ x2 = x2 ^ x3;
+ x4 = x4 ^ x0;
+ x3 = x3 ^ x4;
+ x4 = x4 & x2;
+ x4 = x4 ^ x1;
+ x1 = x1 ^ x3;
+ x3 = x3 & x2;
+ x1 = ~x1;
+ x3 = x3 ^ x1;
+ x1 = x1 & x2;
+ x0 = x0 ^ x4;
+ x1 = x1 ^ x0;
+ }
+
+ private void sboxI7noLT()
+ {
+ x4 = x2;
+ x2 ^= x0;
+ x0 &= x3;
+ x2 = ~x2;
+ x4 |= x3;
+ x3 ^= x1;
+ x1 |= x0;
+ x0 ^= x2;
+ x2 &= x4;
+ x1 ^= x2;
+ x2 ^= x0;
+ x0 |= x2;
+ x3 &= x4;
+ x0 ^= x3;
+ x4 ^= x1;
+ x3 ^= x4;
+ x4 |= x0;
+ x3 ^= x2;
+ x4 ^= x2;
+ }
+
+ private void sboxI6()
+ {
+ x1 = (x1 >>> 22) | (x1 << 10);
+ x3 = (x3 >>> 5) | (x3 << 27);
+ x2 = x0;
+ x1 ^= x4;
+ x2 <<= 7;
+ x3 ^= x4;
+ x1 ^= x2;
+ x3 ^= x0;
+ x4 = (x4 >>> 7) | (x4 << 25);
+ x0 = (x0 >>> 1) | (x0 << 31);
+ x0 ^= x3;
+ x2 = x3 << 3;
+ x4 ^= x2;
+ x3 = (x3 >>> 13) | (x3 << 19);
+ x0 ^= x1;
+ x4 ^= x1;
+ x1 = (x1 >>> 3) | (x1 << 29);
+ x3 ^= x1;
+ x2 = x1;
+ x1 &= x3;
+ x2 ^= x4;
+ x1 = ~x1;
+ x4 ^= x0;
+ x1 ^= x4;
+ x2 |= x3;
+ x3 ^= x1;
+ x4 ^= x2;
+ x2 ^= x0;
+ x0 &= x4;
+ x0 ^= x3;
+ x3 ^= x4;
+ x3 |= x1;
+ x4 ^= x0;
+ x2 ^= x3;
+ }
+
+ private void sboxI5()
+ {
+ x2 = (x2 >>> 22) | (x2 << 10);
+ x0 = (x0 >>> 5) | (x0 << 27);
+ x3 = x1;
+ x2 ^= x4;
+ x3 <<= 7;
+ x0 ^= x4;
+ x2 ^= x3;
+ x0 ^= x1;
+ x4 = (x4 >>> 7) | (x4 << 25);
+ x1 = (x1 >>> 1) | (x1 << 31);
+ x1 ^= x0;
+ x3 = x0 << 3;
+ x4 ^= x3;
+ x0 = (x0 >>> 13) | (x0 << 19);
+ x1 ^= x2;
+ x4 ^= x2;
+ x2 = (x2 >>> 3) | (x2 << 29);
+ x1 = ~x1;
+ x3 = x4;
+ x2 ^= x1;
+ x4 |= x0;
+ x4 ^= x2;
+ x2 |= x1;
+ x2 &= x0;
+ x3 ^= x4;
+ x2 ^= x3;
+ x3 |= x0;
+ x3 ^= x1;
+ x1 &= x2;
+ x1 ^= x4;
+ x3 ^= x2;
+ x4 &= x3;
+ x3 ^= x1;
+ x4 ^= x0;
+ x4 ^= x3;
+ x3 = ~x3;
+ }
+
+ private void sboxI4()
+ {
+ x4 = (x4 >>> 22) | (x4 << 10);
+ x1 = (x1 >>> 5) | (x1 << 27);
+ x0 = x3;
+ x4 ^= x2;
+ x0 <<= 7;
+ x1 ^= x2;
+ x4 ^= x0;
+ x1 ^= x3;
+ x2 = (x2 >>> 7) | (x2 << 25);
+ x3 = (x3 >>> 1) | (x3 << 31);
+ x3 ^= x1;
+ x0 = x1 << 3;
+ x2 ^= x0;
+ x1 = (x1 >>> 13) | (x1 << 19);
+ x3 ^= x4;
+ x2 ^= x4;
+ x4 = (x4 >>> 3) | (x4 << 29);
+ x0 = x4;
+ x4 &= x2;
+ x4 ^= x3;
+ x3 |= x2;
+ x3 &= x1;
+ x0 ^= x4;
+ x0 ^= x3;
+ x3 &= x4;
+ x1 = ~x1;
+ x2 ^= x0;
+ x3 ^= x2;
+ x2 &= x1;
+ x2 ^= x4;
+ x1 ^= x3;
+ x4 &= x1;
+ x2 ^= x1;
+ x4 ^= x0;
+ x4 |= x2;
+ x2 ^= x1;
+ x4 ^= x3;
+ }
+
+ private void sboxI3()
+ {
+ x4 = (x4 >>> 22) | (x4 << 10);
+ x1 = (x1 >>> 5) | (x1 << 27);
+ x3 = x2;
+ x4 ^= x0;
+ x3 <<= 7;
+ x1 ^= x0;
+ x4 ^= x3;
+ x1 ^= x2;
+ x0 = (x0 >>> 7) | (x0 << 25);
+ x2 = (x2 >>> 1) | (x2 << 31);
+ x2 ^= x1;
+ x3 = x1 << 3;
+ x0 ^= x3;
+ x1 = (x1 >>> 13) | (x1 << 19);
+ x2 ^= x4;
+ x0 ^= x4;
+ x4 = (x4 >>> 3) | (x4 << 29);
+ x3 = x4;
+ x4 ^= x2;
+ x2 &= x4;
+ x2 ^= x1;
+ x1 &= x3;
+ x3 ^= x0;
+ x0 |= x2;
+ x0 ^= x4;
+ x1 ^= x3;
+ x4 ^= x1;
+ x1 |= x0;
+ x1 ^= x2;
+ x3 ^= x4;
+ x4 &= x0;
+ x2 |= x0;
+ x2 ^= x4;
+ x3 ^= x1;
+ x4 ^= x3;
+ }
+
+ private void sboxI2()
+ {
+ x4 = (x4 >>> 22) | (x4 << 10);
+ x0 = (x0 >>> 5) | (x0 << 27);
+ x3 = x1;
+ x4 ^= x2;
+ x3 <<= 7;
+ x0 ^= x2;
+ x4 ^= x3;
+ x0 ^= x1;
+ x2 = (x2 >>> 7) | (x2 << 25);
+ x1 = (x1 >>> 1) | (x1 << 31);
+ x1 ^= x0;
+ x3 = x0 << 3;
+ x2 ^= x3;
+ x0 = (x0 >>> 13) | (x0 << 19);
+ x1 ^= x4;
+ x2 ^= x4;
+ x4 = (x4 >>> 3) | (x4 << 29);
+ x4 ^= x2;
+ x2 ^= x0;
+ x3 = x2;
+ x2 &= x4;
+ x2 ^= x1;
+ x1 |= x4;
+ x1 ^= x3;
+ x3 &= x2;
+ x4 ^= x2;
+ x3 &= x0;
+ x3 ^= x4;
+ x4 &= x1;
+ x4 |= x0;
+ x2 = ~x2;
+ x4 ^= x2;
+ x0 ^= x2;
+ x0 &= x1;
+ x2 ^= x3;
+ x2 ^= x0;
+ }
+
+ private void sboxI1()
+ {
+ x4 = (x4 >>> 22) | (x4 << 10);
+ x1 = (x1 >>> 5) | (x1 << 27);
+ x0 = x3;
+ x4 ^= x2;
+ x0 <<= 7;
+ x1 ^= x2;
+ x4 ^= x0;
+ x1 ^= x3;
+ x2 = (x2 >>> 7) | (x2 << 25);
+ x3 = (x3 >>> 1) | (x3 << 31);
+ x3 ^= x1;
+ x0 = x1 << 3;
+ x2 ^= x0;
+ x1 = (x1 >>> 13) | (x1 << 19);
+ x3 ^= x4;
+ x2 ^= x4;
+ x4 = (x4 >>> 3) | (x4 << 29);
+ x0 = x3;
+ x3 ^= x2;
+ x2 &= x3;
+ x0 ^= x4;
+ x2 ^= x1;
+ x1 |= x3;
+ x4 ^= x2;
+ x1 ^= x0;
+ x1 |= x4;
+ x3 ^= x2;
+ x1 ^= x3;
+ x3 |= x2;
+ x3 ^= x1;
+ x0 = ~x0;
+ x0 ^= x3;
+ x3 |= x1;
+ x3 ^= x1;
+ x3 |= x0;
+ x2 ^= x3;
+ }
+
+ private void sboxI0()
+ {
+ x2 = (x2 >>> 22) | (x2 << 10);
+ x0 = (x0 >>> 5) | (x0 << 27);
+ x3 = x1;
+ x2 ^= x4;
+ x3 <<= 7;
+ x0 ^= x4;
+ x2 ^= x3;
+ x0 ^= x1;
+ x4 = (x4 >>> 7) | (x4 << 25);
+ x1 = (x1 >>> 1) | (x1 << 31);
+ x1 ^= x0;
+ x3 = x0 << 3;
+ x4 ^= x3;
+ x0 = (x0 >>> 13) | (x0 << 19);
+ x1 ^= x2;
+ x4 ^= x2;
+ x2 = (x2 >>> 3) | (x2 << 29);
+ x2 = ~x2;
+ x3 = x1;
+ x1 |= x0;
+ x3 = ~x3;
+ x1 ^= x2;
+ x2 |= x3;
+ x1 ^= x4;
+ x0 ^= x3;
+ x2 ^= x0;
+ x0 &= x4;
+ x3 ^= x0;
+ x0 |= x1;
+ x0 ^= x2;
+ x4 ^= x3;
+ x2 ^= x1;
+ x4 ^= x0;
+ x4 ^= x1;
+ x2 &= x4;
+ x3 ^= x2;
+ }
+
+ private void sboxI7()
+ {
+ x1 = (x1 >>> 22) | (x1 << 10);
+ x0 = (x0 >>> 5) | (x0 << 27);
+ x2 = x3;
+ x1 ^= x4;
+ x2 <<= 7;
+ x0 ^= x4;
+ x1 ^= x2;
+ x0 ^= x3;
+ x4 = (x4 >>> 7) | (x4 << 25);
+ x3 = (x3 >>> 1) | (x3 << 31);
+ x3 ^= x0;
+ x2 = x0 << 3;
+ x4 ^= x2;
+ x0 = (x0 >>> 13) | (x0 << 19);
+ x3 ^= x1;
+ x4 ^= x1;
+ x1 = (x1 >>> 3) | (x1 << 29);
+ x2 = x1;
+ x1 ^= x0;
+ x0 &= x4;
+ x1 = ~x1;
+ x2 |= x4;
+ x4 ^= x3;
+ x3 |= x0;
+ x0 ^= x1;
+ x1 &= x2;
+ x3 ^= x1;
+ x1 ^= x0;
+ x0 |= x1;
+ x4 &= x2;
+ x0 ^= x4;
+ x2 ^= x3;
+ x4 ^= x2;
+ x2 |= x0;
+ x4 ^= x1;
+ x2 ^= x1;
+ }
+
+ // These S-Box functions are used in the key setup.
+
+ /** S-Box 0. */
+ private void sbox0(int r0, int r1, int r2, int r3)
+ {
+ int r4 = r1 ^ r2;
+ r3 ^= r0;
+ r1 = r1 & r3 ^ r0;
+ r0 = (r0 | r3) ^ r4;
+ r4 ^= r3;
+ r3 ^= r2;
+ r2 = (r2 | r1) ^ r4;
+ r4 = ~r4 | r1;
+ r1 ^= r3 ^ r4;
+ r3 |= r0;
+ x0 = r1 ^ r3;
+ x1 = r4 ^ r3;
+ x2 = r2;
+ x3 = r0;
+ }
+
+ /** S-Box 1. */
+ private void sbox1(int r0, int r1, int r2, int r3)
+ {
+ r0 = ~r0;
+ int r4 = r0;
+ r2 = ~r2;
+ r0 &= r1;
+ r2 ^= r0;
+ r0 |= r3;
+ r3 ^= r2;
+ r1 ^= r0;
+ r0 ^= r4;
+ r4 |= r1;
+ r1 ^= r3;
+ r2 = (r2 | r0) & r4;
+ r0 ^= r1;
+ x0 = r2;
+ x1 = r0 & r2 ^ r4;
+ x2 = r3;
+ x3 = r1 & r2 ^ r0;
+ }
+
+ /** S-Box 2. */
+ private void sbox2(int r0, int r1, int r2, int r3)
+ {
+ int r4 = r0;
+ r0 = r0 & r2 ^ r3;
+ r2 = r2 ^ r1 ^ r0;
+ r3 = (r3 | r4) ^ r1;
+ r4 ^= r2;
+ r1 = r3;
+ r3 = (r3 | r4) ^ r0;
+ r0 &= r1;
+ r4 ^= r0;
+ x0 = r2;
+ x1 = r3;
+ x2 = r1 ^ r3 ^ r4;
+ x3 = ~r4;
+ }
+
+ /** S-Box 3. */
+ private void sbox3(int r0, int r1, int r2, int r3)
+ {
+ int r4 = r0;
+ r0 |= r3;
+ r3 ^= r1;
+ r1 &= r4;
+ r4 = r4 ^ r2 | r1;
+ r2 ^= r3;
+ r3 = r3 & r0 ^ r4;
+ r0 ^= r1;
+ r4 = r4 & r0 ^ r2;
+ r1 = (r1 ^ r3 | r0) ^ r2;
+ r0 ^= r3;
+ x0 = (r1 | r3) ^ r0;
+ x1 = r1;
+ x2 = r3;
+ x3 = r4;
+ }
+
+ /** S-Box 4. */
+ private void sbox4(int r0, int r1, int r2, int r3)
+ {
+ r1 ^= r3;
+ int r4 = r1;
+ r3 = ~r3;
+ r2 ^= r3;
+ r3 ^= r0;
+ r1 = r1 & r3 ^ r2;
+ r4 ^= r3;
+ r0 ^= r4;
+ r2 = r2 & r4 ^ r0;
+ r0 &= r1;
+ r3 ^= r0;
+ r4 = (r4 | r1) ^ r0;
+ x0 = r1;
+ x1 = r4 ^ (r2 & r3);
+ x2 = ~((r0 | r3) ^ r2);
+ x3 = r3;
+ }
+
+ /** S-Box 5. */
+ private void sbox5(int r0, int r1, int r2, int r3)
+ {
+ r0 ^= r1;
+ r1 ^= r3;
+ int r4 = r1;
+ r3 = ~r3;
+ r1 &= r0;
+ r2 ^= r3;
+ r1 ^= r2;
+ r2 |= r4;
+ r4 ^= r3;
+ r3 = r3 & r1 ^ r0;
+ r4 = r4 ^ r1 ^ r2;
+ x0 = r1;
+ x1 = r3;
+ x2 = r0 & r3 ^ r4;
+ x3 = ~(r2 ^ r0) ^ (r4 | r3);
+ }
+
+ /** S-Box 6. */
+ private void sbox6(int r0, int r1, int r2, int r3)
+ {
+ int r4 = r3;
+ r2 = ~r2;
+ r3 = r3 & r0 ^ r2;
+ r0 ^= r4;
+ r2 = (r2 | r4) ^ r0;
+ r1 ^= r3;
+ r0 |= r1;
+ r2 ^= r1;
+ r4 ^= r0;
+ r0 = (r0 | r3) ^ r2;
+ r4 = r4 ^ r3 ^ r0;
+ x0 = r0;
+ x1 = r1;
+ x2 = r4;
+ x3 = r2 & r4 ^ ~r3;
+ }
+
+ /** S-Box 7. */
+ private void sbox7(int r0, int r1, int r2, int r3)
+ {
+ int r4 = r1;
+ r1 = (r1 | r2) ^ r3;
+ r4 ^= r2;
+ r2 ^= r1;
+ r3 = (r3 | r4) & r0;
+ r4 ^= r2;
+ r3 ^= r1;
+ r1 = (r1 | r4) ^ r0;
+ r0 = (r0 | r4) ^ r2;
+ r1 ^= r4;
+ r2 ^= r1;
+ x0 = r4 ^ (~r2 | r0);
+ x1 = r3;
+ x2 = r1 & r0 ^ r4;
+ x3 = r0;
+ }
+
+ // Inner classes.
+ // -----------------------------------------------------------------------
+
+ private class Key implements Cloneable
+ {
+
+ // Constants and variables.
+ // --------------------------------------------------------------------
+
+ int k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15,
+ k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29,
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43,
+ k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57,
+ k58, k59, k60, k61, k62, k63, k64, k65, k66, k67, k68, k69, k70, k71,
+ k72, k73, k74, k75, k76, k77, k78, k79, k80, k81, k82, k83, k84, k85,
+ k86, k87, k88, k89, k90, k91, k92, k93, k94, k95, k96, k97, k98, k99,
+ k100, k101, k102, k103, k104, k105, k106, k107, k108, k109, k110, k111,
+ k112, k113, k114, k115, k116, k117, k118, k119, k120, k121, k122, k123,
+ k124, k125, k126, k127, k128, k129, k130, k131;
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ Key()
+ {
+ }
+
+ /** Cloning constructor. */
+ private Key(Key that)
+ {
+ this.k0 = that.k0;
+ this.k1 = that.k1;
+ this.k2 = that.k2;
+ this.k3 = that.k3;
+ this.k4 = that.k4;
+ this.k5 = that.k5;
+ this.k6 = that.k6;
+ this.k7 = that.k7;
+ this.k8 = that.k8;
+ this.k9 = that.k9;
+ this.k10 = that.k10;
+ this.k11 = that.k11;
+ this.k12 = that.k12;
+ this.k13 = that.k13;
+ this.k14 = that.k14;
+ this.k15 = that.k15;
+ this.k16 = that.k16;
+ this.k17 = that.k17;
+ this.k18 = that.k18;
+ this.k19 = that.k19;
+ this.k20 = that.k20;
+ this.k21 = that.k21;
+ this.k22 = that.k22;
+ this.k23 = that.k23;
+ this.k24 = that.k24;
+ this.k25 = that.k25;
+ this.k26 = that.k26;
+ this.k27 = that.k27;
+ this.k28 = that.k28;
+ this.k29 = that.k29;
+ this.k30 = that.k30;
+ this.k31 = that.k31;
+ this.k32 = that.k32;
+ this.k33 = that.k33;
+ this.k34 = that.k34;
+ this.k35 = that.k35;
+ this.k36 = that.k36;
+ this.k37 = that.k37;
+ this.k38 = that.k38;
+ this.k39 = that.k39;
+ this.k40 = that.k40;
+ this.k41 = that.k41;
+ this.k42 = that.k42;
+ this.k43 = that.k43;
+ this.k44 = that.k44;
+ this.k45 = that.k45;
+ this.k46 = that.k46;
+ this.k47 = that.k47;
+ this.k48 = that.k48;
+ this.k49 = that.k49;
+ this.k50 = that.k50;
+ this.k51 = that.k51;
+ this.k52 = that.k52;
+ this.k53 = that.k53;
+ this.k54 = that.k54;
+ this.k55 = that.k55;
+ this.k56 = that.k56;
+ this.k57 = that.k57;
+ this.k58 = that.k58;
+ this.k59 = that.k59;
+ this.k60 = that.k60;
+ this.k61 = that.k61;
+ this.k62 = that.k62;
+ this.k63 = that.k63;
+ this.k64 = that.k64;
+ this.k65 = that.k65;
+ this.k66 = that.k66;
+ this.k67 = that.k67;
+ this.k68 = that.k68;
+ this.k69 = that.k69;
+ this.k70 = that.k70;
+ this.k71 = that.k71;
+ this.k72 = that.k72;
+ this.k73 = that.k73;
+ this.k74 = that.k74;
+ this.k75 = that.k75;
+ this.k76 = that.k76;
+ this.k77 = that.k77;
+ this.k78 = that.k78;
+ this.k79 = that.k79;
+ this.k80 = that.k80;
+ this.k81 = that.k81;
+ this.k82 = that.k82;
+ this.k83 = that.k83;
+ this.k84 = that.k84;
+ this.k85 = that.k85;
+ this.k86 = that.k86;
+ this.k87 = that.k87;
+ this.k88 = that.k88;
+ this.k89 = that.k89;
+ this.k90 = that.k90;
+ this.k91 = that.k91;
+ this.k92 = that.k92;
+ this.k93 = that.k93;
+ this.k94 = that.k94;
+ this.k95 = that.k95;
+ this.k96 = that.k96;
+ this.k97 = that.k97;
+ this.k98 = that.k98;
+ this.k99 = that.k99;
+ this.k100 = that.k100;
+ this.k101 = that.k101;
+ this.k102 = that.k102;
+ this.k103 = that.k103;
+ this.k104 = that.k104;
+ this.k105 = that.k105;
+ this.k106 = that.k106;
+ this.k107 = that.k107;
+ this.k108 = that.k108;
+ this.k109 = that.k109;
+ this.k110 = that.k110;
+ this.k111 = that.k111;
+ this.k112 = that.k112;
+ this.k113 = that.k113;
+ this.k114 = that.k114;
+ this.k115 = that.k115;
+ this.k116 = that.k116;
+ this.k117 = that.k117;
+ this.k118 = that.k118;
+ this.k119 = that.k119;
+ this.k120 = that.k120;
+ this.k121 = that.k121;
+ this.k122 = that.k122;
+ this.k123 = that.k123;
+ this.k124 = that.k124;
+ this.k125 = that.k125;
+ this.k126 = that.k126;
+ this.k127 = that.k127;
+ this.k128 = that.k128;
+ this.k129 = that.k129;
+ this.k130 = that.k130;
+ this.k131 = that.k131;
+ }
+
+ // Cloneable interface implementation.
+ // --------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new Key(this);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/Square.java b/gnu/javax/crypto/cipher/Square.java
new file mode 100644
index 000000000..15cb8b536
--- /dev/null
+++ b/gnu/javax/crypto/cipher/Square.java
@@ -0,0 +1,520 @@
+/* Square.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>Square is a 128-bit key, 128-bit block cipher algorithm developed by Joan
+ * Daemen, Lars Knudsen and Vincent Rijmen.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.esat.kuleuven.ac.be/~rijmen/square/">The block
+ * cipher Square</a>.<br>
+ * <a href="mailto:daemen.j@protonworld.com">Joan Daemen</a>,
+ * <a href="mailto:lars.knudsen@esat.kuleuven.ac.be">Lars Knudsen</a> and
+ * <a href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a>.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class Square extends BaseCipher
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes
+
+ private static final int DEFAULT_KEY_SIZE = 16; // in bytes
+
+ private static final int ROUNDS = 8;
+
+ private static final int ROOT = 0x1F5; // for generating GF(2**8)
+
+ private static final int[] OFFSET = new int[ROUNDS];
+
+ private static final String Sdata = "\uB1CE\uC395\u5AAD\uE702\u4D44\uFB91\u0C87\uA150"
+ + "\uCB67\u54DD\u468F\uE14E\uF0FD\uFCEB\uF9C4\u1A6E"
+ + "\u5EF5\uCC8D\u1C56\u43FE\u0761\uF875\u59FF\u0322"
+ + "\u8AD1\u13EE\u8800\u0E34\u1580\u94E3\uEDB5\u5323"
+ + "\u4B47\u17A7\u9035\uABD8\uB8DF\u4F57\u9A92\uDB1B"
+ + "\u3CC8\u9904\u8EE0\uD77D\u85BB\u402C\u3A45\uF142"
+ + "\u6520\u4118\u7225\u9370\u3605\uF20B\uA379\uEC08"
+ + "\u2731\u32B6\u7CB0\u0A73\u5B7B\uB781\uD20D\u6A26"
+ + "\u9E58\u9C83\u74B3\uAC30\u7A69\u770F\uAE21\uDED0"
+ + "\u2E97\u10A4\u98A8\uD468\u2D62\u296D\u1649\u76C7"
+ + "\uE8C1\u9637\uE5CA\uF4E9\u6312\uC2A6\u14BC\uD328"
+ + "\uAF2F\uE624\u52C6\uA009\uBD8C\uCF5D\u115F\u01C5"
+ + "\u9F3D\uA29B\uC93B\uBE51\u191F\u3F5C\uB2EF\u4ACD"
+ + "\uBFBA\u6F64\uD9F3\u3EB4\uAADC\uD506\uC07E\uF666"
+ + "\u6C84\u7138\uB91D\u7F9D\u488B\u2ADA\uA533\u8239"
+ + "\uD678\u86FA\uE42B\uA91E\u8960\u6BEA\u554C\uF7E2";
+
+ /** Substitution boxes for encryption and decryption. */
+ private static final byte[] Se = new byte[256];
+
+ private static final byte[] Sd = new byte[256];
+
+ /** Transposition boxes for encryption and decryption. */
+ private static final int[] Te = new int[256];
+
+ private static final int[] Td = new int[256];
+
+ /**
+ * KAT vector (from ecb_vk):
+ * I=87
+ * KEY=00000000000000000000020000000000
+ * CT=A9DF031B4E25E89F527EFFF89CB0BEBA
+ */
+ private static final byte[] KAT_KEY = Util.toBytesFromString("00000000000000000000020000000000");
+
+ private static final byte[] KAT_CT = Util.toBytesFromString("A9DF031B4E25E89F527EFFF89CB0BEBA");
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ // Static code - to intialise lookup tables
+ // -------------------------------------------------------------------------
+
+ static
+ {
+ int i, j;
+ /*
+ // Generate exp and log tables used in multiplication over GF(2 ** m)
+ byte[] exp = new byte[256];
+ byte[] log = new byte[256];
+
+ exp[0] = 1;
+ for (i = 1; i < 256; i++) {
+ j = exp[i - 1] << 1;
+ if ((j & 0x100) != 0) {
+ j ^= ROOT; // reduce j (mod ROOT)
+ }
+
+ exp[i] = (byte) j;
+ log[j & 0xFF] = (byte) i;
+ }
+
+ // Compute the substitution box Se[] and its inverse Sd[] based on
+ // F(x) = x**{-1} plus affine transform of the output.
+ Se[0] = 0;
+ Se[1] = 1;
+ for (i = 2; i < 256; i++) {
+ Se[i] = exp[(255 - log[i]) & 0xFF];
+ }
+
+ // Let Se[i] be represented as an 8-row vector V over GF(2); the affine
+ // transformation is A * V + T, where the rows of the 8 x 8 matrix A are
+ // contained in trans[0]...trans[7] and the 8-row vector T is contained
+ // in 0xB1.
+ int[] trans = new int[] {0x01, 0x03, 0x05, 0x0F, 0x1F, 0x3D, 0x7B, 0xD6};
+ int u, v;
+ for (i = 0; i < 256; i++) {
+ v = 0xB1; // affine part of the transform
+ for (j = 0; j < 8; j++) {
+ u = Se[i] & trans[j] & 0xFF; // column-wise mult. over GF(2)
+ u ^= u >>> 4; // sum of all bits of u over GF(2)
+ u ^= u >>> 2;
+ u ^= u >>> 1;
+ u &= 1;
+ v ^= u << j; // row alignment of the result
+ }
+ Se[i] = (byte) v;
+ Sd[v] = (byte) i; // inverse substitution box
+ }
+
+ System.out.println("Se="+Util.toUnicodeString(Se));
+ System.out.println("Sd="+Util.toUnicodeString(Sd));
+ */
+ /**/
+ // re-construct Se box values
+ int limit = Sdata.length();
+ char c1;
+ for (i = 0, j = 0; i < limit; i++)
+ {
+ c1 = Sdata.charAt(i);
+ Se[j++] = (byte) (c1 >>> 8);
+ Se[j++] = (byte) c1;
+ }
+
+ // compute Sd box values
+ for (i = 0; i < 256; i++)
+ {
+ Sd[Se[i] & 0xFF] = (byte) i;
+ }
+
+ // generate OFFSET values
+ OFFSET[0] = 1;
+ for (i = 1; i < ROUNDS; i++)
+ {
+ OFFSET[i] = mul(OFFSET[i - 1], 2);
+ OFFSET[i - 1] <<= 24;
+ }
+
+ OFFSET[ROUNDS - 1] <<= 24;
+
+ // generate Te and Td boxes if we're not reading their values
+ // Notes:
+ // (1) The function mul() computes the product of two elements of GF(2**8)
+ // with ROOT as reduction polynomial.
+ // (2) the values used in computing the Te and Td are the GF(2**8)
+ // coefficients of the diffusion polynomial c(x) and its inverse
+ // (modulo x**4 + 1) d(x), defined in sections 2.1 and 4 of the Square
+ // paper.
+ for (i = 0; i < 256; i++)
+ {
+ j = Se[i] & 0xFF;
+ Te[i] = (Se[i & 3] == 0) ? 0 : mul(j, 2) << 24 | j << 16 | j << 8
+ | mul(j, 3);
+
+ j = Sd[i] & 0xFF;
+ Td[i] = (Sd[i & 3] == 0) ? 0 : mul(j, 14) << 24 | mul(j, 9) << 16
+ | mul(j, 13) << 8 | mul(j, 11);
+ }
+ /**/
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Square()
+ {
+ super(Registry.SQUARE_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ private static void square(byte[] in, int i, byte[] out, int j, int[][] K,
+ int[] T, byte[] S)
+ {
+ int a = ((in[i++]) << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ K[0][0];
+ int b = ((in[i++]) << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ K[0][1];
+ int c = ((in[i++]) << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF))
+ ^ K[0][2];
+ int d = ((in[i++]) << 24 | (in[i++] & 0xFF) << 16 | (in[i++] & 0xFF) << 8 | (in[i] & 0xFF))
+ ^ K[0][3];
+
+ int r, aa, bb, cc, dd;
+ for (r = 1; r < ROUNDS; r++)
+ { // R - 1 full rounds
+ aa = T[(a >>> 24)] ^ rot32R(T[(b >>> 24)], 8)
+ ^ rot32R(T[(c >>> 24)], 16) ^ rot32R(T[(d >>> 24)], 24) ^ K[r][0];
+ bb = T[(a >>> 16) & 0xFF] ^ rot32R(T[(b >>> 16) & 0xFF], 8)
+ ^ rot32R(T[(c >>> 16) & 0xFF], 16)
+ ^ rot32R(T[(d >>> 16) & 0xFF], 24) ^ K[r][1];
+ cc = T[(a >>> 8) & 0xFF] ^ rot32R(T[(b >>> 8) & 0xFF], 8)
+ ^ rot32R(T[(c >>> 8) & 0xFF], 16)
+ ^ rot32R(T[(d >>> 8) & 0xFF], 24) ^ K[r][2];
+ dd = T[a & 0xFF] ^ rot32R(T[b & 0xFF], 8) ^ rot32R(T[c & 0xFF], 16)
+ ^ rot32R(T[d & 0xFF], 24) ^ K[r][3];
+
+ a = aa;
+ b = bb;
+ c = cc;
+ d = dd;
+ }
+
+ // last round (diffusion becomes only transposition)
+ aa = ((S[(a >>> 24)]) << 24 | (S[(b >>> 24)] & 0xFF) << 16
+ | (S[(c >>> 24)] & 0xFF) << 8 | (S[(d >>> 24)] & 0xFF))
+ ^ K[r][0];
+ bb = ((S[(a >>> 16) & 0xFF]) << 24 | (S[(b >>> 16) & 0xFF] & 0xFF) << 16
+ | (S[(c >>> 16) & 0xFF] & 0xFF) << 8 | (S[(d >>> 16) & 0xFF] & 0xFF))
+ ^ K[r][1];
+ cc = ((S[(a >>> 8) & 0xFF]) << 24 | (S[(b >>> 8) & 0xFF] & 0xFF) << 16
+ | (S[(c >>> 8) & 0xFF] & 0xFF) << 8 | (S[(d >>> 8) & 0xFF] & 0xFF))
+ ^ K[r][2];
+ dd = ((S[a & 0xFF]) << 24 | (S[b & 0xFF] & 0xFF) << 16
+ | (S[c & 0xFF] & 0xFF) << 8 | (S[d & 0xFF] & 0xFF))
+ ^ K[r][3];
+
+ out[j++] = (byte) (aa >>> 24);
+ out[j++] = (byte) (aa >>> 16);
+ out[j++] = (byte) (aa >>> 8);
+ out[j++] = (byte) aa;
+ out[j++] = (byte) (bb >>> 24);
+ out[j++] = (byte) (bb >>> 16);
+ out[j++] = (byte) (bb >>> 8);
+ out[j++] = (byte) bb;
+ out[j++] = (byte) (cc >>> 24);
+ out[j++] = (byte) (cc >>> 16);
+ out[j++] = (byte) (cc >>> 8);
+ out[j++] = (byte) cc;
+ out[j++] = (byte) (dd >>> 24);
+ out[j++] = (byte) (dd >>> 16);
+ out[j++] = (byte) (dd >>> 8);
+ out[j] = (byte) dd;
+ }
+
+ /**
+ * <p>Applies the Theta function to an input <i>in</i> in order to produce in
+ * <i>out</i> an internal session sub-key.</p>
+ *
+ * <p>Both <i>in</i> and <i>out</i> are arrays of four ints.</p>
+ *
+ * <p>Pseudo-code is:</p>
+ *
+ * <pre>
+ * for (i = 0; i < 4; i++) {
+ * out[i] = 0;
+ * for (j = 0, n = 24; j < 4; j++, n -= 8) {
+ * k = mul(in[i] >>> 24, G[0][j]) ^
+ * mul(in[i] >>> 16, G[1][j]) ^
+ * mul(in[i] >>> 8, G[2][j]) ^
+ * mul(in[i] , G[3][j]);
+ * out[i] ^= k << n;
+ * }
+ * }
+ * </pre>
+ */
+ private static void transform(int[] in, int[] out)
+ {
+ int l3, l2, l1, l0, m;
+ for (int i = 0; i < 4; i++)
+ {
+ l3 = in[i];
+ l2 = l3 >>> 8;
+ l1 = l3 >>> 16;
+ l0 = l3 >>> 24;
+ m = ((mul(l0, 2) ^ mul(l1, 3) ^ l2 ^ l3) & 0xFF) << 24;
+ m ^= ((l0 ^ mul(l1, 2) ^ mul(l2, 3) ^ l3) & 0xFF) << 16;
+ m ^= ((l0 ^ l1 ^ mul(l2, 2) ^ mul(l3, 3)) & 0xFF) << 8;
+ m ^= ((mul(l0, 3) ^ l1 ^ l2 ^ mul(l3, 2)) & 0xFF);
+ out[i] = m;
+ }
+ }
+
+ /**
+ * <p>Left rotate a 32-bit chunk.</p>
+ *
+ * @param x the 32-bit data to rotate
+ * @param s number of places to left-rotate by
+ * @return the newly permutated value.
+ */
+ private static int rot32L(int x, int s)
+ {
+ return x << s | x >>> (32 - s);
+ }
+
+ /**
+ * <p>Right rotate a 32-bit chunk.</p>
+ *
+ * @param x the 32-bit data to rotate
+ * @param s number of places to right-rotate by
+ * @return the newly permutated value.
+ */
+ private static int rot32R(int x, int s)
+ {
+ return x >>> s | x << (32 - s);
+ }
+
+ /**
+ * <p>Returns the product of two binary numbers a and b, using the generator
+ * ROOT as the modulus: p = (a * b) mod ROOT. ROOT Generates a suitable
+ * Galois Field in GF(2**8).</p>
+ *
+ * <p>For best performance call it with abs(b) &lt; abs(a).</p>
+ *
+ * @param a operand for multiply.
+ * @param b operand for multiply.
+ * @return the result of (a * b) % ROOT.
+ */
+ private static final int mul(int a, int b)
+ {
+ if (a == 0)
+ {
+ return 0;
+ }
+
+ a &= 0xFF;
+ b &= 0xFF;
+ int result = 0;
+ while (b != 0)
+ {
+ if ((b & 0x01) != 0)
+ {
+ result ^= a;
+ }
+
+ b >>>= 1;
+ a <<= 1;
+ if (a > 0xFF)
+ {
+ a ^= ROOT;
+ }
+ }
+ return result & 0xFF;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ Square result = new Square();
+ result.currentBlockSize = this.currentBlockSize;
+
+ return result;
+ }
+
+ // IBlockCipherSpi interface implementation --------------------------------
+
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(DEFAULT_BLOCK_SIZE));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(DEFAULT_KEY_SIZE));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Object makeKey(byte[] uk, int bs) throws InvalidKeyException
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (uk == null)
+ {
+ throw new InvalidKeyException("Empty key");
+ }
+ if (uk.length != DEFAULT_KEY_SIZE)
+ {
+ throw new InvalidKeyException("Key is not 128-bit.");
+ }
+
+ int[][] Ke = new int[ROUNDS + 1][4];
+ int[][] Kd = new int[ROUNDS + 1][4];
+ int[][] tK = new int[ROUNDS + 1][4];
+ int i = 0;
+
+ Ke[0][0] = (uk[i++] & 0xFF) << 24 | (uk[i++] & 0xFF) << 16
+ | (uk[i++] & 0xFF) << 8 | (uk[i++] & 0xFF);
+ tK[0][0] = Ke[0][0];
+ Ke[0][1] = (uk[i++] & 0xFF) << 24 | (uk[i++] & 0xFF) << 16
+ | (uk[i++] & 0xFF) << 8 | (uk[i++] & 0xFF);
+ tK[0][1] = Ke[0][1];
+ Ke[0][2] = (uk[i++] & 0xFF) << 24 | (uk[i++] & 0xFF) << 16
+ | (uk[i++] & 0xFF) << 8 | (uk[i++] & 0xFF);
+ tK[0][2] = Ke[0][2];
+ Ke[0][3] = (uk[i++] & 0xFF) << 24 | (uk[i++] & 0xFF) << 16
+ | (uk[i++] & 0xFF) << 8 | (uk[i] & 0xFF);
+ tK[0][3] = Ke[0][3];
+
+ int j;
+ for (i = 1, j = 0; i < ROUNDS + 1; i++, j++)
+ {
+ tK[i][0] = tK[j][0] ^ rot32L(tK[j][3], 8) ^ OFFSET[j];
+ tK[i][1] = tK[j][1] ^ tK[i][0];
+ tK[i][2] = tK[j][2] ^ tK[i][1];
+ tK[i][3] = tK[j][3] ^ tK[i][2];
+
+ System.arraycopy(tK[i], 0, Ke[i], 0, 4);
+
+ transform(Ke[j], Ke[j]);
+ }
+
+ for (i = 0; i < ROUNDS; i++)
+ {
+ System.arraycopy(tK[ROUNDS - i], 0, Kd[i], 0, 4);
+ }
+
+ transform(tK[0], Kd[ROUNDS]);
+
+ return new Object[] { Ke, Kd };
+ }
+
+ public void encrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[][] K = (int[][]) ((Object[]) k)[0];
+ square(in, i, out, j, K, Te, Se);
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int j, Object k, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ int[][] K = (int[][]) ((Object[]) k)[1];
+ square(in, i, out, j, K, Td, Sd);
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ boolean result = super.selfTest(); // do symmetry tests
+ if (result)
+ {
+ result = testKat(KAT_KEY, KAT_CT);
+ }
+ valid = new Boolean(result);
+ }
+ return valid.booleanValue();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/TripleDES.java b/gnu/javax/crypto/cipher/TripleDES.java
new file mode 100644
index 000000000..9b44c9ca7
--- /dev/null
+++ b/gnu/javax/crypto/cipher/TripleDES.java
@@ -0,0 +1,196 @@
+/* TripleDES.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.security.InvalidKeyException;
+
+/**
+ * Triple-DES, 3DES, or DESede is a <i>combined cipher</i> that uses
+ * three iterations of the Data Encryption Standard cipher to improve
+ * the security (at the cost of speed) of plain DES.
+ *
+ * <p>Triple-DES runs the DES algorithm three times with three
+ * independent 56 bit keys. To encrypt:</p>
+ *
+ * <blockquote><i>C<sub>i</sub> =
+ * E<sub>k3</sub> ( E<sub>k2</sub><sup>-1</sup> ( E<sub>k1</sub> ( P<sub>i</sub> )))</i></blockquote>
+ *
+ * <p>And to decrypt:</p>
+ *
+ * <blockquote><i>P<sub>i</sub> =
+ * E<sub>k1</sub><sup>-1</sup> ( E<sub>k2</sub> ( E<sub>k3</sub><sup>-1</sup> ( C<sub>i</sub> )))</i></blockquote>
+ *
+ * <p>(The "ede" comes from the encryption operation, which runs
+ * Encrypt-Decrypt-Encrypt)</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms,
+ * and Source Code in C, Second Edition</i>. (1996 John Wiley and Sons)
+ * ISBN 0-471-11709-9. Page 294--295.</li>
+ * </ol>
+ */
+public class TripleDES extends BaseCipher
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ /** Triple-DES only operates on 64 bit blocks. */
+ public static final int BLOCK_SIZE = 8;
+
+ /** Triple-DES uses 168 bits of a parity-adjusted 192 bit key. */
+ public static final int KEY_SIZE = 24;
+
+ /** The underlying DES instance. */
+ private DES des;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Default 0-arguments constructor.
+ */
+ public TripleDES()
+ {
+ super(Registry.TRIPLEDES_CIPHER, BLOCK_SIZE, KEY_SIZE);
+ des = new DES();
+ }
+
+ // Class methods.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Transform a key so it will be parity adjusted.
+ *
+ * @param kb The key bytes to adjust.
+ * @param offset The starting offset into the key bytes.
+ * @see DES#adjustParity(byte[],int)
+ */
+ public static void adjustParity(byte[] kb, int offset)
+ {
+ DES.adjustParity(kb, offset);
+ DES.adjustParity(kb, offset + 8);
+ DES.adjustParity(kb, offset + 16);
+ }
+
+ /**
+ * Tests if a byte array has already been parity adjusted.
+ *
+ * @param kb The key bytes to test.
+ * @param offset The starting offset into the key bytes.
+ * @return <code>true</code> if the bytes in <i>kb</i> starting at
+ * <i>offset</i> are parity adjusted.
+ * @see DES#isParityAdjusted(byte[],int)
+ * @see #adjustParity(byte[],int)
+ */
+ public static boolean isParityAdjusted(byte[] kb, int offset)
+ {
+ return DES.isParityAdjusted(kb, offset)
+ && DES.isParityAdjusted(kb, offset + 8)
+ && DES.isParityAdjusted(kb, offset + 16);
+ }
+
+ // Methods implementing BaseCipher.
+ // -----------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new TripleDES();
+ }
+
+ public Iterator blockSizes()
+ {
+ return Collections.singleton(new Integer(BLOCK_SIZE)).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ return Collections.singleton(new Integer(KEY_SIZE)).iterator();
+ }
+
+ public Object makeKey(byte[] kb, int bs) throws InvalidKeyException
+ {
+ if (kb.length != KEY_SIZE)
+ throw new InvalidKeyException("TripleDES key must be 24 bytes");
+
+ if (!isParityAdjusted(kb, 0))
+ adjustParity(kb, 0);
+
+ byte[] k1 = new byte[DES.KEY_SIZE], k2 = new byte[DES.KEY_SIZE], k3 = new byte[DES.KEY_SIZE];
+ System.arraycopy(kb, 0, k1, 0, DES.KEY_SIZE);
+ System.arraycopy(kb, DES.KEY_SIZE, k2, 0, DES.KEY_SIZE);
+ System.arraycopy(kb, 2 * DES.KEY_SIZE, k3, 0, DES.KEY_SIZE);
+ Context ctx = new Context();
+
+ ctx.k1 = (DES.Context) des.makeKey(k1, bs);
+ ctx.k2 = (DES.Context) des.makeKey(k2, bs);
+ ctx.k3 = (DES.Context) des.makeKey(k3, bs);
+
+ return ctx;
+ }
+
+ public void encrypt(byte[] in, int i, byte[] out, int o, Object K, int bs)
+ {
+ byte[] temp = new byte[BLOCK_SIZE];
+ des.encrypt(in, i, temp, 0, ((Context) K).k1, bs);
+ des.decrypt(temp, 0, temp, 0, ((Context) K).k2, bs);
+ des.encrypt(temp, 0, out, o, ((Context) K).k3, bs);
+ }
+
+ public void decrypt(byte[] in, int i, byte[] out, int o, Object K, int bs)
+ {
+ byte[] temp = new byte[BLOCK_SIZE];
+ des.decrypt(in, i, temp, 0, ((Context) K).k3, bs);
+ des.encrypt(temp, 0, temp, 0, ((Context) K).k2, bs);
+ des.decrypt(temp, 0, out, o, ((Context) K).k1, bs);
+ }
+
+ // Inner classes.
+ // -----------------------------------------------------------------------
+
+ private final class Context
+ {
+ DES.Context k1, k2, k3;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/Twofish.java b/gnu/javax/crypto/cipher/Twofish.java
new file mode 100644
index 000000000..bea7f5d2c
--- /dev/null
+++ b/gnu/javax/crypto/cipher/Twofish.java
@@ -0,0 +1,909 @@
+/* Twofish.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+//import java.io.PrintWriter;
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>Twofish is a balanced 128-bit Feistel cipher, consisting of 16 rounds. In
+ * each round, a 64-bit S-box value is computed from 64 bits of the block, and
+ * this value is xored into the other half of the block. The two half-blocks are
+ * then exchanged, and the next round begins. Before the first round, all input
+ * bits are xored with key-dependent "whitening" subkeys, and after the final
+ * round the output bits are xored with other key-dependent whitening subkeys;
+ * these subkeys are not used anywhere else in the algorithm.</p>
+ *
+ * <p>Twofish is designed by Bruce Schneier, Doug Whiting, John Kelsey, Chris
+ * Hall, David Wagner and Niels Ferguson.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.counterpane.com/twofish-paper.html">Twofish: A
+ * 128-bit Block Cipher</a>.</li>
+ * </ol>
+ */
+public final class Twofish extends BaseCipher
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ // private static final String NAME = "twofish";
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 9;
+
+ // private static final PrintWriter err = new PrintWriter(System.out, true);
+ // private static void debug(String s) {
+ // err.println(">>> "+NAME+": "+s);
+ // }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes
+
+ private static final int DEFAULT_KEY_SIZE = 16; // in bytes
+
+ private static final int MAX_ROUNDS = 16; // max # rounds (for allocating subkeys)
+
+ private static final int ROUNDS = MAX_ROUNDS;
+
+ // subkey array indices
+ private static final int INPUT_WHITEN = 0;
+
+ private static final int OUTPUT_WHITEN = INPUT_WHITEN + DEFAULT_BLOCK_SIZE
+ / 4;
+
+ private static final int ROUND_SUBKEYS = OUTPUT_WHITEN + DEFAULT_BLOCK_SIZE
+ / 4;
+
+ // private static final int TOTAL_SUBKEYS = ROUND_SUBKEYS + 2*MAX_ROUNDS;
+
+ private static final int SK_STEP = 0x02020202;
+
+ private static final int SK_BUMP = 0x01010101;
+
+ private static final int SK_ROTL = 9;
+
+ private static final String[] Pm = new String[] {
+ // p0
+ "\uA967\uB3E8\u04FD\uA376\u9A92\u8078\uE4DD\uD138"
+ + "\u0DC6\u3598\u18F7\uEC6C\u4375\u3726\uFA13\u9448"
+ + "\uF2D0\u8B30\u8454\uDF23\u195B\u3D59\uF3AE\uA282"
+ + "\u6301\u832E\uD951\u9B7C\uA6EB\uA5BE\u160C\uE361"
+ + "\uC08C\u3AF5\u732C\u250B\uBB4E\u896B\u536A\uB4F1"
+ + "\uE1E6\uBD45\uE2F4\uB666\uCC95\u0356\uD41C\u1ED7"
+ + "\uFBC3\u8EB5\uE9CF\uBFBA\uEA77\u39AF\u33C9\u6271"
+ + "\u8179\u09AD\u24CD\uF9D8\uE5C5\uB94D\u4408\u86E7"
+ + "\uA11D\uAAED\u0670\uB2D2\u417B\uA011\u31C2\u2790"
+ + "\u20F6\u60FF\u965C\uB1AB\u9E9C\u521B\u5F93\u0AEF"
+ + "\u9185\u49EE\u2D4F\u8F3B\u4787\u6D46\uD63E\u6964"
+ + "\u2ACE\uCB2F\uFC97\u057A\uAC7F\uD51A\u4B0E\uA75A"
+ + "\u2814\u3F29\u883C\u4C02\uB8DA\uB017\u551F\u8A7D"
+ + "\u57C7\u8D74\uB7C4\u9F72\u7E15\u2212\u5807\u9934"
+ + "\u6E50\uDE68\u65BC\uDBF8\uC8A8\u2B40\uDCFE\u32A4"
+ + "\uCA10\u21F0\uD35D\u0F00\u6F9D\u3642\u4A5E\uC1E0",
+ // p1
+ "\u75F3\uC6F4\uDB7B\uFBC8\u4AD3\uE66B\u457D\uE84B"
+ + "\uD632\uD8FD\u3771\uF1E1\u300F\uF81B\u87FA\u063F"
+ + "\u5EBA\uAE5B\u8A00\uBC9D\u6DC1\uB10E\u805D\uD2D5"
+ + "\uA084\u0714\uB590\u2CA3\uB273\u4C54\u9274\u3651"
+ + "\u38B0\uBD5A\uFC60\u6296\u6C42\uF710\u7C28\u278C"
+ + "\u1395\u9CC7\u2446\u3B70\uCAE3\u85CB\u11D0\u93B8"
+ + "\uA683\u20FF\u9F77\uC3CC\u036F\u08BF\u40E7\u2BE2"
+ + "\u790C\uAA82\u413A\uEAB9\uE49A\uA497\u7EDA\u7A17"
+ + "\u6694\uA11D\u3DF0\uDEB3\u0B72\uA71C\uEFD1\u533E"
+ + "\u8F33\u265F\uEC76\u2A49\u8188\uEE21\uC41A\uEBD9"
+ + "\uC539\u99CD\uAD31\u8B01\u1823\uDD1F\u4E2D\uF948"
+ + "\u4FF2\u658E\u785C\u5819\u8DE5\u9857\u677F\u0564"
+ + "\uAF63\uB6FE\uF5B7\u3CA5\uCEE9\u6844\uE04D\u4369"
+ + "\u292E\uAC15\u59A8\u0A9E\u6E47\uDF34\u356A\uCFDC"
+ + "\u22C9\uC09B\u89D4\uEDAB\u12A2\u0D52\uBB02\u2FA9"
+ + "\uD761\u1EB4\u5004\uF6C2\u1625\u8656\u5509\uBE91" };
+
+ /** Fixed 8x8 permutation S-boxes */
+ private static final byte[][] P = new byte[2][256]; // blank final
+
+ /**
+ * Define the fixed p0/p1 permutations used in keyed S-box lookup. By
+ * changing the following constant definitions, the S-boxes will
+ * automatically get changed in the Twofish engine.
+ */
+ private static final int P_00 = 1;
+
+ private static final int P_01 = 0;
+
+ private static final int P_02 = 0;
+
+ private static final int P_03 = P_01 ^ 1;
+
+ private static final int P_04 = 1;
+
+ private static final int P_10 = 0;
+
+ private static final int P_11 = 0;
+
+ private static final int P_12 = 1;
+
+ private static final int P_13 = P_11 ^ 1;
+
+ private static final int P_14 = 0;
+
+ private static final int P_20 = 1;
+
+ private static final int P_21 = 1;
+
+ private static final int P_22 = 0;
+
+ private static final int P_23 = P_21 ^ 1;
+
+ private static final int P_24 = 0;
+
+ private static final int P_30 = 0;
+
+ private static final int P_31 = 1;
+
+ private static final int P_32 = 1;
+
+ private static final int P_33 = P_31 ^ 1;
+
+ private static final int P_34 = 1;
+
+ /** Primitive polynomial for GF(256) */
+ // private static final int GF256_FDBK = 0x169;
+ private static final int GF256_FDBK_2 = 0x169 / 2;
+
+ private static final int GF256_FDBK_4 = 0x169 / 4;
+
+ /** MDS matrix */
+ private static final int[][] MDS = new int[4][256]; // blank final
+
+ private static final int RS_GF_FDBK = 0x14D; // field generator
+
+ /**
+ * KAT vector (from ecb_vk):
+ * I=183
+ * KEY=0000000000000000000000000000000000000000000002000000000000000000
+ * CT=F51410475B33FBD3DB2117B5C17C82D4
+ */
+ private static final byte[] KAT_KEY = Util.toBytesFromString("0000000000000000000000000000000000000000000002000000000000000000");
+
+ private static final byte[] KAT_CT = Util.toBytesFromString("F51410475B33FBD3DB2117B5C17C82D4");
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ // Static code - to intialise the MDS matrix and lookup tables -------------
+
+ static
+ {
+ long time = System.currentTimeMillis();
+
+ // expand the P arrays
+ int i;
+ char c;
+ for (i = 0; i < 256; i++)
+ {
+ c = Pm[0].charAt(i >>> 1);
+ P[0][i] = (byte) ((i & 1) == 0 ? c >>> 8 : c);
+
+ c = Pm[1].charAt(i >>> 1);
+ P[1][i] = (byte) ((i & 1) == 0 ? c >>> 8 : c);
+ }
+
+ // precompute the MDS matrix
+ int[] m1 = new int[2];
+ int[] mX = new int[2];
+ int[] mY = new int[2];
+ int j;
+ for (i = 0; i < 256; i++)
+ {
+ j = P[0][i] & 0xFF; // compute all the matrix elements
+ m1[0] = j;
+ mX[0] = Mx_X(j) & 0xFF;
+ mY[0] = Mx_Y(j) & 0xFF;
+
+ j = P[1][i] & 0xFF;
+ m1[1] = j;
+ mX[1] = Mx_X(j) & 0xFF;
+ mY[1] = Mx_Y(j) & 0xFF;
+
+ MDS[0][i] = m1[P_00] << 0 | // fill matrix w/ above elements
+ mX[P_00] << 8 | mY[P_00] << 16 | mY[P_00] << 24;
+ MDS[1][i] = mY[P_10] << 0 | mY[P_10] << 8 | mX[P_10] << 16
+ | m1[P_10] << 24;
+ MDS[2][i] = mX[P_20] << 0 | mY[P_20] << 8 | m1[P_20] << 16
+ | mY[P_20] << 24;
+ MDS[3][i] = mX[P_30] << 0 | m1[P_30] << 8 | mY[P_30] << 16
+ | mX[P_30] << 24;
+ }
+
+ time = System.currentTimeMillis() - time;
+
+ if (DEBUG && debuglevel > 8)
+ {
+ System.out.println("==========");
+ System.out.println();
+ System.out.println("Static Data");
+ System.out.println();
+ System.out.println("MDS[0][]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(MDS[0][i * 4 + j])
+ + ", ");
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ System.out.println("MDS[1][]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(MDS[1][i * 4 + j])
+ + ", ");
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ System.out.println("MDS[2][]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(MDS[2][i * 4 + j])
+ + ", ");
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ System.out.println("MDS[3][]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(MDS[3][i * 4 + j])
+ + ", ");
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ System.out.println("Total initialization time: " + time + " ms.");
+ System.out.println();
+ }
+ }
+
+ private static final int LFSR1(int x)
+ {
+ return (x >> 1) ^ ((x & 0x01) != 0 ? GF256_FDBK_2 : 0);
+ }
+
+ private static final int LFSR2(int x)
+ {
+ return (x >> 2) ^ ((x & 0x02) != 0 ? GF256_FDBK_2 : 0)
+ ^ ((x & 0x01) != 0 ? GF256_FDBK_4 : 0);
+ }
+
+ // private static final int Mx_1(int x) {
+ // return x;
+ // }
+
+ private static final int Mx_X(int x)
+ { // 5B
+ return x ^ LFSR2(x);
+ }
+
+ private static final int Mx_Y(int x)
+ { // EF
+ return x ^ LFSR1(x) ^ LFSR2(x);
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Twofish()
+ {
+ super(Registry.TWOFISH_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ private static final int b0(int x)
+ {
+ return x & 0xFF;
+ }
+
+ private static final int b1(int x)
+ {
+ return (x >>> 8) & 0xFF;
+ }
+
+ private static final int b2(int x)
+ {
+ return (x >>> 16) & 0xFF;
+ }
+
+ private static final int b3(int x)
+ {
+ return (x >>> 24) & 0xFF;
+ }
+
+ /**
+ * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box 32-bit
+ * entity from two key material 32-bit entities.
+ *
+ * @param k0 1st 32-bit entity.
+ * @param k1 2nd 32-bit entity.
+ * @return remainder polynomial generated using RS code
+ */
+ private static final int RS_MDS_Encode(int k0, int k1)
+ {
+ int r = k1;
+ int i;
+ for (i = 0; i < 4; i++)
+ { // shift 1 byte at a time
+ r = RS_rem(r);
+ }
+ r ^= k0;
+ for (i = 0; i < 4; i++)
+ {
+ r = RS_rem(r);
+ }
+ return r;
+ }
+
+ /**
+ * Reed-Solomon code parameters: (12, 8) reversible code:<p>
+ * <pre>
+ * g(x) = x**4 + (a + 1/a) x**3 + a x**2 + (a + 1/a) x + 1
+ * </pre>
+ * where a = primitive root of field generator 0x14D
+ */
+ private static final int RS_rem(int x)
+ {
+ int b = (x >>> 24) & 0xFF;
+ int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xFF;
+ int g3 = (b >>> 1) ^ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0) ^ g2;
+ int result = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b;
+ return result;
+ }
+
+ private static final int F32(int k64Cnt, int x, int[] k32)
+ {
+ int b0 = b0(x);
+ int b1 = b1(x);
+ int b2 = b2(x);
+ int b3 = b3(x);
+ int k0 = k32[0];
+ int k1 = k32[1];
+ int k2 = k32[2];
+ int k3 = k32[3];
+
+ int result = 0;
+ switch (k64Cnt & 3)
+ {
+ case 1:
+ result = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)]
+ ^ MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)]
+ ^ MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)]
+ ^ MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
+ break;
+ case 0: // same as 4
+ b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
+ b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
+ b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
+ b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
+ case 3:
+ b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
+ b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
+ b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
+ b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
+ case 2: // 128-bit keys (optimize for this case)
+ result = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF)
+ ^ b0(k0)]
+ ^ MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF)
+ ^ b1(k0)]
+ ^ MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF)
+ ^ b2(k0)]
+ ^ MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF)
+ ^ b3(k0)];
+ break;
+ }
+ return result;
+ }
+
+ private static final int Fe32(int[] sBox, int x, int R)
+ {
+ return sBox[2 * _b(x, R)] ^ sBox[2 * _b(x, R + 1) + 1]
+ ^ sBox[0x200 + 2 * _b(x, R + 2)]
+ ^ sBox[0x200 + 2 * _b(x, R + 3) + 1];
+ }
+
+ private static final int _b(int x, int N)
+ {
+ // int result = 0;
+ // switch (N%4) {
+ // case 0: result = b0(x); break;
+ // case 1: result = b1(x); break;
+ // case 2: result = b2(x); break;
+ // case 3: result = b3(x); break;
+ // }
+ // return result;
+ // profiling shows that the code spends too long in this method.
+ // following constructs seem to improve, albeit marginally, performance
+ switch (N % 4)
+ {
+ case 0:
+ return x & 0xFF;
+ case 1:
+ return (x >>> 8) & 0xFF;
+ case 2:
+ return (x >>> 16) & 0xFF;
+ default:
+ return x >>> 24;
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ Twofish result = new Twofish();
+ result.currentBlockSize = this.currentBlockSize;
+
+ return result;
+ }
+
+ // IBlockCipherSpi interface implementation --------------------------------
+
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(DEFAULT_BLOCK_SIZE));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ public Iterator keySizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(8)); // 64-bit
+ al.add(new Integer(16)); // 128-bit
+ al.add(new Integer(24)); // 192-bit
+ al.add(new Integer(32)); // 256-bit
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ /**
+ * <p>Expands a user-supplied key material into a session key for a designated
+ * <i>block size</i>.</p>
+ *
+ * @param k the 64/128/192/256-bit user-key to use.
+ * @param bs the desired block size in bytes.
+ * @return an Object encapsulating the session key.
+ * @exception IllegalArgumentException if the block size is not 16 (128-bit).
+ * @exception InvalidKeyException if the key data is invalid.
+ */
+ public Object makeKey(byte[] k, int bs) throws InvalidKeyException
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (k == null)
+ {
+ throw new InvalidKeyException("Empty key");
+ }
+ int length = k.length;
+ if (!(length == 8 || length == 16 || length == 24 || length == 32))
+ {
+ throw new InvalidKeyException("Incorrect key length");
+ }
+
+ int k64Cnt = length / 8;
+ int subkeyCnt = ROUND_SUBKEYS + 2 * ROUNDS;
+ int[] k32e = new int[4]; // even 32-bit entities
+ int[] k32o = new int[4]; // odd 32-bit entities
+ int[] sBoxKey = new int[4];
+ //
+ // split user key material into even and odd 32-bit entities and
+ // compute S-box keys using (12, 8) Reed-Solomon code over GF(256)
+ //
+ int i, j, offset = 0;
+ for (i = 0, j = k64Cnt - 1; i < 4 && offset < length; i++, j--)
+ {
+ k32e[i] = (k[offset++] & 0xFF) | (k[offset++] & 0xFF) << 8
+ | (k[offset++] & 0xFF) << 16 | (k[offset++] & 0xFF) << 24;
+ k32o[i] = (k[offset++] & 0xFF) | (k[offset++] & 0xFF) << 8
+ | (k[offset++] & 0xFF) << 16 | (k[offset++] & 0xFF) << 24;
+ sBoxKey[j] = RS_MDS_Encode(k32e[i], k32o[i]); // reverse order
+ }
+ // compute the round decryption subkeys for PHT. these same subkeys
+ // will be used in encryption but will be applied in reverse order.
+ int q, A, B;
+ int[] subKeys = new int[subkeyCnt];
+ for (i = q = 0; i < subkeyCnt / 2; i++, q += SK_STEP)
+ {
+ A = F32(k64Cnt, q, k32e); // A uses even key entities
+ B = F32(k64Cnt, q + SK_BUMP, k32o); // B uses odd key entities
+ B = B << 8 | B >>> 24;
+ A += B;
+ subKeys[2 * i] = A; // combine with a PHT
+ A += B;
+ subKeys[2 * i + 1] = A << SK_ROTL | A >>> (32 - SK_ROTL);
+ }
+
+ // fully expand the table for speed
+ int k0 = sBoxKey[0];
+ int k1 = sBoxKey[1];
+ int k2 = sBoxKey[2];
+ int k3 = sBoxKey[3];
+ int b0, b1, b2, b3;
+ int[] sBox = new int[4 * 256];
+ for (i = 0; i < 256; i++)
+ {
+ b0 = b1 = b2 = b3 = i;
+ switch (k64Cnt & 3)
+ {
+ case 1:
+ sBox[2 * i] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)];
+ sBox[2 * i + 1] = MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)];
+ sBox[0x200 + 2 * i] = MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)];
+ sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
+ break;
+ case 0: // same as 4
+ b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
+ b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
+ b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
+ b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
+ case 3:
+ b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
+ b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
+ b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
+ b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
+ case 2: // 128-bit keys
+ sBox[2 * i] = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF)
+ ^ b0(k0)];
+ sBox[2 * i + 1] = MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF)
+ ^ b1(k0)];
+ sBox[0x200 + 2 * i] = MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF)
+ ^ b2(k0)];
+ sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][(P[P_32][b3] & 0xFF)
+ ^ b3(k1)] & 0xFF)
+ ^ b3(k0)];
+ }
+ }
+
+ if (DEBUG && debuglevel > 7)
+ {
+ System.out.println("S-box[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(sBox[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(sBox[256 + i * 4 + j])
+ + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(sBox[512 + i * 4 + j])
+ + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(sBox[768 + i * 4 + j])
+ + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("User (odd, even) keys --> S-Box keys:");
+ for (i = 0; i < k64Cnt; i++)
+ {
+ System.out.println("0x" + Util.toString(k32o[i]) + " 0x"
+ + Util.toString(k32e[i]) + " --> 0x"
+ + Util.toString(sBoxKey[k64Cnt - 1 - i]));
+ }
+ System.out.println();
+ System.out.println("Round keys:");
+ for (i = 0; i < ROUND_SUBKEYS + 2 * ROUNDS; i += 2)
+ {
+ System.out.println("0x" + Util.toString(subKeys[i]) + " 0x"
+ + Util.toString(subKeys[i + 1]));
+ }
+ System.out.println();
+ }
+
+ return new Object[] { sBox, subKeys };
+ }
+
+ public void encrypt(byte[] in, int inOffset, byte[] out, int outOffset,
+ Object sessionKey, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ Object[] sk = (Object[]) sessionKey; // extract S-box and session key
+ int[] sBox = (int[]) sk[0];
+ int[] sKey = (int[]) sk[1];
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PT=" + Util.toString(in, inOffset, bs));
+ }
+
+ int x0 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
+ | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 24;
+ int x1 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
+ | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 24;
+ int x2 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
+ | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 24;
+ int x3 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
+ | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 24;
+
+ x0 ^= sKey[INPUT_WHITEN];
+ x1 ^= sKey[INPUT_WHITEN + 1];
+ x2 ^= sKey[INPUT_WHITEN + 2];
+ x3 ^= sKey[INPUT_WHITEN + 3];
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PTw=" + Util.toString(x0) + Util.toString(x1)
+ + Util.toString(x2) + Util.toString(x3));
+ }
+
+ int t0, t1;
+ int k = ROUND_SUBKEYS;
+ for (int R = 0; R < ROUNDS; R += 2)
+ {
+ t0 = Fe32(sBox, x0, 0);
+ t1 = Fe32(sBox, x1, 3);
+ x2 ^= t0 + t1 + sKey[k++];
+ x2 = x2 >>> 1 | x2 << 31;
+ x3 = x3 << 1 | x3 >>> 31;
+ x3 ^= t0 + 2 * t1 + sKey[k++];
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CT" + (R) + "=" + Util.toString(x0)
+ + Util.toString(x1) + Util.toString(x2)
+ + Util.toString(x3));
+ }
+
+ t0 = Fe32(sBox, x2, 0);
+ t1 = Fe32(sBox, x3, 3);
+ x0 ^= t0 + t1 + sKey[k++];
+ x0 = x0 >>> 1 | x0 << 31;
+ x1 = x1 << 1 | x1 >>> 31;
+ x1 ^= t0 + 2 * t1 + sKey[k++];
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CT" + (R + 1) + "=" + Util.toString(x0)
+ + Util.toString(x1) + Util.toString(x2)
+ + Util.toString(x3));
+ }
+ }
+ x2 ^= sKey[OUTPUT_WHITEN];
+ x3 ^= sKey[OUTPUT_WHITEN + 1];
+ x0 ^= sKey[OUTPUT_WHITEN + 2];
+ x1 ^= sKey[OUTPUT_WHITEN + 3];
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CTw=" + Util.toString(x0) + Util.toString(x1)
+ + Util.toString(x2) + Util.toString(x3));
+ }
+
+ out[outOffset++] = (byte) x2;
+ out[outOffset++] = (byte) (x2 >>> 8);
+ out[outOffset++] = (byte) (x2 >>> 16);
+ out[outOffset++] = (byte) (x2 >>> 24);
+ out[outOffset++] = (byte) x3;
+ out[outOffset++] = (byte) (x3 >>> 8);
+ out[outOffset++] = (byte) (x3 >>> 16);
+ out[outOffset++] = (byte) (x3 >>> 24);
+ out[outOffset++] = (byte) x0;
+ out[outOffset++] = (byte) (x0 >>> 8);
+ out[outOffset++] = (byte) (x0 >>> 16);
+ out[outOffset++] = (byte) (x0 >>> 24);
+ out[outOffset++] = (byte) x1;
+ out[outOffset++] = (byte) (x1 >>> 8);
+ out[outOffset++] = (byte) (x1 >>> 16);
+ out[outOffset] = (byte) (x1 >>> 24);
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CT=" + Util.toString(out, outOffset - 15, 16));
+ System.out.println();
+ }
+ }
+
+ public void decrypt(byte[] in, int inOffset, byte[] out, int outOffset,
+ Object sessionKey, int bs)
+ {
+ if (bs != DEFAULT_BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ Object[] sk = (Object[]) sessionKey; // extract S-box and session key
+ int[] sBox = (int[]) sk[0];
+ int[] sKey = (int[]) sk[1];
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CT=" + Util.toString(in, inOffset, bs));
+ }
+
+ int x2 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
+ | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 24;
+ int x3 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
+ | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 24;
+ int x0 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
+ | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 24;
+ int x1 = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
+ | (in[inOffset++] & 0xFF) << 16 | (in[inOffset++] & 0xFF) << 24;
+
+ x2 ^= sKey[OUTPUT_WHITEN];
+ x3 ^= sKey[OUTPUT_WHITEN + 1];
+ x0 ^= sKey[OUTPUT_WHITEN + 2];
+ x1 ^= sKey[OUTPUT_WHITEN + 3];
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("CTw=" + Util.toString(x2) + Util.toString(x3)
+ + Util.toString(x0) + Util.toString(x1));
+ }
+
+ int k = ROUND_SUBKEYS + 2 * ROUNDS - 1;
+ int t0, t1;
+ for (int R = 0; R < ROUNDS; R += 2)
+ {
+ t0 = Fe32(sBox, x2, 0);
+ t1 = Fe32(sBox, x3, 3);
+ x1 ^= t0 + 2 * t1 + sKey[k--];
+ x1 = x1 >>> 1 | x1 << 31;
+ x0 = x0 << 1 | x0 >>> 31;
+ x0 ^= t0 + t1 + sKey[k--];
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PT" + (ROUNDS - R) + "=" + Util.toString(x2)
+ + Util.toString(x3) + Util.toString(x0)
+ + Util.toString(x1));
+ }
+
+ t0 = Fe32(sBox, x0, 0);
+ t1 = Fe32(sBox, x1, 3);
+ x3 ^= t0 + 2 * t1 + sKey[k--];
+ x3 = x3 >>> 1 | x3 << 31;
+ x2 = x2 << 1 | x2 >>> 31;
+ x2 ^= t0 + t1 + sKey[k--];
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PT" + (ROUNDS - R - 1) + "="
+ + Util.toString(x2) + Util.toString(x3)
+ + Util.toString(x0) + Util.toString(x1));
+ }
+ }
+ x0 ^= sKey[INPUT_WHITEN];
+ x1 ^= sKey[INPUT_WHITEN + 1];
+ x2 ^= sKey[INPUT_WHITEN + 2];
+ x3 ^= sKey[INPUT_WHITEN + 3];
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PTw=" + Util.toString(x2) + Util.toString(x3)
+ + Util.toString(x0) + Util.toString(x1));
+ }
+
+ out[outOffset++] = (byte) x0;
+ out[outOffset++] = (byte) (x0 >>> 8);
+ out[outOffset++] = (byte) (x0 >>> 16);
+ out[outOffset++] = (byte) (x0 >>> 24);
+ out[outOffset++] = (byte) x1;
+ out[outOffset++] = (byte) (x1 >>> 8);
+ out[outOffset++] = (byte) (x1 >>> 16);
+ out[outOffset++] = (byte) (x1 >>> 24);
+ out[outOffset++] = (byte) x2;
+ out[outOffset++] = (byte) (x2 >>> 8);
+ out[outOffset++] = (byte) (x2 >>> 16);
+ out[outOffset++] = (byte) (x2 >>> 24);
+ out[outOffset++] = (byte) x3;
+ out[outOffset++] = (byte) (x3 >>> 8);
+ out[outOffset++] = (byte) (x3 >>> 16);
+ out[outOffset] = (byte) (x3 >>> 24);
+
+ if (DEBUG && debuglevel > 6)
+ {
+ System.out.println("PT=" + Util.toString(out, outOffset - 15, 16));
+ System.out.println();
+ }
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ boolean result = super.selfTest(); // do symmetry tests
+ if (result)
+ {
+ result = testKat(KAT_KEY, KAT_CT);
+ }
+ valid = new Boolean(result);
+ }
+ return valid.booleanValue();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/cipher/WeakKeyException.java b/gnu/javax/crypto/cipher/WeakKeyException.java
new file mode 100644
index 000000000..4454e0e45
--- /dev/null
+++ b/gnu/javax/crypto/cipher/WeakKeyException.java
@@ -0,0 +1,71 @@
+/* WeakKeyException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.cipher;
+
+import java.security.InvalidKeyException;
+
+/**
+ * <p>Checked exception thrown to indicate that a weak key has been generated
+ * and or specified instead of a valid non-weak value.</p>
+ */
+public class WeakKeyException extends InvalidKeyException
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public WeakKeyException()
+ {
+ super();
+ }
+
+ public WeakKeyException(String msg)
+ {
+ super(msg);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/GnuCrypto.java b/gnu/javax/crypto/jce/GnuCrypto.java
new file mode 100644
index 000000000..276f61ea3
--- /dev/null
+++ b/gnu/javax/crypto/jce/GnuCrypto.java
@@ -0,0 +1,569 @@
+/* GnuCrypto.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.mac.MacFactory;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>The GNU Crypto implementation of the Java Cryptographic Extension (JCE)
+ * Provider.</p>
+ *
+ * @see java.security.Provider
+ */
+public final class GnuCrypto extends Provider
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>The <a href="http://www.gnu.org/software/gnu-crypto/">GNU Crypto</a>
+ * Provider.</p>
+ */
+ public GnuCrypto()
+ {
+ super(Registry.GNU_CRYPTO, 2.1, "GNU Crypto JCE Provider");
+
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ // Cipher
+ put("Cipher.ANUBIS",
+ gnu.javax.crypto.jce.cipher.AnubisSpi.class.getName());
+ put("Cipher.ANUBIS ImplementedIn", "Software");
+ put("Cipher.ARCFOUR",
+ gnu.javax.crypto.jce.cipher.ARCFourSpi.class.getName());
+ put("Cipher.ARCFOUR ImplementedIn", "Software");
+ put("Cipher.BLOWFISH",
+ gnu.javax.crypto.jce.cipher.BlowfishSpi.class.getName());
+ put("Cipher.BLOWFISH ImplementedIn", "Software");
+ put("Cipher.DES", gnu.javax.crypto.jce.cipher.DESSpi.class.getName());
+ put("Cipher.DES ImplementedIn", "Software");
+ put("Cipher.KHAZAD",
+ gnu.javax.crypto.jce.cipher.KhazadSpi.class.getName());
+ put("Cipher.KHAZAD ImplementedIn", "Software");
+ put("Cipher.NULL",
+ gnu.javax.crypto.jce.cipher.NullCipherSpi.class.getName());
+ put("Cipher.NULL ImplementedIn", "Software");
+ put("Cipher.AES",
+ gnu.javax.crypto.jce.cipher.RijndaelSpi.class.getName());
+ put("Cipher.AES ImplementedIn", "Software");
+ put("Cipher.RIJNDAEL",
+ gnu.javax.crypto.jce.cipher.RijndaelSpi.class.getName());
+ put("Cipher.RIJNDAEL ImplementedIn", "Software");
+ put("Cipher.SERPENT",
+ gnu.javax.crypto.jce.cipher.SerpentSpi.class.getName());
+ put("Cipher.SERPENT ImplementedIn", "Software");
+ put("Cipher.SQUARE",
+ gnu.javax.crypto.jce.cipher.SquareSpi.class.getName());
+ put("Cipher.SQUARE ImplementedIn", "Software");
+ put("Cipher.TRIPLEDES",
+ gnu.javax.crypto.jce.cipher.TripleDESSpi.class.getName());
+ put("Cipher.TRIPLEDES ImplementedIn", "Software");
+ put("Cipher.TWOFISH",
+ gnu.javax.crypto.jce.cipher.TwofishSpi.class.getName());
+ put("Cipher.TWOFISH ImplementedIn", "Software");
+ put("Cipher.CAST5",
+ gnu.javax.crypto.jce.cipher.Cast5Spi.class.getName());
+ put("Cipher.CAST5 ImplementedIn", "Software");
+
+ // PBES2 ciphers.
+ put("Cipher.PBEWithHMacHavalAndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.AES.class.getName());
+ put("Cipher.PBEWithHMacHavalAndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Anubis.class.getName());
+ put(
+ "Cipher.PBEWithHMacHavalAndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacHavalAndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Cast5.class.getName());
+ put("Cipher.PBEWithHMacHavalAndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.DES.class.getName());
+ put("Cipher.PBEWithHMacHavalAndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Khazad.class.getName());
+ put("Cipher.PBEWithHMacHavalAndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Serpent.class.getName());
+ put("Cipher.PBEWithHMacHavalAndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Square.class.getName());
+ put(
+ "Cipher.PBEWithHMacHavalAndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.TripleDES.class.getName());
+ put("Cipher.PBEWithHMacHavalAndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacMD2AndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.AES.class.getName());
+ put("Cipher.PBEWithHMacMD2AndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Anubis.class.getName());
+ put("Cipher.PBEWithHMacMD2AndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacMD2AndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Cast5.class.getName());
+ put("Cipher.PBEWithHMacMD2AndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.DES.class.getName());
+ put("Cipher.PBEWithHMacMD2AndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Khazad.class.getName());
+ put("Cipher.PBEWithHMacMD2AndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Serpent.class.getName());
+ put("Cipher.PBEWithHMacMD2AndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Square.class.getName());
+ put("Cipher.PBEWithHMacMD2AndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.TripleDES.class.getName());
+ put("Cipher.PBEWithHMacMD2AndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacMD4AndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.AES.class.getName());
+ put("Cipher.PBEWithHMacMD4AndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.Anubis.class.getName());
+ put("Cipher.PBEWithHMacMD4AndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacMD4AndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.Cast5.class.getName());
+ put("Cipher.PBEWithHMacMD4AndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.DES.class.getName());
+ put("Cipher.PBEWithHMacMD4AndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.Khazad.class.getName());
+ put("Cipher.PBEWithHMacMD4AndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.Serpent.class.getName());
+ put("Cipher.PBEWithHMacMD4AndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.Square.class.getName());
+ put("Cipher.PBEWithHMacMD4AndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.TripleDES.class.getName());
+ put("Cipher.PBEWithHMacMD4AndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD4.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacMD5AndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.AES.class.getName());
+ put("Cipher.PBEWithHMacMD5AndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Anubis.class.getName());
+ put("Cipher.PBEWithHMacMD5AndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacMD5AndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Cast5.class.getName());
+ put("Cipher.PBEWithHMacMD5AndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.DES.class.getName());
+ put("Cipher.PBEWithHMacMD5AndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Khazad.class.getName());
+ put("Cipher.PBEWithHMacMD5AndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Serpent.class.getName());
+ put("Cipher.PBEWithHMacMD5AndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Square.class.getName());
+ put("Cipher.PBEWithHMacMD5AndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.TripleDES.class.getName());
+ put("Cipher.PBEWithHMacMD5AndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacSHA1AndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.AES.class.getName());
+ put("Cipher.PBEWithHMacSHA1AndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Anubis.class.getName());
+ put("Cipher.PBEWithHMacSHA1AndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacSHA1AndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Cast5.class.getName());
+ put("Cipher.PBEWithHMacSHA1AndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.DES.class.getName());
+ put("Cipher.PBEWithHMacSHA1AndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Khazad.class.getName());
+ put("Cipher.PBEWithHMacSHA1AndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Serpent.class.getName());
+ put("Cipher.PBEWithHMacSHA1AndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Square.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA1AndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.TripleDES.class.getName());
+ put("Cipher.PBEWithHMacSHA1AndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacSHA256AndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.AES.class.getName());
+ put("Cipher.PBEWithHMacSHA256AndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Anubis.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA256AndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacSHA256AndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Cast5.class.getName());
+ put("Cipher.PBEWithHMacSHA256AndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.DES.class.getName());
+ put("Cipher.PBEWithHMacSHA256AndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Khazad.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA256AndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Serpent.class.getName());
+ put("Cipher.PBEWithHMacSHA256AndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Square.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA256AndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.TripleDES.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA256AndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacSHA384AndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.AES.class.getName());
+ put("Cipher.PBEWithHMacSHA384AndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Anubis.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA384AndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacSHA384AndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Cast5.class.getName());
+ put("Cipher.PBEWithHMacSHA384AndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.DES.class.getName());
+ put("Cipher.PBEWithHMacSHA384AndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Khazad.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA384AndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Serpent.class.getName());
+ put("Cipher.PBEWithHMacSHA384AndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Square.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA384AndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.TripleDES.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA384AndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacSHA512AndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.AES.class.getName());
+ put("Cipher.PBEWithHMacSHA512AndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Anubis.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA512AndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacSHA512AndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Cast5.class.getName());
+ put("Cipher.PBEWithHMacSHA512AndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.DES.class.getName());
+ put("Cipher.PBEWithHMacSHA512AndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Khazad.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA512AndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Serpent.class.getName());
+ put("Cipher.PBEWithHMacSHA512AndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Square.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA512AndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.TripleDES.class.getName());
+ put(
+ "Cipher.PBEWithHMacSHA512AndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacTigerAndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.AES.class.getName());
+ put("Cipher.PBEWithHMacTigerAndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Anubis.class.getName());
+ put(
+ "Cipher.PBEWithHMacTigerAndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Blowfish.class.getName());
+ put("Cipher.PBEWithHMacTigerAndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Cast5.class.getName());
+ put("Cipher.PBEWithHMacTigerAndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.DES.class.getName());
+ put("Cipher.PBEWithHMacTigerAndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Khazad.class.getName());
+ put("Cipher.PBEWithHMacTigerAndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Serpent.class.getName());
+ put("Cipher.PBEWithHMacTigerAndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Square.class.getName());
+ put(
+ "Cipher.PBEWithHMacTigerAndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.TripleDES.class.getName());
+ put("Cipher.PBEWithHMacTigerAndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Twofish.class.getName());
+
+ put("Cipher.PBEWithHMacWhirlpoolAndAES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.AES.class.getName());
+ put(
+ "Cipher.PBEWithHMacWhirlpoolAndAnubis",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Anubis.class.getName());
+ put(
+ "Cipher.PBEWithHMacWhirlpoolAndBlowfish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Blowfish.class.getName());
+ put(
+ "Cipher.PBEWithHMacWhirlpoolAndCast5",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Cast5.class.getName());
+ put("Cipher.PBEWithHMacWhirlpoolAndDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.DES.class.getName());
+ put(
+ "Cipher.PBEWithHMacWhirlpoolAndKhazad",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Khazad.class.getName());
+ put(
+ "Cipher.PBEWithHMacWhirlpoolAndSerpent",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Serpent.class.getName());
+ put(
+ "Cipher.PBEWithHMacWhirlpoolAndSquare",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Square.class.getName());
+ put(
+ "Cipher.PBEWithHMacWhirlpoolAndTripleDES",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.TripleDES.class.getName());
+ put(
+ "Cipher.PBEWithHMacWhirlpoolAndTwofish",
+ gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Twofish.class.getName());
+
+ // SecretKeyFactory interface to PBKDF2.
+ put(
+ "SecretKeyFactory.PBKDF2WithHMacHaval",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacHaval.class.getName());
+ put("SecretKeyFactory.PBKDF2WithHMacMD2",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacMD2.class.getName());
+ put("SecretKeyFactory.PBKDF2WithHMacMD4",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacMD4.class.getName());
+ put("SecretKeyFactory.PBKDF2WithHMacMD5",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacMD5.class.getName());
+ put(
+ "SecretKeyFactory.PBKDF2WithHMacSHA1",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacSHA1.class.getName());
+ put(
+ "SecretKeyFactory.PBKDF2WithHMacSHA256",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacSHA256.class.getName());
+ put(
+ "SecretKeyFactory.PBKDF2WithHMacSHA384",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacSHA384.class.getName());
+ put(
+ "SecretKeyFactory.PBKDF2WithHMacSHA512",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacSHA512.class.getName());
+ put(
+ "SecretKeyFactory.PBKDF2WithHMacTiger",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacTiger.class.getName());
+ put(
+ "SecretKeyFactory.PBKDF2WithHMacWhirlpool",
+ gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacWhirlpool.class.getName());
+
+ // Simple SecretKeyFactory implementations.
+ put("SecretKeyFactory.Anubis",
+ gnu.javax.crypto.jce.key.AnubisSecretKeyFactoryImpl.class.getName());
+ put(
+ "SecretKeyFactory.Blowfish",
+ gnu.javax.crypto.jce.key.BlowfishSecretKeyFactoryImpl.class.getName());
+ put("SecretKeyFactory.Cast5",
+ gnu.javax.crypto.jce.key.Cast5SecretKeyFactoryImpl.class.getName());
+ put("SecretKeyFactory.DES",
+ gnu.javax.crypto.jce.key.DESSecretKeyFactoryImpl.class.getName());
+ put("SecretKeyFactory.Khazad",
+ gnu.javax.crypto.jce.key.KhazadSecretKeyFactoryImpl.class.getName());
+ put(
+ "SecretKeyFactory.Rijndael",
+ gnu.javax.crypto.jce.key.RijndaelSecretKeyFactoryImpl.class.getName());
+ put(
+ "SecretKeyFactory.Serpent",
+ gnu.javax.crypto.jce.key.SerpentSecretKeyFactoryImpl.class.getName());
+ put("SecretKeyFactory.Square",
+ gnu.javax.crypto.jce.key.SquareSecretKeyFactoryImpl.class.getName());
+ put("SecretKeyFactory.TripleDES",
+ gnu.javax.crypto.jce.key.DESedeSecretKeyFactoryImpl.class.getName());
+ put("Alg.Alias.SecretKeyFactory.AES", "Rijndael");
+ put("Alg.Alias.SecretKeyFactory.DESede", "TripleDES");
+ put("Alg.Alias.SecretKeyFactory.3-DES", "TripleDES");
+ put("Alg.Alias.SecretKeyFactory.3DES", "TripleDES");
+
+ put("AlgorithmParameters.BlockCipherParameters",
+ gnu.javax.crypto.jce.params.BlockCipherParameters.class.getName());
+
+ // MAC
+ put("Mac.HMAC-MD2", gnu.javax.crypto.jce.mac.HMacMD2Spi.class.getName());
+ put("Mac.HMAC-MD4", gnu.javax.crypto.jce.mac.HMacMD4Spi.class.getName());
+ put("Mac.HMAC-MD5", gnu.javax.crypto.jce.mac.HMacMD5Spi.class.getName());
+ put("Mac.HMAC-RIPEMD128",
+ gnu.javax.crypto.jce.mac.HMacRipeMD128Spi.class.getName());
+ put("Mac.HMAC-RIPEMD160",
+ gnu.javax.crypto.jce.mac.HMacRipeMD160Spi.class.getName());
+ put("Mac.HMAC-SHA160",
+ gnu.javax.crypto.jce.mac.HMacSHA160Spi.class.getName());
+ put("Mac.HMAC-SHA256",
+ gnu.javax.crypto.jce.mac.HMacSHA256Spi.class.getName());
+ put("Mac.HMAC-SHA384",
+ gnu.javax.crypto.jce.mac.HMacSHA384Spi.class.getName());
+ put("Mac.HMAC-SHA512",
+ gnu.javax.crypto.jce.mac.HMacSHA512Spi.class.getName());
+ put("Mac.HMAC-TIGER",
+ gnu.javax.crypto.jce.mac.HMacTigerSpi.class.getName());
+ put("Mac.HMAC-HAVAL",
+ gnu.javax.crypto.jce.mac.HMacHavalSpi.class.getName());
+ put("Mac.HMAC-WHIRLPOOL",
+ gnu.javax.crypto.jce.mac.HMacWhirlpoolSpi.class.getName());
+ put("Mac.TMMH16", gnu.javax.crypto.jce.mac.TMMH16Spi.class.getName());
+ put("Mac.UHASH32", gnu.javax.crypto.jce.mac.UHash32Spi.class.getName());
+ put("Mac.UMAC32", gnu.javax.crypto.jce.mac.UMac32Spi.class.getName());
+
+ put("Mac.OMAC-ANUBIS",
+ gnu.javax.crypto.jce.mac.OMacAnubisImpl.class.getName());
+ put("Mac.OMAC-BLOWFISH",
+ gnu.javax.crypto.jce.mac.OMacBlowfishImpl.class.getName());
+ put("Mac.OMAC-CAST5",
+ gnu.javax.crypto.jce.mac.OMacCast5Impl.class.getName());
+ put("Mac.OMAC-DES",
+ gnu.javax.crypto.jce.mac.OMacDESImpl.class.getName());
+ put("Mac.OMAC-KHAZAD",
+ gnu.javax.crypto.jce.mac.OMacKhazadImpl.class.getName());
+ put("Mac.OMAC-RIJNDAEL",
+ gnu.javax.crypto.jce.mac.OMacRijndaelImpl.class.getName());
+ put("Mac.OMAC-SERPENT",
+ gnu.javax.crypto.jce.mac.OMacSerpentImpl.class.getName());
+ put("Mac.OMAC-SQUARE",
+ gnu.javax.crypto.jce.mac.OMacSquareImpl.class.getName());
+ put("Mac.OMAC-TRIPLEDES",
+ gnu.javax.crypto.jce.mac.OMacTripleDESImpl.class.getName());
+ put("Mac.OMAC-TWOFISH",
+ gnu.javax.crypto.jce.mac.OMacTwofishImpl.class.getName());
+
+ // Aliases
+ put("Alg.Alias.AlgorithmParameters.AES", "BlockCipherParameters");
+ put("Alg.Alias.AlgorithmParameters.BLOWFISH", "BlockCipherParameters");
+ put("Alg.Alias.AlgorithmParameters.ANUBIS", "BlockCipherParameters");
+ put("Alg.Alias.AlgorithmParameters.KHAZAD", "BlockCipherParameters");
+ put("Alg.Alias.AlgorithmParameters.NULL", "BlockCipherParameters");
+ put("Alg.Alias.AlgorithmParameters.RIJNDAEL", "BlockCipherParameters");
+ put("Alg.Alias.AlgorithmParameters.SERPENT", "BlockCipherParameters");
+ put("Alg.Alias.AlgorithmParameters.SQUARE", "BlockCipherParameters");
+ put("Alg.Alias.AlgorithmParameters.TWOFISH", "BlockCipherParameters");
+ put("Alg.Alias.Cipher.RC4", "ARCFOUR");
+ put("Alg.Alias.Cipher.3-DES", "TRIPLEDES");
+ put("Alg.Alias.Cipher.3DES", "TRIPLEDES");
+ put("Alg.Alias.Cipher.DES-EDE", "TRIPLEDES");
+ put("Alg.Alias.Cipher.DESede", "TRIPLEDES");
+ put("Alg.Alias.Cipher.CAST128", "CAST5");
+ put("Alg.Alias.Cipher.CAST-128", "CAST5");
+ put("Alg.Alias.Mac.HMAC-SHS", "HMAC-SHA160");
+ put("Alg.Alias.Mac.HMAC-SHA", "HMAC-SHA160");
+ put("Alg.Alias.Mac.HMAC-SHA1", "HMAC-SHA160");
+ put("Alg.Alias.Mac.HMAC-SHA-160", "HMAC-SHA160");
+ put("Alg.Alias.Mac.HMAC-SHA-256", "HMAC-SHA256");
+ put("Alg.Alias.Mac.HMAC-SHA-384", "HMAC-SHA384");
+ put("Alg.Alias.Mac.HMAC-SHA-512", "HMAC-SHA512");
+ put("Alg.Alias.Mac.HMAC-RIPEMD-160", "HMAC-RIPEMD160");
+ put("Alg.Alias.Mac.HMAC-RIPEMD-128", "HMAC-RIPEMD128");
+ put("Alg.Alias.Mac.OMAC-AES", "OMAC-RIJNDAEL");
+ put("Alg.Alias.Mac.OMAC-3DES", "OMAC-3DES");
+ put("Alg.Alias.Mac.HmacMD4", "HMAC-MD4");
+ put("Alg.Alias.Mac.HmacMD5", "HMAC-MD5");
+ put("Alg.Alias.Mac.HmacSHA-1", "HMAC-SHA-1");
+ put("Alg.Alias.Mac.HmacSHA1", "HMAC-SHA1");
+ put("Alg.Alias.Mac.HmacSHA-160", "HMAC-SHA-160");
+ put("Alg.Alias.Mac.HmacSHA160", "HMAC-SHA-160");
+ put("Alg.Alias.Mac.HmacSHA-256", "HMAC-SHA-256");
+ put("Alg.Alias.Mac.HmacSHA256", "HMAC-SHA-256");
+ put("Alg.Alias.Mac.HmacSHA-384", "HMAC-SHA-384");
+ put("Alg.Alias.Mac.HmacSHA384", "HMAC-SHA-384");
+ put("Alg.Alias.Mac.HmacSHA-512", "HMAC-SHA-512");
+ put("Alg.Alias.Mac.HmacSHA512", "HMAC-SHA-512");
+ put("Alg.Alias.Mac.HmacRIPEMD128", "HMAC-RIPEMD128");
+ put("Alg.Alias.Mac.HmacRIPEMD-128", "HMAC-RIPEMD128");
+ put("Alg.Alias.Mac.HmacRIPEMD160", "HMAC-RIPEMD160");
+ put("Alg.Alias.Mac.HmacRIPEMD-160", "HMAC-RIPEMD160");
+ put("Alg.Alias.Mac.HmacTiger", "HMAC-TIGER");
+ put("Alg.Alias.Mac.HmacHaval", "HMAC-HAVAL");
+ put("Alg.Alias.Mac.HmacWhirlpool", "HMAC-WHIRLPOOL");
+
+ // KeyAgreement
+ put("KeyAgreement.DiffieHellman",
+ gnu.javax.crypto.DiffieHellmanImpl.class.getName());
+ put("Alg.Alias.KeyAgreement.DH", "DiffieHellman");
+
+ // Cipher
+ put("Cipher.RSAES-PKCS1-v1_5",
+ gnu.javax.crypto.RSACipherImpl.class.getName());
+ put("Alg.Alias.Cipher.RSA", "RSAES-PKCS1-v1_5");
+
+ // SecureRandom
+ put("SecureRandom.ARCFOUR", gnu.javax.crypto.jce.prng.ARCFourRandomSpi.class.getName());
+ put("SecureRandom.ARCFOUR ImplementedIn", "Software");
+ put("SecureRandom.CSPRNG", gnu.javax.crypto.jce.prng.CSPRNGSpi.class.getName());
+ put("SecureRandom.CSPRNG ImplementedIn", "Software");
+ put("SecureRandom.ICM", gnu.javax.crypto.jce.prng.ICMRandomSpi.class.getName());
+ put("SecureRandom.ICM ImplementedIn", "Software");
+ put("SecureRandom.UMAC-KDF", gnu.javax.crypto.jce.prng.UMacRandomSpi.class.getName());
+ put("SecureRandom.UMAC-KDF ImplementedIn", "Software");
+ put("SecureRandom.Fortuna", gnu.javax.crypto.jce.prng.FortunaImpl.class.getName ());
+ put("SecureRandom.Fortuna ImplementedIn", "Software");
+
+ // KeyStore
+ put("KeyStore.GKR", gnu.javax.crypto.jce.keyring.GnuKeyring.class.getName());
+ put("Alg.Alias.KeyStore.GnuKeyring", "GKR");
+
+ return null;
+ }
+ });
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns a {@link Set} of names of symmetric key block cipher algorithms
+ * available from this {@link Provider}.</p>
+ *
+ * @return a {@link Set} of cipher names (Strings).
+ */
+ public static final Set getCipherNames()
+ {
+ HashSet s = new HashSet();
+ s.addAll(CipherFactory.getNames());
+ s.add(Registry.ARCFOUR_PRNG);
+ return s;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of names of MAC algorithms available from
+ * this {@link Provider}.</p>
+ *
+ * @return a {@link Set} of MAC names (Strings).
+ */
+ public static final Set getMacNames()
+ {
+ return MacFactory.getNames();
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/javax/crypto/jce/GnuSasl.java b/gnu/javax/crypto/jce/GnuSasl.java
new file mode 100644
index 000000000..6ee86ae19
--- /dev/null
+++ b/gnu/javax/crypto/jce/GnuSasl.java
@@ -0,0 +1,114 @@
+/* GnuSasl.java -- javax.security.sasl algorithms.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.ClientFactory;
+import gnu.javax.crypto.sasl.ServerFactory;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.util.Set;
+
+public final class GnuSasl extends Provider
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public GnuSasl()
+ {
+ super (Registry.GNU_SASL, 2.1, "GNU Crypto SASL Provider");
+
+ AccessController.doPrivileged (new PrivilegedAction()
+ {
+ public Object run()
+ {
+ // SASL Client and Server mechanisms
+ put("SaslClientFactory.ANONYMOUS", gnu.javax.crypto.sasl.ClientFactory.class.getName());
+ put("SaslClientFactory.PLAIN", gnu.javax.crypto.sasl.ClientFactory.class.getName());
+ put("SaslClientFactory.CRAM-MD5", gnu.javax.crypto.sasl.ClientFactory.class.getName());
+ put("SaslClientFactory.SRP", gnu.javax.crypto.sasl.ClientFactory.class.getName());
+
+ put("SaslServerFactory.ANONYMOUS", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+ put("SaslServerFactory.PLAIN", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+ put("SaslServerFactory.CRAM-MD5", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+ put("SaslServerFactory.SRP-MD5", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+ put("SaslServerFactory.SRP-SHA-160", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+ put("SaslServerFactory.SRP-RIPEMD128", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+ put("SaslServerFactory.SRP-RIPEMD160", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+ put("SaslServerFactory.SRP-TIGER", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+ put("SaslServerFactory.SRP-WHIRLPOOL", gnu.javax.crypto.sasl.ServerFactory.class.getName());
+
+ put("Alg.Alias.SaslServerFactory.SRP-SHS", "SRP-SHA-160");
+ put("Alg.Alias.SaslServerFactory.SRP-SHA", "SRP-SHA-160");
+ put("Alg.Alias.SaslServerFactory.SRP-SHA1", "SRP-SHA-160");
+ put("Alg.Alias.SaslServerFactory.SRP-SHA-1", "SRP-SHA-160");
+ put("Alg.Alias.SaslServerFactory.SRP-SHA160", "SRP-SHA-160");
+ put("Alg.Alias.SaslServerFactory.SRP-RIPEMD-128", "SRP-RIPEMD128");
+ put("Alg.Alias.SaslServerFactory.SRP-RIPEMD-160", "SRP-RIPEMD160");
+
+ return null;
+ }
+ });
+ }
+
+ /**
+ * <p>Returns a {@link Set} of names of SASL Client mechanisms available from
+ * this {@link Provider}.</p>
+ *
+ * @return a {@link Set} of SASL Client mechanisms (Strings).
+ */
+ public static final Set getSaslClientMechanismNames()
+ {
+ return ClientFactory.getNames();
+ }
+
+ /**
+ * <p>Returns a {@link Set} of names of SASL Server mechanisms available from
+ * this {@link Provider}.</p>
+ *
+ * @return a {@link Set} of SASL Server mechanisms (Strings).
+ */
+ public static final Set getSaslServerMechanismNames()
+ {
+ return ServerFactory.getNames();
+ }
+}
diff --git a/gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java b/gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java
new file mode 100644
index 000000000..59231c6c7
--- /dev/null
+++ b/gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java
@@ -0,0 +1,229 @@
+/* PBKDF2SecretKeyFactory.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce;
+
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+import java.util.HashMap;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import gnu.javax.crypto.prng.IPBE;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.prng.PRNGFactory;
+
+public abstract class PBKDF2SecretKeyFactory extends SecretKeyFactorySpi
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ protected String macName;
+
+ private static final int DEFAULT_ITERATION_COUNT = 1000;
+
+ private static final int DEFAULT_KEY_LEN = 32;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ protected PBKDF2SecretKeyFactory(String macName)
+ {
+ this.macName = macName;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ protected SecretKey engineGenerateSecret(KeySpec spec)
+ throws InvalidKeySpecException
+ {
+ if (!(spec instanceof PBEKeySpec))
+ {
+ throw new InvalidKeySpecException("not a PBEKeySpec");
+ }
+ IRandom kdf = PRNGFactory.getInstance("PBKDF2-" + macName);
+ HashMap attr = new HashMap();
+ attr.put(IPBE.PASSWORD, ((PBEKeySpec) spec).getPassword());
+ byte[] salt = ((PBEKeySpec) spec).getSalt();
+ if (salt == null)
+ {
+ salt = new byte[0];
+ }
+ attr.put(IPBE.SALT, salt);
+ int ic = ((PBEKeySpec) spec).getIterationCount();
+ if (ic <= 0)
+ {
+ ic = DEFAULT_ITERATION_COUNT;
+ }
+ attr.put(IPBE.ITERATION_COUNT, new Integer(ic));
+ kdf.init(attr);
+ int len = ((PBEKeySpec) spec).getKeyLength();
+ if (len <= 0)
+ {
+ len = DEFAULT_KEY_LEN;
+ }
+ byte[] dk = new byte[len];
+ try
+ {
+ kdf.nextBytes(dk, 0, len);
+ }
+ catch (LimitReachedException lre)
+ {
+ throw new IllegalArgumentException(lre.toString());
+ }
+
+ return new SecretKeySpec(dk, "PBKDF2");
+ }
+
+ protected KeySpec engineGetKeySpec(SecretKey key, Class clazz)
+ throws InvalidKeySpecException
+ {
+ throw new InvalidKeySpecException("not supported");
+ }
+
+ protected SecretKey engineTranslateKey(SecretKey key)
+ {
+ return new SecretKeySpec(key.getEncoded(), key.getAlgorithm());
+ }
+
+ // Inner classes.
+ // ------------------------------------------------------------------------
+
+ public static class HMacHaval extends PBKDF2SecretKeyFactory
+ {
+ public HMacHaval()
+ {
+ super("HMAC-HAVAL");
+ }
+ }
+
+ public static class HMacMD2 extends PBKDF2SecretKeyFactory
+ {
+ public HMacMD2()
+ {
+ super("HMAC-MD2");
+ }
+ }
+
+ public static class HMacMD4 extends PBKDF2SecretKeyFactory
+ {
+ public HMacMD4()
+ {
+ super("HMAC-MD4");
+ }
+ }
+
+ public static class HMacMD5 extends PBKDF2SecretKeyFactory
+ {
+ public HMacMD5()
+ {
+ super("HMAC-MD5");
+ }
+ }
+
+ public static class HMacRipeMD128 extends PBKDF2SecretKeyFactory
+ {
+ public HMacRipeMD128()
+ {
+ super("HMAC-RIPEMD128");
+ }
+ }
+
+ public static class HMacRipeMD160 extends PBKDF2SecretKeyFactory
+ {
+ public HMacRipeMD160()
+ {
+ super("HMAC-RIPEMD160");
+ }
+ }
+
+ public static class HMacSHA1 extends PBKDF2SecretKeyFactory
+ {
+ public HMacSHA1()
+ {
+ super("HMAC-SHA1");
+ }
+ }
+
+ public static class HMacSHA256 extends PBKDF2SecretKeyFactory
+ {
+ public HMacSHA256()
+ {
+ super("HMAC-SHA256");
+ }
+ }
+
+ public static class HMacSHA384 extends PBKDF2SecretKeyFactory
+ {
+ public HMacSHA384()
+ {
+ super("HMAC-SHA384");
+ }
+ }
+
+ public static class HMacSHA512 extends PBKDF2SecretKeyFactory
+ {
+ public HMacSHA512()
+ {
+ super("HMAC-SHA512");
+ }
+ }
+
+ public static class HMacTiger extends PBKDF2SecretKeyFactory
+ {
+ public HMacTiger()
+ {
+ super("HMAC-TIGER");
+ }
+ }
+
+ public static class HMacWhirlpool extends PBKDF2SecretKeyFactory
+ {
+ public HMacWhirlpool()
+ {
+ super("HMAC-WHIRLPOOL");
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/AESSpi.java b/gnu/javax/crypto/jce/cipher/AESSpi.java
new file mode 100644
index 000000000..ba7466fc3
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/AESSpi.java
@@ -0,0 +1,104 @@
+/* AESSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.jce.spec.BlockCipherParameterSpec;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+/**
+ * The implementation of the AES <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class AESSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public AESSpi()
+ {
+ super(Registry.AES_CIPHER, 16);
+ }
+
+ // Methods from CipherAdapter
+ // -----------------------------------------------------------------------
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+ SecureRandom random) throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ if (params instanceof BlockCipherParameterSpec)
+ {
+ if (((BlockCipherParameterSpec) params).getBlockSize() != 16)
+ {
+ throw new InvalidAlgorithmParameterException(
+ "AES block size must be 16 bytes");
+ }
+ }
+ super.engineInit(opmode, key, params, random);
+ }
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random) throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ AlgorithmParameterSpec spec = null;
+ try
+ {
+ if (params != null)
+ {
+ spec = params.getParameterSpec(BlockCipherParameterSpec.class);
+ }
+ }
+ catch (InvalidParameterSpecException ipse)
+ {
+ }
+ engineInit(opmode, key, spec, random);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/ARCFourSpi.java b/gnu/javax/crypto/jce/cipher/ARCFourSpi.java
new file mode 100644
index 000000000..8fc1fe4cb
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/ARCFourSpi.java
@@ -0,0 +1,208 @@
+/* ARCFourSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.prng.ARCFour;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.prng.PRNGFactory;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import java.util.HashMap;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+
+/**
+ * The <i>Service Provider Interface</i> (<b>SPI</b>) for the ARCFOUR
+ * stream cipher.
+ *
+ * @version $Revision: 1.1 $
+ */
+public class ARCFourSpi extends CipherSpi
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ private IRandom keystream;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public ARCFourSpi()
+ {
+ super();
+ keystream = PRNGFactory.getInstance(Registry.ARCFOUR_PRNG);
+ }
+
+ // Methods implementing CipherSpi.
+ // -----------------------------------------------------------------------
+
+ protected int engineGetBlockSize()
+ {
+ return 0; // stream cipher.
+ }
+
+ protected void engineSetMode(String s) throws NoSuchAlgorithmException
+ {
+ // ignored.
+ }
+
+ protected void engineSetPadding(String s) throws NoSuchPaddingException
+ {
+ // ignored.
+ }
+
+ protected byte[] engineGetIV()
+ {
+ return null;
+ }
+
+ protected int engineGetOutputSize(int in)
+ {
+ return in;
+ }
+
+ protected AlgorithmParameters engineGetParameters()
+ {
+ return null;
+ }
+
+ protected void engineInit(int mode, Key key, SecureRandom r)
+ throws InvalidKeyException
+ {
+ if (mode != Cipher.ENCRYPT_MODE && mode != Cipher.DECRYPT_MODE)
+ {
+ throw new IllegalArgumentException(
+ "arcfour is for encryption or decryption only");
+ }
+ if (key == null || !key.getFormat().equalsIgnoreCase("RAW"))
+ {
+ throw new InvalidKeyException("key must be non-null raw bytes");
+ }
+ HashMap attrib = new HashMap();
+ attrib.put(ARCFour.ARCFOUR_KEY_MATERIAL, key.getEncoded());
+ keystream.init(attrib);
+ }
+
+ protected void engineInit(int mode, Key key, AlgorithmParameterSpec p,
+ SecureRandom r) throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ engineInit(mode, key, r);
+ }
+
+ protected void engineInit(int mode, Key key, AlgorithmParameters p,
+ SecureRandom r) throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ engineInit(mode, key, r);
+ }
+
+ protected byte[] engineUpdate(byte[] in, int offset, int length)
+ {
+ if (length < 0 || offset < 0 || length + offset > in.length)
+ {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ byte[] result = new byte[length];
+ try
+ {
+ for (int i = 0; i < length; i++)
+ {
+ result[i] = (byte) (in[i + offset] ^ keystream.nextByte());
+ }
+ }
+ catch (LimitReachedException wontHappen)
+ {
+ }
+ return result;
+ }
+
+ protected int engineUpdate(byte[] in, int inOffset, int length, byte[] out,
+ int outOffset) throws ShortBufferException
+ {
+ if (length < 0 || inOffset < 0 || length + inOffset > in.length
+ || outOffset < 0)
+ {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (outOffset + length > out.length)
+ {
+ throw new ShortBufferException();
+ }
+ try
+ {
+ for (int i = 0; i < length; i++)
+ {
+ out[i + outOffset] = (byte) (in[i + inOffset] ^ keystream.nextByte());
+ }
+ }
+ catch (LimitReachedException wontHappen)
+ {
+ }
+ return length;
+ }
+
+ protected byte[] engineDoFinal(byte[] in, int offset, int length)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ return engineUpdate(in, offset, length);
+ }
+
+ protected int engineDoFinal(byte[] in, int inOffset, int length, byte[] out,
+ int outOffset) throws ShortBufferException,
+ IllegalBlockSizeException, BadPaddingException
+ {
+ return engineUpdate(in, inOffset, length, out, outOffset);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/AnubisSpi.java b/gnu/javax/crypto/jce/cipher/AnubisSpi.java
new file mode 100644
index 000000000..ac2f596c8
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/AnubisSpi.java
@@ -0,0 +1,59 @@
+/* AnubisSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Anubis <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class AnubisSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public AnubisSpi()
+ {
+ super(Registry.ANUBIS_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/BlowfishSpi.java b/gnu/javax/crypto/jce/cipher/BlowfishSpi.java
new file mode 100644
index 000000000..d1a28616d
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/BlowfishSpi.java
@@ -0,0 +1,59 @@
+/* BlowfishSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Blowfish <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class BlowfishSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public BlowfishSpi()
+ {
+ super(Registry.BLOWFISH_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/Cast5Spi.java b/gnu/javax/crypto/jce/cipher/Cast5Spi.java
new file mode 100644
index 000000000..b1d4cf703
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/Cast5Spi.java
@@ -0,0 +1,68 @@
+/* Cast5Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the <code>CAST5</code> (a.k.a. CAST-128) <i>Service
+ * Provider Interface</i> (<b>SPI</b>) Adapter.
+ *
+ * @version Revision: $
+ */
+public class Cast5Spi extends CipherAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Cast5Spi()
+ {
+ super(Registry.CAST5_CIPHER);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/CipherAdapter.java b/gnu/javax/crypto/jce/cipher/CipherAdapter.java
new file mode 100644
index 000000000..9667a67ff
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/CipherAdapter.java
@@ -0,0 +1,507 @@
+/* CipherAdapter.java --
+ Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.jce.spec.BlockCipherParameterSpec;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+import gnu.javax.crypto.pad.IPad;
+import gnu.javax.crypto.pad.PadFactory;
+import gnu.javax.crypto.pad.WrongPaddingException;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * <p>The implementation of a generic {@link Cipher} <i>Adapter</i> class to
+ * wrap GNU Crypto cipher instances.</p>
+ *
+ * <p>This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
+ * the {@link Cipher} class, which provides the functionality of symmetric-key
+ * block ciphers, such as the AES.<p>
+ *
+ * <p>This base class defines all of the abstract methods in {@link CipherSpi},
+ * but does not define the (non-abstract) key wrapping functions that extended
+ * the base cipher SPI, and these methods thus immediately throw an
+ * {@link UnsupportedOperationException}. If a cipher implementation provides
+ * this functionality, or if it in fact accepts parameters other than the key
+ * and the initialization vector, the subclass should override those methods.
+ * Otherwise a subclass need only call the {@link #CipherAdapter(String)}
+ * constructor with the name of the cipher.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+class CipherAdapter extends CipherSpi
+{
+
+ // Constants and variables.
+ // -------------------------------------------------------------------------
+
+ /** Our cipher instance. */
+ protected IBlockCipher cipher;
+
+ /** Our mode instance. */
+ protected IMode mode;
+
+ /** Our padding instance. */
+ protected IPad pad;
+
+ /** The current key size. */
+ protected int keyLen;
+
+ /** Our attributes map. */
+ protected Map attributes;
+
+ /** An incomplete block. */
+ protected byte[] partBlock;
+
+ /** The number of bytes in {@link #partBlock}. */
+ protected int partLen;
+
+ /** The length of blocks we are processing. */
+ protected int blockLen;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Protected constructor to be called by subclasses. The cipher name
+ * argument should be the appropriate one listed in {@link gnu.crypto.Registry}.
+ * The basic cipher instance is created, along with an instance of the
+ * {@link gnu.crypto.mode.ECB} mode and no padding.</p>
+ *
+ * @param cipherName The cipher to instantiate.
+ * @param blockLen The block length to use.
+ */
+ protected CipherAdapter(String cipherName, int blockLen)
+ {
+ cipher = CipherFactory.getInstance(cipherName);
+ attributes = new HashMap();
+ this.blockLen = blockLen;
+ mode = ModeFactory.getInstance("ECB", cipher, blockLen);
+ attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(blockLen));
+ }
+
+ /**
+ * <p>Creates a new cipher adapter with the default block size.</p>
+ *
+ * @param cipherName The cipher to instantiate.
+ */
+ protected CipherAdapter(String cipherName)
+ {
+ cipher = CipherFactory.getInstance(cipherName);
+ blockLen = cipher.defaultBlockSize();
+ attributes = new HashMap();
+ mode = ModeFactory.getInstance("ECB", cipher, blockLen);
+ attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(blockLen));
+ }
+
+ // Instance methods implementing javax.crypto.CipherSpi.
+ // -------------------------------------------------------------------------
+
+ protected void engineSetMode(String modeName) throws NoSuchAlgorithmException
+ {
+ if (modeName.length() >= 3
+ && modeName.substring(0, 3).equalsIgnoreCase("CFB"))
+ {
+ if (modeName.length() > 3)
+ {
+ try
+ {
+ int bs = Integer.parseInt(modeName.substring(3));
+ attributes.put(IMode.MODE_BLOCK_SIZE, new Integer(bs / 8));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new NoSuchAlgorithmException(modeName);
+ }
+ modeName = "CFB";
+ }
+ }
+ else
+ {
+ attributes.remove(IMode.MODE_BLOCK_SIZE);
+ }
+ mode = ModeFactory.getInstance(modeName, cipher, blockLen);
+ if (mode == null)
+ {
+ throw new NoSuchAlgorithmException(modeName);
+ }
+ }
+
+ protected void engineSetPadding(String padName) throws NoSuchPaddingException
+ {
+ if (padName.equalsIgnoreCase("NoPadding"))
+ {
+ pad = null;
+ return;
+ }
+ pad = PadFactory.getInstance(padName);
+ if (pad == null)
+ {
+ throw new NoSuchPaddingException(padName);
+ }
+ }
+
+ protected int engineGetBlockSize()
+ {
+ if (cipher != null)
+ {
+ return blockLen;
+ }
+ return 0;
+ }
+
+ protected int engineGetOutputSize(int inputLen)
+ {
+ final int blockSize = mode.currentBlockSize();
+ return ((inputLen + partLen) / blockSize) * blockSize;
+ }
+
+ protected byte[] engineGetIV()
+ {
+ byte[] iv = (byte[]) attributes.get(IMode.IV);
+ if (iv == null)
+ {
+ return null;
+ }
+ return (byte[]) iv.clone();
+ }
+
+ protected AlgorithmParameters engineGetParameters()
+ {
+ BlockCipherParameterSpec spec = new BlockCipherParameterSpec(
+ (byte[]) attributes.get(IMode.IV),
+ cipher.currentBlockSize(),
+ keyLen);
+ AlgorithmParameters params;
+ try
+ {
+ params = AlgorithmParameters.getInstance("BlockCipherParameters");
+ params.init(spec);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ return null;
+ }
+ catch (InvalidParameterSpecException ipse)
+ {
+ return null;
+ }
+ return params;
+ }
+
+ protected void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException
+ {
+ switch (opmode)
+ {
+ case Cipher.ENCRYPT_MODE:
+ attributes.put(IMode.STATE, new Integer(IMode.ENCRYPTION));
+ break;
+ case Cipher.DECRYPT_MODE:
+ attributes.put(IMode.STATE, new Integer(IMode.DECRYPTION));
+ break;
+ }
+ if (!key.getFormat().equalsIgnoreCase("RAW"))
+ {
+ throw new InvalidKeyException("bad key format " + key.getFormat());
+ }
+ byte[] kb = key.getEncoded();
+ if (keyLen == 0)
+ {
+ keyLen = kb.length;
+ }
+ else if (keyLen < kb.length)
+ {
+ byte[] kbb = kb;
+ kb = new byte[keyLen];
+ System.arraycopy(kbb, 0, kb, 0, keyLen);
+ }
+ attributes.put(IBlockCipher.KEY_MATERIAL, kb);
+ reset();
+ }
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+ SecureRandom random) throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ if (params == null)
+ {
+ byte[] iv = new byte[blockLen];
+ random.nextBytes(iv);
+ attributes.put(IMode.IV, iv);
+ blockLen = cipher.defaultBlockSize();
+ attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(blockLen));
+ keyLen = 0;
+ }
+ else if (params instanceof BlockCipherParameterSpec)
+ {
+ attributes.put(
+ IBlockCipher.CIPHER_BLOCK_SIZE,
+ new Integer(
+ ((BlockCipherParameterSpec) params).getBlockSize()));
+ attributes.put(IMode.IV, ((BlockCipherParameterSpec) params).getIV());
+ keyLen = ((BlockCipherParameterSpec) params).getKeySize();
+ blockLen = ((BlockCipherParameterSpec) params).getBlockSize();
+ }
+ else if (params instanceof IvParameterSpec)
+ {
+ attributes.put(IMode.IV, ((IvParameterSpec) params).getIV());
+ blockLen = cipher.defaultBlockSize();
+ attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(blockLen));
+ keyLen = 0;
+ }
+ engineInit(opmode, key, random);
+ }
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random) throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ AlgorithmParameterSpec spec = null;
+ try
+ {
+ if (params != null)
+ {
+ spec = params.getParameterSpec(BlockCipherParameterSpec.class);
+ }
+ }
+ catch (InvalidParameterSpecException ignored)
+ {
+ }
+ engineInit(opmode, key, spec, random);
+ }
+
+ protected byte[] engineUpdate(byte[] input, int off, int len)
+ {
+ final int blockSize = mode.currentBlockSize();
+ final int count = (partLen + len) / blockSize;
+ final byte[] out = new byte[count * blockSize];
+ try
+ {
+ engineUpdate(input, off, len, out, 0);
+ }
+ catch (ShortBufferException x)
+ { // should not happen
+ x.printStackTrace(System.err);
+ }
+ return out;
+ }
+
+ // protected int
+ // engineUpdate(byte[] in, int inOff, int inLen, byte[] out, int outOff)
+ // throws ShortBufferException
+ // {
+ // int blockSize = mode.currentBlockSize();
+ // int count = (partLen + inLen) / blockSize;
+ // if (count * blockSize > out.length - outOff) {
+ // throw new ShortBufferException();
+ // }
+ // byte[] buf;
+ // if (partLen > 0 && count > 0) {
+ // buf = new byte[partLen + inLen];
+ // System.arraycopy(partBlock, 0, buf, 0, partLen);
+ // if (in != null && inLen > 0) {
+ // System.arraycopy(in, inOff, buf, partLen, inLen);
+ // }
+ // partLen = 0;
+ // inOff = 0;
+ // } else {
+ // buf = in;
+ // }
+ // for (int i = 0; i < count; i++) {
+ // mode.update(buf, i * blockSize + inOff, out, i * blockSize + outOff);
+ // }
+ // if (inOff + inLen > count * blockSize) {
+ // partLen = (inOff + inLen) - (count * blockSize);
+ // System.arraycopy(in, count * blockSize, partBlock, 0, partLen);
+ // }
+ // return count * blockSize;
+ // }
+
+ protected int engineUpdate(byte[] in, int inOff, int inLen, byte[] out,
+ int outOff) throws ShortBufferException
+ {
+ if (inLen == 0)
+ { // nothing to process
+ return 0;
+ }
+ final int blockSize = mode.currentBlockSize();
+ final int blockCount = (partLen + inLen) / blockSize;
+ final int result = blockCount * blockSize;
+ if (result > out.length - outOff)
+ {
+ throw new ShortBufferException();
+ }
+ if (blockCount == 0)
+ { // not enough bytes for even 1 block
+ System.arraycopy(in, inOff, partBlock, partLen, inLen);
+ partLen += inLen;
+ return 0;
+ }
+ final byte[] buf;
+ // we have enough bytes for at least 1 block
+ if (partLen == 0)
+ { // if no cached bytes use input
+ buf = in;
+ }
+ else
+ { // prefix input with cached bytes
+ buf = new byte[partLen + inLen];
+ System.arraycopy(partBlock, 0, buf, 0, partLen);
+ if (in != null && inLen > 0)
+ {
+ System.arraycopy(in, inOff, buf, partLen, inLen);
+ }
+ inOff = 0;
+ }
+ for (int i = 0; i < blockCount; i++)
+ { // update blockCount * blockSize
+ mode.update(buf, inOff, out, outOff);
+ inOff += blockSize;
+ outOff += blockSize;
+ }
+ partLen += inLen - result;
+ if (partLen > 0)
+ { // cache remaining bytes from buf
+ System.arraycopy(buf, inOff, partBlock, 0, partLen);
+ }
+ return result;
+ }
+
+ protected byte[] engineDoFinal(byte[] input, int off, int len)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ final byte[] result;
+ final byte[] buf = engineUpdate(input, off, len);
+ if (pad != null)
+ {
+ switch (((Integer) attributes.get(IMode.STATE)).intValue())
+ {
+ case IMode.ENCRYPTION:
+ byte[] padding = pad.pad(partBlock, 0, partLen);
+ byte[] buf2 = engineUpdate(padding, 0, padding.length);
+ result = new byte[buf.length + buf2.length];
+ System.arraycopy(buf, 0, result, 0, buf.length);
+ System.arraycopy(buf2, 0, result, buf.length, buf2.length);
+ break;
+ case IMode.DECRYPTION:
+ int padLen;
+ try
+ {
+ padLen = pad.unpad(buf, 0, buf.length);
+ }
+ catch (WrongPaddingException wpe)
+ {
+ throw new BadPaddingException(wpe.getMessage());
+ }
+ result = new byte[buf.length - padLen];
+ System.arraycopy(buf, 0, result, 0, result.length);
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ else
+ {
+ if (partLen > 0)
+ {
+ throw new IllegalBlockSizeException(partLen + " trailing bytes");
+ }
+ result = buf;
+ }
+
+ try
+ {
+ reset();
+ }
+ catch (InvalidKeyException ike)
+ {
+ // Should not happen; if we initialized it with the current
+ // parameters before, we should be able to do it again.
+ throw new Error(ike);
+ }
+ return result;
+ }
+
+ protected int engineDoFinal(byte[] in, int inOff, int inLen, byte[] out,
+ int outOff) throws BadPaddingException,
+ IllegalBlockSizeException, ShortBufferException
+ {
+ byte[] buf = engineDoFinal(in, inOff, inLen);
+ if (out.length + outOff < buf.length)
+ {
+ throw new ShortBufferException();
+ }
+ System.arraycopy(buf, 0, out, outOff, buf.length);
+ return buf.length;
+ }
+
+ private void reset() throws InvalidKeyException
+ {
+ mode.reset();
+ mode.init(attributes);
+ if (pad != null)
+ {
+ pad.reset();
+ pad.init(blockLen);
+ }
+ partBlock = new byte[blockLen];
+ partLen = 0;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/DESSpi.java b/gnu/javax/crypto/jce/cipher/DESSpi.java
new file mode 100644
index 000000000..f3ec8220a
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/DESSpi.java
@@ -0,0 +1,59 @@
+/* DESSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the DES <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class DESSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public DESSpi()
+ {
+ super(Registry.DES_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/KhazadSpi.java b/gnu/javax/crypto/jce/cipher/KhazadSpi.java
new file mode 100644
index 000000000..7f43dd010
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/KhazadSpi.java
@@ -0,0 +1,59 @@
+/* KhazadSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Khazad <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class KhazadSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public KhazadSpi()
+ {
+ super(Registry.KHAZAD_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/NullCipherSpi.java b/gnu/javax/crypto/jce/cipher/NullCipherSpi.java
new file mode 100644
index 000000000..0876c9585
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/NullCipherSpi.java
@@ -0,0 +1,59 @@
+/* NullCipherSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Null cipher <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class NullCipherSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public NullCipherSpi()
+ {
+ super(Registry.NULL_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/PBES2.java b/gnu/javax/crypto/jce/cipher/PBES2.java
new file mode 100644
index 000000000..28b327d83
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/PBES2.java
@@ -0,0 +1,1352 @@
+/* PBES2.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.javax.crypto.prng.IPBE;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.prng.PRNGFactory;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.HashMap;
+
+import javax.crypto.interfaces.PBEKey;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * <p>.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public abstract class PBES2 extends CipherAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The HMac (PRF) algorithm name. */
+ protected String macName;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected PBES2(String cipherName, int blockLen, String macName)
+ {
+ super(cipherName, blockLen);
+ this.macName = macName;
+ }
+
+ protected PBES2(String cipherName, String macName)
+ {
+ super(cipherName);
+ this.macName = macName;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ protected void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException
+ {
+ if (!(key instanceof PBEKey))
+ throw new InvalidKeyException("not a PBE key");
+
+ super.engineInit(opmode, genkey((PBEKey) key), random);
+ }
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+ SecureRandom random) throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ if (!(key instanceof PBEKey))
+ throw new InvalidKeyException("not a PBE key");
+
+ super.engineInit(opmode, genkey((PBEKey) key), params, random);
+ }
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random) throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ if (!(key instanceof PBEKey))
+ throw new InvalidKeyException("not a PBE key");
+
+ super.engineInit(opmode, genkey((PBEKey) key), params, random);
+ }
+
+ private SecretKeySpec genkey(PBEKey key) throws InvalidKeyException
+ {
+ IRandom kdf = PRNGFactory.getInstance("PBKDF2-" + macName);
+ if (kdf == null)
+ {
+ throw new IllegalArgumentException("no such KDF: PBKDF2-" + macName);
+ }
+ HashMap attrib = new HashMap();
+ attrib.put(IPBE.ITERATION_COUNT, new Integer(key.getIterationCount()));
+ attrib.put(IPBE.PASSWORD, key.getPassword());
+ attrib.put(IPBE.SALT, key.getSalt());
+ try
+ {
+ kdf.init(attrib);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new InvalidKeyException(iae.toString());
+ }
+ byte[] dk = new byte[mode.defaultKeySize()];
+ try
+ {
+ kdf.nextBytes(dk, 0, dk.length);
+ }
+ catch (LimitReachedException shouldNotHappen)
+ {
+ // throw new Error(shouldNotHappen);
+ throw new Error(String.valueOf(shouldNotHappen));
+ }
+ return new SecretKeySpec(dk, cipher.name());
+ }
+
+ // Inner classe(s)
+ // =========================================================================
+
+ public static class HMacSHA1 extends PBES2
+ {
+
+ // Constructor(s)
+ // ---------------------------------------------------------------------
+
+ public HMacSHA1(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-SHA1");
+ }
+
+ public HMacSHA1(String cipher)
+ {
+ super(cipher, "HMAC-SHA1");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacSHA1
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacSHA1
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacSHA1
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacSHA1
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacSHA1
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacSHA1
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacSHA1
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacSHA1
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacSHA1
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacSHA1
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacMD5 extends PBES2
+ {
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ public HMacMD5(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-MD5");
+ }
+
+ public HMacMD5(String cipher)
+ {
+ super(cipher, "HMAC-MD5");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacMD5
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacMD5
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacMD5
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacMD5
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacMD5
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacMD5
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacMD5
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacMD5
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacMD5
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacMD5
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacMD2 extends PBES2
+ {
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ public HMacMD2(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-MD2");
+ }
+
+ public HMacMD2(String cipher)
+ {
+ super(cipher, "HMAC-MD2");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacMD2
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacMD2
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacMD2
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacMD2
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacMD2
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacMD2
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacMD2
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacMD2
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacMD2
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacMD2
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacMD4 extends PBES2
+ {
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ public HMacMD4(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-MD4");
+ }
+
+ public HMacMD4(String cipher)
+ {
+ super(cipher, "HMAC-MD4");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacMD4
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacMD4
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacMD4
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacMD4
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacMD4
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacMD4
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacMD4
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacMD4
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacMD4
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacMD4
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacHaval extends PBES2
+ {
+
+ // Constructor(s)
+ // ---------------------------------------------------------------------
+
+ public HMacHaval(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-HAVAL");
+ }
+
+ public HMacHaval(String cipher)
+ {
+ super(cipher, "HMAC-HAVAL");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacHaval
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacHaval
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacHaval
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacHaval
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacHaval
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacHaval
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacHaval
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacHaval
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacHaval
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacHaval
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacRipeMD128 extends PBES2
+ {
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ public HMacRipeMD128(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-RIPEMD128");
+ }
+
+ public HMacRipeMD128(String cipher)
+ {
+ super(cipher, "HMAC-RIPEMD128");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacRipeMD128
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacRipeMD128
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacRipeMD128
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacRipeMD128
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacRipeMD128
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacRipeMD128
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacRipeMD128
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacRipeMD128
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacRipeMD128
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacRipeMD128
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacRipeMD160 extends PBES2
+ {
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ public HMacRipeMD160(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-RIPEMD160");
+ }
+
+ public HMacRipeMD160(String cipher)
+ {
+ super(cipher, "HMAC-RIPEMD160");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacRipeMD160
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacRipeMD160
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacRipeMD160
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacRipeMD160
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacRipeMD160
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacRipeMD160
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacRipeMD160
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacRipeMD160
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacRipeMD160
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacRipeMD160
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacSHA256 extends PBES2
+ {
+
+ // Constructor(s)
+ // ---------------------------------------------------------------------
+
+ public HMacSHA256(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-SHA-256");
+ }
+
+ public HMacSHA256(String cipher)
+ {
+ super(cipher, "HMAC-SHA-256");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacSHA256
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacSHA256
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacSHA256
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacSHA256
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacSHA256
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacSHA256
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacSHA256
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacSHA256
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacSHA256
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacSHA256
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacSHA384 extends PBES2
+ {
+
+ // Constructor(s)
+ // ---------------------------------------------------------------------
+
+ public HMacSHA384(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-SHA-384");
+ }
+
+ public HMacSHA384(String cipher)
+ {
+ super(cipher, "HMAC-SHA-384");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacSHA384
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacSHA384
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacSHA384
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacSHA384
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacSHA384
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacSHA384
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacSHA384
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacSHA384
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacSHA384
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacSHA384
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacSHA512 extends PBES2
+ {
+
+ // Constructor(s)
+ // ---------------------------------------------------------------------
+
+ public HMacSHA512(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-SHA-512");
+ }
+
+ public HMacSHA512(String cipher)
+ {
+ super(cipher, "HMAC-SHA-512");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacSHA512
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacSHA512
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacSHA512
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacSHA512
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacSHA512
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacSHA512
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacSHA512
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacSHA512
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacSHA512
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacSHA512
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacTiger extends PBES2
+ {
+
+ // Constructor(s)
+ // ---------------------------------------------------------------------
+
+ public HMacTiger(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-TIGER");
+ }
+
+ public HMacTiger(String cipher)
+ {
+ super(cipher, "HMAC-TIGER");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacTiger
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacTiger
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacTiger
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacTiger
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacTiger
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacTiger
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacTiger
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacTiger
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacTiger
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacTiger
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+
+ public static class HMacWhirlpool extends PBES2
+ {
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ public HMacWhirlpool(String cipher, int blockLen)
+ {
+ super(cipher, blockLen, "HMAC-WHIRLPOOL");
+ }
+
+ public HMacWhirlpool(String cipher)
+ {
+ super(cipher, "HMAC-WHIRLPOOL");
+ }
+
+ // Inner classe(s)
+ // ======================================================================
+
+ public static class AES extends HMacWhirlpool
+ {
+ public AES()
+ {
+ super("AES");
+ }
+ }
+
+ public static class Anubis extends HMacWhirlpool
+ {
+ public Anubis()
+ {
+ super("Anubis");
+ }
+ }
+
+ public static class Blowfish extends HMacWhirlpool
+ {
+ public Blowfish()
+ {
+ super("Blowfish");
+ }
+ }
+
+ public static class Cast5 extends HMacWhirlpool
+ {
+ public Cast5()
+ {
+ super("Cast5");
+ }
+ }
+
+ public static class DES extends HMacWhirlpool
+ {
+ public DES()
+ {
+ super("DES");
+ }
+ }
+
+ public static class Khazad extends HMacWhirlpool
+ {
+ public Khazad()
+ {
+ super("Khazad");
+ }
+ }
+
+ public static class Serpent extends HMacWhirlpool
+ {
+ public Serpent()
+ {
+ super("Serpent");
+ }
+ }
+
+ public static class Square extends HMacWhirlpool
+ {
+ public Square()
+ {
+ super("Square");
+ }
+ }
+
+ public static class TripleDES extends HMacWhirlpool
+ {
+ public TripleDES()
+ {
+ super("TripleDES");
+ }
+ }
+
+ public static class Twofish extends HMacWhirlpool
+ {
+ public Twofish()
+ {
+ super("Twofish");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/RijndaelSpi.java b/gnu/javax/crypto/jce/cipher/RijndaelSpi.java
new file mode 100644
index 000000000..1a67f934b
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/RijndaelSpi.java
@@ -0,0 +1,59 @@
+/* RijndaelSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Rijndael <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class RijndaelSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public RijndaelSpi()
+ {
+ super(Registry.RIJNDAEL_CIPHER, 16);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/SerpentSpi.java b/gnu/javax/crypto/jce/cipher/SerpentSpi.java
new file mode 100644
index 000000000..394a0ce0a
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/SerpentSpi.java
@@ -0,0 +1,59 @@
+/* SerpentSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Serpent <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class SerpentSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public SerpentSpi()
+ {
+ super(Registry.SERPENT_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/SquareSpi.java b/gnu/javax/crypto/jce/cipher/SquareSpi.java
new file mode 100644
index 000000000..bb59cd224
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/SquareSpi.java
@@ -0,0 +1,59 @@
+/* SquareSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Square <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class SquareSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public SquareSpi()
+ {
+ super(Registry.SQUARE_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/TripleDESSpi.java b/gnu/javax/crypto/jce/cipher/TripleDESSpi.java
new file mode 100644
index 000000000..cec30f653
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/TripleDESSpi.java
@@ -0,0 +1,59 @@
+/* TripleDESSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Triple-DES <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class TripleDESSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public TripleDESSpi()
+ {
+ super(Registry.TRIPLEDES_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/cipher/TwofishSpi.java b/gnu/javax/crypto/jce/cipher/TwofishSpi.java
new file mode 100644
index 000000000..34f2d95d6
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/TwofishSpi.java
@@ -0,0 +1,59 @@
+/* TwofishSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Twofish <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class TwofishSpi extends CipherAdapter
+{
+
+ // Constructors.
+ // --------------------------------------------------------------------
+
+ public TwofishSpi()
+ {
+ super(Registry.TWOFISH_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java
new file mode 100644
index 000000000..e8d7788e8
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java
@@ -0,0 +1,53 @@
+/* AnubisKeyGeneratorImpl.java -- Anubis key generator.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class AnubisKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public AnubisKeyGeneratorImpl ()
+ {
+ super (Registry.ANUBIS_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..f9725eae0
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java
@@ -0,0 +1,53 @@
+/* AnubisSecretKeyFactoryImpl.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public class AnubisSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+ public AnubisSecretKeyFactoryImpl()
+ {
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java
new file mode 100644
index 000000000..a0e687acd
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java
@@ -0,0 +1,53 @@
+/* BlowfishKeyGeneratorImpl.java -- Blowfish key generator.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class BlowfishKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public BlowfishKeyGeneratorImpl ()
+ {
+ super (Registry.BLOWFISH_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..4b3620bc1
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java
@@ -0,0 +1,53 @@
+/* BlowfishSecretKeyFactoryImpl.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public class BlowfishSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+ public BlowfishSecretKeyFactoryImpl()
+ {
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java
new file mode 100644
index 000000000..18d26e67f
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java
@@ -0,0 +1,53 @@
+/* Cast5KeyGeneratorImpl.java -- CAST-5 key generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class Cast5KeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public Cast5KeyGeneratorImpl ()
+ {
+ super (Registry.CAST5_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java
new file mode 100644
index 000000000..4bd31711e
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java
@@ -0,0 +1,53 @@
+/* Cast5SecretKeyFactoryImpl.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public class Cast5SecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+ public Cast5SecretKeyFactoryImpl()
+ {
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java
new file mode 100644
index 000000000..19c54653a
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java
@@ -0,0 +1,73 @@
+/* DESKeyGeneratorImpl.java -- DES key generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.DES;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+public class DESKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public DESKeyGeneratorImpl ()
+ {
+ super (Registry.DES_CIPHER);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ protected SecretKey engineGenerateKey ()
+ {
+ if (!init)
+ throw new IllegalStateException ("not initialized");
+ byte[] buf = new byte [currentKeySize];
+ do
+ {
+ random.nextBytes (buf);
+ }
+ while (DES.isWeak (buf) || DES.isSemiWeak (buf));
+ DES.adjustParity (buf, 0);
+ return new SecretKeySpec (buf, algorithm);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..e0f1c5860
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java
@@ -0,0 +1,80 @@
+/* DESSecretKeyFactoryImpl.java -- DES key factory.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.DESKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class DESSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+
+ public DESSecretKeyFactoryImpl()
+ {
+ }
+
+ protected SecretKey engineGenerateSecret (KeySpec spec)
+ throws InvalidKeySpecException
+ {
+ if (spec instanceof DESKeySpec)
+ return new SecretKeySpec (((DESKeySpec) spec).getKey(), "DES");
+ return super.engineGenerateSecret (spec);
+ }
+
+ protected KeySpec engineGetKeySpec (SecretKey key, Class spec)
+ throws InvalidKeySpecException
+ {
+ if (spec.isAssignableFrom (DESKeySpec.class))
+ try
+ {
+ return new DESKeySpec (key.getEncoded());
+ }
+ catch (InvalidKeyException ike)
+ {
+ InvalidKeySpecException ikse = new InvalidKeySpecException
+ ("can't create DES key spec");
+ ikse.initCause (ike);
+ throw ikse;
+ }
+ return super.engineGetKeySpec (key, spec);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..15e109940
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java
@@ -0,0 +1,80 @@
+/* DESedeSecretKeyFactoryImpl.java -- DESede key factory.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.DESedeKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class DESedeSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+
+ public DESedeSecretKeyFactoryImpl()
+ {
+ }
+
+ protected SecretKey engineGenerateSecret (KeySpec spec)
+ throws InvalidKeySpecException
+ {
+ if (spec instanceof DESedeKeySpec)
+ return new SecretKeySpec (((DESedeKeySpec) spec).getKey(), "DESede");
+ return super.engineGenerateSecret (spec);
+ }
+
+ protected KeySpec engineGetKeySpec (SecretKey key, Class spec)
+ throws InvalidKeySpecException
+ {
+ if (spec.equals (DESedeKeySpec.class))
+ try
+ {
+ return new DESedeKeySpec (key.getEncoded());
+ }
+ catch (InvalidKeyException ike)
+ {
+ InvalidKeySpecException ikse = new InvalidKeySpecException
+ ("can't create DESede key spec");
+ ikse.initCause (ike);
+ throw ikse;
+ }
+ return super.engineGetKeySpec (key, spec);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java
new file mode 100644
index 000000000..c01391e44
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java
@@ -0,0 +1,52 @@
+/* KhazadKeyGeneratorImpl.java -- Khazad key generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class KhazadKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public KhazadKeyGeneratorImpl ()
+ {
+ super (Registry.KHAZAD_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..c86e01110
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java
@@ -0,0 +1,52 @@
+/* KhazadSecretKeyFactoryImpl.java -- simple byte array-wrapping factory.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public class KhazadSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+ public KhazadSecretKeyFactoryImpl()
+ {
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java
new file mode 100644
index 000000000..535e573ad
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java
@@ -0,0 +1,52 @@
+/* RijndaelKeyGeneratorImpl.java -- Rijndael key generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class RijndaelKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public RijndaelKeyGeneratorImpl ()
+ {
+ super (Registry.RIJNDAEL_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..4aab584a2
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java
@@ -0,0 +1,52 @@
+/* RijndaelSecretKeyFactoryImpl.java -- simple byte array-wrapping factory.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public class RijndaelSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+ public RijndaelSecretKeyFactoryImpl()
+ {
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java
new file mode 100644
index 000000000..72defe1d7
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java
@@ -0,0 +1,87 @@
+/* SecretKeyFactoryImpl.java -- simple byte array-wrapping factory.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public abstract class SecretKeyFactoryImpl extends SecretKeyFactorySpi
+{
+
+ protected SecretKeyFactoryImpl()
+ {
+ }
+
+ protected SecretKey engineGenerateSecret (KeySpec spec)
+ throws InvalidKeySpecException
+ {
+ if (spec instanceof SecretKeySpec)
+ return (SecretKey) spec;
+ throw new InvalidKeySpecException ("unknown key spec: " +
+ spec.getClass().getName());
+ }
+
+ protected KeySpec engineGetKeySpec (SecretKey key, Class spec)
+ throws InvalidKeySpecException
+ {
+ if (spec.equals (SecretKeySpec.class))
+ {
+ if (key instanceof SecretKeySpec)
+ return (KeySpec) key;
+ else
+ return new SecretKeySpec (key.getEncoded(), key.getAlgorithm());
+ }
+ throw new InvalidKeySpecException ("unsupported key spec: " +
+ spec.getName());
+ }
+
+ protected SecretKey engineTranslateKey (SecretKey key)
+ throws InvalidKeyException
+ {
+ if (!"RAW".equals (key.getFormat()))
+ throw new InvalidKeyException ("only raw keys are supported");
+
+ // SecretKeySpec is good enough for our purposes.
+ return new SecretKeySpec (key.getEncoded(), key.getAlgorithm());
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java
new file mode 100644
index 000000000..0a6265573
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java
@@ -0,0 +1,120 @@
+/* SecretKeyGeneratorImpl.java -- symmetric key pair generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.crypto.KeyGeneratorSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+public class SecretKeyGeneratorImpl extends KeyGeneratorSpi
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ protected final int defaultKeySize;
+ protected final List keySizes;
+ protected final String algorithm;
+ protected boolean init;
+ protected int currentKeySize;
+ protected SecureRandom random;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ protected SecretKeyGeneratorImpl (final String algorithm)
+ {
+ this.algorithm = algorithm;
+ IBlockCipher cipher = CipherFactory.getInstance (algorithm);
+ if (cipher == null)
+ throw new IllegalArgumentException ("no such cipher: "+algorithm);
+ defaultKeySize = cipher.defaultKeySize ();
+ keySizes = new LinkedList();
+ for (Iterator it = cipher.keySizes (); it.hasNext (); )
+ {
+ keySizes.add (it.next ());
+ }
+ init = false;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ protected SecretKey engineGenerateKey ()
+ {
+ if (!init)
+ throw new IllegalStateException ("not initialized");
+ byte[] buf = new byte [currentKeySize];
+ random.nextBytes (buf);
+ return new SecretKeySpec (buf, algorithm);
+ }
+
+ protected void engineInit (AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ throw new InvalidAlgorithmParameterException (algorithm +
+ " does not support algorithm paramaters");
+ }
+
+ protected void engineInit (int keySize, SecureRandom random)
+ {
+ keySize >>>= 3; // Use bytes.
+ if (!keySizes.contains (new Integer (keySize)))
+ throw new InvalidParameterException ("unsupported key size: " + keySize);
+ currentKeySize = keySize;
+ this.random = random;
+ init = true;
+ }
+
+ protected void engineInit (SecureRandom random)
+ {
+ engineInit (defaultKeySize << 3, random);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java
new file mode 100644
index 000000000..766860a96
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java
@@ -0,0 +1,52 @@
+/* SerpentKeyGeneratorImpl.java -- Serpent key generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class SerpentKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public SerpentKeyGeneratorImpl ()
+ {
+ super (Registry.SERPENT_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..6e80671fa
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java
@@ -0,0 +1,52 @@
+/* SerpentSecretKeyFactoryImpl.java -- simple byte array-wrapping factory.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public class SerpentSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+ public SerpentSecretKeyFactoryImpl()
+ {
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java
new file mode 100644
index 000000000..4bfbeb668
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java
@@ -0,0 +1,52 @@
+/* SquareKeyGeneratorImpl.java -- Square key generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class SquareKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public SquareKeyGeneratorImpl ()
+ {
+ super (Registry.SQUARE_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..d1d5d5514
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java
@@ -0,0 +1,52 @@
+/* SquareSecretKeyFactoryImpl.java -- simple byte array-wrapping factory.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public class SquareSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+ public SquareSecretKeyFactoryImpl()
+ {
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java
new file mode 100644
index 000000000..eb423fcd1
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java
@@ -0,0 +1,52 @@
+/* TripleDESKeyGeneratorImpl.java -- TripleDES key generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class TripleDESKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public TripleDESKeyGeneratorImpl ()
+ {
+ super (Registry.TRIPLEDES_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java b/gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java
new file mode 100644
index 000000000..ae7e22fee
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java
@@ -0,0 +1,52 @@
+/* TwofishKeyGeneratorImpl.java -- Twofish key generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+
+public class TwofishKeyGeneratorImpl extends SecretKeyGeneratorImpl
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public TwofishKeyGeneratorImpl ()
+ {
+ super (Registry.TWOFISH_CIPHER);
+ }
+}
diff --git a/gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java b/gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java
new file mode 100644
index 000000000..e6ca80b63
--- /dev/null
+++ b/gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java
@@ -0,0 +1,52 @@
+/* TwofishSecretKeyFactoryImpl.java -- simple byte array-wrapping factory.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.crypto.jce.key;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+public class TwofishSecretKeyFactoryImpl extends SecretKeyFactoryImpl
+{
+ public TwofishSecretKeyFactoryImpl()
+ {
+ }
+}
diff --git a/gnu/javax/crypto/jce/keyring/GnuKeyring.java b/gnu/javax/crypto/jce/keyring/GnuKeyring.java
new file mode 100644
index 000000000..d74d386b4
--- /dev/null
+++ b/gnu/javax/crypto/jce/keyring/GnuKeyring.java
@@ -0,0 +1,413 @@
+/* GnuKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.keyring;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.security.Key;
+import java.security.KeyStoreSpi;
+import java.security.KeyStoreException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import javax.crypto.SecretKey;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.keyring.IKeyring;
+import gnu.javax.crypto.keyring.IPrivateKeyring;
+import gnu.javax.crypto.keyring.IPublicKeyring;
+import gnu.javax.crypto.keyring.GnuPrivateKeyring;
+import gnu.javax.crypto.keyring.GnuPublicKeyring;
+import gnu.javax.crypto.keyring.MalformedKeyringException;
+import gnu.javax.crypto.keyring.PrimitiveEntry;
+
+public class GnuKeyring extends KeyStoreSpi
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ private boolean loaded;
+
+ private IKeyring keyring;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public GnuKeyring()
+ {
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public Enumeration engineAliases()
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return new Enumeration()
+ {
+ public boolean hasMoreElements()
+ {
+ return false;
+ }
+
+ public Object nextElement()
+ {
+ throw new NoSuchElementException();
+ }
+ };
+ }
+ return keyring.aliases();
+ }
+
+ public boolean engineContainsAlias(String alias)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return false;
+ }
+ return keyring.containsAlias(alias);
+ }
+
+ public void engineDeleteEntry(String alias)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring != null)
+ {
+ keyring.remove(alias);
+ }
+ }
+
+ public Certificate engineGetCertificate(String alias)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return null;
+ }
+ if (!(keyring instanceof IPublicKeyring))
+ {
+ throw new IllegalStateException("not a public keyring");
+ }
+ return ((IPublicKeyring) keyring).getCertificate(alias);
+ }
+
+ public String engineGetCertificateAlias(Certificate cert)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return null;
+ }
+ if (!(keyring instanceof IPublicKeyring))
+ {
+ throw new IllegalStateException("not a public keyring");
+ }
+ Enumeration aliases = keyring.aliases();
+ while (aliases.hasMoreElements())
+ {
+ String alias = (String) aliases.nextElement();
+ Certificate cert2 = ((IPublicKeyring) keyring).getCertificate(alias);
+ if (cert.equals(cert2))
+ {
+ return alias;
+ }
+ }
+ return null;
+ }
+
+ public void engineSetCertificateEntry(String alias, Certificate cert)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ keyring = new GnuPublicKeyring("HMAC-SHA-1", 20);
+ }
+ if (!(keyring instanceof IPublicKeyring))
+ {
+ throw new IllegalStateException("not a public keyring");
+ }
+ ((IPublicKeyring) keyring).putCertificate(alias, cert);
+ }
+
+ public Certificate[] engineGetCertificateChain(String alias)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return null;
+ }
+ if (!(keyring instanceof IPrivateKeyring))
+ {
+ throw new IllegalStateException("not a private keyring");
+ }
+ return ((IPrivateKeyring) keyring).getCertPath(alias);
+ }
+
+ public Date engineGetCreationDate(String alias)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return null;
+ }
+ List entries = keyring.get(alias);
+ if (entries.size() == 0)
+ {
+ return null;
+ }
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Object o = it.next();
+ if (o instanceof PrimitiveEntry)
+ {
+ return ((PrimitiveEntry) o).getCreationDate();
+ }
+ }
+ return null;
+ }
+
+ public Key engineGetKey(String alias, char[] password)
+ throws UnrecoverableKeyException
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return null;
+ }
+ if (!(keyring instanceof IPrivateKeyring))
+ {
+ throw new IllegalStateException("not a private keyring");
+ }
+ if (password == null)
+ {
+ if (((IPrivateKeyring) keyring).containsPublicKey(alias))
+ {
+ return ((IPrivateKeyring) keyring).getPublicKey(alias);
+ }
+ }
+ if (((IPrivateKeyring) keyring).containsPrivateKey(alias))
+ {
+ return ((IPrivateKeyring) keyring).getPrivateKey(alias, password);
+ }
+ return null;
+ }
+
+ public void engineSetKeyEntry(String alias, Key key, char[] password,
+ Certificate[] chain) throws KeyStoreException
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ keyring = new GnuPrivateKeyring("HMAC-SHA-1", 20, "AES", "OFB", 16);
+ }
+ if (!(keyring instanceof IPrivateKeyring))
+ {
+ throw new IllegalStateException("not a private keyring");
+ }
+ if (key instanceof PublicKey)
+ {
+ ((IPrivateKeyring) keyring).putPublicKey(alias, (PublicKey) key);
+ return;
+ }
+ if (!(key instanceof PrivateKey) && !(key instanceof SecretKey))
+ {
+ throw new KeyStoreException("cannot store keys of type "
+ + key.getClass().getName());
+ }
+ try
+ {
+ CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ ((IPrivateKeyring) keyring).putCertPath(alias, chain);
+ }
+ catch (CertificateException ce)
+ {
+ throw new KeyStoreException(ce.toString());
+ }
+ ((IPrivateKeyring) keyring).putPrivateKey(alias, key, password);
+ }
+
+ public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain)
+ throws KeyStoreException
+ {
+ throw new KeyStoreException("method not supported");
+ }
+
+ public boolean engineIsCertificateEntry(String alias)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return false;
+ }
+ if (!(keyring instanceof IPublicKeyring))
+ {
+ return false;
+ }
+ return ((IPublicKeyring) keyring).containsCertificate(alias);
+ }
+
+ public boolean engineIsKeyEntry(String alias)
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return false;
+ }
+ if (!(keyring instanceof IPrivateKeyring))
+ {
+ return false;
+ }
+ return ((IPrivateKeyring) keyring).containsPublicKey(alias)
+ || ((IPrivateKeyring) keyring).containsPrivateKey(alias);
+ }
+
+ public void engineLoad(InputStream in, char[] password) throws IOException
+ {
+ if (in != null)
+ {
+ if (!in.markSupported())
+ {
+ in = new BufferedInputStream(in);
+ }
+ in.mark(5);
+ for (int i = 0; i < 4; i++)
+ if (in.read() != Registry.GKR_MAGIC[i])
+ throw new MalformedKeyringException("incorrect magic");
+ int usage = in.read();
+ in.reset();
+ HashMap attr = new HashMap();
+ attr.put(IKeyring.KEYRING_DATA_IN, in);
+ attr.put(IKeyring.KEYRING_PASSWORD, password);
+ switch (usage)
+ {
+ case GnuPublicKeyring.USAGE:
+ keyring = new GnuPublicKeyring();
+ break;
+ case GnuPrivateKeyring.USAGE:
+ keyring = new GnuPrivateKeyring();
+ break;
+ default:
+ throw new MalformedKeyringException("unsupported ring usage: "
+ + Integer.toBinaryString(usage));
+ }
+ keyring.load(attr);
+ }
+ loaded = true;
+ }
+
+ public void engineStore(OutputStream out, char[] password) throws IOException
+ {
+ if (!loaded || keyring == null)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ HashMap attr = new HashMap();
+ attr.put(IKeyring.KEYRING_DATA_OUT, out);
+ attr.put(IKeyring.KEYRING_PASSWORD, password);
+ keyring.store(attr);
+ }
+
+ public int engineSize()
+ {
+ if (!loaded)
+ {
+ throw new IllegalStateException ("not loaded");
+ }
+ if (keyring == null)
+ {
+ return 0;
+ }
+ return keyring.size();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacHavalSpi.java b/gnu/javax/crypto/jce/mac/HMacHavalSpi.java
new file mode 100644
index 000000000..df1319cbf
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacHavalSpi.java
@@ -0,0 +1,67 @@
+/* HMacHavalSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HMAC-HAVAL <i>Service Provider Interface</i>
+ * (<b>SPI</b>) Adapter.
+ *
+ * @version Revision: $
+ */
+public class HMacHavalSpi extends MacAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public HMacHavalSpi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.HAVAL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacMD2Spi.java b/gnu/javax/crypto/jce/mac/HMacMD2Spi.java
new file mode 100644
index 000000000..935f5e5a3
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacMD2Spi.java
@@ -0,0 +1,59 @@
+/* HMacMD2Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HMAC-MD2 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacMD2Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public HMacMD2Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.MD2_HASH);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacMD4Spi.java b/gnu/javax/crypto/jce/mac/HMacMD4Spi.java
new file mode 100644
index 000000000..49507a6dd
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacMD4Spi.java
@@ -0,0 +1,59 @@
+/* HMacMD4Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HMAC-MD4 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacMD4Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public HMacMD4Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.MD4_HASH);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacMD5Spi.java b/gnu/javax/crypto/jce/mac/HMacMD5Spi.java
new file mode 100644
index 000000000..3bc0fea6b
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacMD5Spi.java
@@ -0,0 +1,59 @@
+/* HMacMD5Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HMAC-MD5 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacMD5Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public HMacMD5Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.MD5_HASH);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java b/gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java
new file mode 100644
index 000000000..6a57e6c9d
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java
@@ -0,0 +1,59 @@
+/* HMacRipeMD128Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HMAC-RIPEMD-128 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacRipeMD128Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public HMacRipeMD128Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.RIPEMD128_HASH);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java b/gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java
new file mode 100644
index 000000000..a47e1a5c7
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java
@@ -0,0 +1,59 @@
+/* HMacRipeMD160Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HMAC-RIPEMD-160 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacRipeMD160Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public HMacRipeMD160Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.RIPEMD160_HASH);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacSHA160Spi.java b/gnu/javax/crypto/jce/mac/HMacSHA160Spi.java
new file mode 100644
index 000000000..e251dc373
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacSHA160Spi.java
@@ -0,0 +1,59 @@
+/* HMacSHA160Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HMAC-SHA-160 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacSHA160Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public HMacSHA160Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.SHA160_HASH);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacSHA256Spi.java b/gnu/javax/crypto/jce/mac/HMacSHA256Spi.java
new file mode 100644
index 000000000..7caa26041
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacSHA256Spi.java
@@ -0,0 +1,67 @@
+/* HMacSHA256Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the HMAC-SHA-256 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacSHA256Spi extends MacAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -----------------------------------------------------------------------
+
+ public HMacSHA256Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.SHA256_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacSHA384Spi.java b/gnu/javax/crypto/jce/mac/HMacSHA384Spi.java
new file mode 100644
index 000000000..d3e454b54
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacSHA384Spi.java
@@ -0,0 +1,67 @@
+/* HMacSHA384Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the HMAC-SHA-384 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class HMacSHA384Spi extends MacAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -----------------------------------------------------------------------
+
+ public HMacSHA384Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.SHA384_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacSHA512Spi.java b/gnu/javax/crypto/jce/mac/HMacSHA512Spi.java
new file mode 100644
index 000000000..f02267c84
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacSHA512Spi.java
@@ -0,0 +1,67 @@
+/* HMacSHA512Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the HMAC-SHA-512 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class HMacSHA512Spi extends MacAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -----------------------------------------------------------------------
+
+ public HMacSHA512Spi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.SHA512_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacTigerSpi.java b/gnu/javax/crypto/jce/mac/HMacTigerSpi.java
new file mode 100644
index 000000000..e4eb26ca9
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacTigerSpi.java
@@ -0,0 +1,59 @@
+/* HMacTigerSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Tiger <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacTigerSpi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public HMacTigerSpi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.TIGER_HASH);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java b/gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java
new file mode 100644
index 000000000..8e2ef6d2f
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java
@@ -0,0 +1,59 @@
+/* HMacWhirlpoolSpi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HMAC-Whirlpool <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class HMacWhirlpoolSpi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public HMacWhirlpoolSpi()
+ {
+ super(Registry.HMAC_NAME_PREFIX + Registry.WHIRLPOOL_HASH);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/MacAdapter.java b/gnu/javax/crypto/jce/mac/MacAdapter.java
new file mode 100644
index 000000000..86cc29c30
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/MacAdapter.java
@@ -0,0 +1,142 @@
+/* MacAdapter.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.HashMap;
+import java.util.Map;
+import javax.crypto.MacSpi;
+
+/**
+ * <p>The implementation of a generic {@link javax.crypto.Mac} adapter class
+ * to wrap GNU Crypto MAC instances.</p>
+ *
+ * <p>This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
+ * the {@link javax.crypto.Mac} class, which provides the functionality of a
+ * message authentication code algorithm, such as the <i>Hashed Message
+ * Authentication Code</i> (<b>HMAC</b>) algorithms.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+class MacAdapter extends MacSpi implements Cloneable
+{
+
+ // Constants and variables
+ // -----------------------------------------------------------------------
+
+ /** Our MAC instance. */
+ protected IMac mac;
+
+ /** Our MAC attributes. */
+ protected Map attributes;
+
+ // Constructor(s)
+ // -----------------------------------------------------------------------
+
+ /**
+ * <p>Creates a new Mac instance for the given name.</p>
+ *
+ * @param name The name of the mac to create.
+ */
+ protected MacAdapter(String name)
+ {
+ mac = MacFactory.getInstance(name);
+ attributes = new HashMap();
+ }
+
+ // Class methods
+ // -----------------------------------------------------------------------
+
+ // Instance methods
+ // -----------------------------------------------------------------------
+
+ // Cloneable interface implementation ------------------------------------
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+
+ // Instance methods implementing javax.crypto.MacSpi ---------------------
+
+ protected byte[] engineDoFinal()
+ {
+ byte[] result = mac.digest();
+ engineReset();
+ return result;
+ }
+
+ protected int engineGetMacLength()
+ {
+ return mac.macSize();
+ }
+
+ protected void engineInit(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ if (!key.getFormat().equalsIgnoreCase("RAW"))
+ {
+ throw new InvalidKeyException("unknown key format " + key.getFormat());
+ }
+ attributes.put(IMac.MAC_KEY_MATERIAL, key.getEncoded());
+ mac.reset();
+ mac.init(attributes);
+ }
+
+ protected void engineReset()
+ {
+ mac.reset();
+ }
+
+ protected void engineUpdate(byte b)
+ {
+ mac.update(b);
+ }
+
+ protected void engineUpdate(byte[] in, int off, int len)
+ {
+ mac.update(in, off, len);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacAnubisImpl.java b/gnu/javax/crypto/jce/mac/OMacAnubisImpl.java
new file mode 100644
index 000000000..4bfda4fd6
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacAnubisImpl.java
@@ -0,0 +1,53 @@
+/* OMacAnubisImpl.java -- OMAC-ANUBIS adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacAnubisImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacAnubisImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.ANUBIS_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java b/gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java
new file mode 100644
index 000000000..8d168e57b
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java
@@ -0,0 +1,53 @@
+/* OMacBlowfishImpl.java -- OMAC-BLOWFISH adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacBlowfishImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacBlowfishImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.BLOWFISH_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacCast5Impl.java b/gnu/javax/crypto/jce/mac/OMacCast5Impl.java
new file mode 100644
index 000000000..3385d116b
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacCast5Impl.java
@@ -0,0 +1,53 @@
+/* OMacCast5Impl.java -- OMAC-CAST5 adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacCast5Impl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacCast5Impl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.CAST5_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacDESImpl.java b/gnu/javax/crypto/jce/mac/OMacDESImpl.java
new file mode 100644
index 000000000..3fb23bdef
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacDESImpl.java
@@ -0,0 +1,53 @@
+/* OMacDESImpl.java -- OMAC-DES adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacDESImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacDESImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.DES_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacImpl.java b/gnu/javax/crypto/jce/mac/OMacImpl.java
new file mode 100644
index 000000000..f91902ae5
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacImpl.java
@@ -0,0 +1,137 @@
+/* OMacImpl.java -- OMAC adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+import javax.crypto.MacSpi;
+
+public abstract class OMacImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ protected OMacImpl(String name)
+ {
+ super(Registry.OMAC_PREFIX + name);
+ }
+
+ // Inner classes.
+ // -------------------------------------------------------------------------
+
+ public class Anubis extends OMacImpl
+ {
+ public Anubis()
+ {
+ super(Registry.ANUBIS_CIPHER);
+ }
+ }
+
+ public class Blowfish extends OMacImpl
+ {
+ public Blowfish()
+ {
+ super(Registry.BLOWFISH_CIPHER);
+ }
+ }
+
+ public class Cast5 extends OMacImpl
+ {
+ public Cast5()
+ {
+ super(Registry.CAST5_CIPHER);
+ }
+ }
+
+ public class DES extends OMacImpl
+ {
+ public DES()
+ {
+ super(Registry.DES_CIPHER);
+ }
+ }
+
+ public class Khazad extends OMacImpl
+ {
+ public Khazad()
+ {
+ super(Registry.KHAZAD_CIPHER);
+ }
+ }
+
+ public class Rijndael extends OMacImpl
+ {
+ public Rijndael()
+ {
+ super(Registry.RIJNDAEL_CIPHER);
+ }
+ }
+
+ public class Serpent extends OMacImpl
+ {
+ public Serpent()
+ {
+ super(Registry.SERPENT_CIPHER);
+ }
+ }
+
+ public class Square extends OMacImpl
+ {
+ public Square()
+ {
+ super(Registry.SQUARE_CIPHER);
+ }
+ }
+
+ public class TripleDES extends OMacImpl
+ {
+ public TripleDES()
+ {
+ super(Registry.TRIPLEDES_CIPHER);
+ }
+ }
+
+ public class Twofish extends OMacImpl
+ {
+ public Twofish()
+ {
+ super(Registry.TWOFISH_CIPHER);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacKhazadImpl.java b/gnu/javax/crypto/jce/mac/OMacKhazadImpl.java
new file mode 100644
index 000000000..82c047c25
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacKhazadImpl.java
@@ -0,0 +1,53 @@
+/* OMacKhazadImpl.java -- OMAC-KHAZAD adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacKhazadImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacKhazadImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.KHAZAD_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java b/gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java
new file mode 100644
index 000000000..47d3f6aae
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java
@@ -0,0 +1,53 @@
+/* OMacRijndaelImpl.java -- OMAC-RIJNDAEL adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacRijndaelImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacRijndaelImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.RIJNDAEL_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacSerpentImpl.java b/gnu/javax/crypto/jce/mac/OMacSerpentImpl.java
new file mode 100644
index 000000000..bec2c1f5c
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacSerpentImpl.java
@@ -0,0 +1,53 @@
+/* OMacSerpentImpl.java -- OMAC-SERPENT adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacSerpentImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacSerpentImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.SERPENT_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacSquareImpl.java b/gnu/javax/crypto/jce/mac/OMacSquareImpl.java
new file mode 100644
index 000000000..0442b7caf
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacSquareImpl.java
@@ -0,0 +1,53 @@
+/* OMacSquareImpl.java -- OMAC-SQUARE adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacSquareImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacSquareImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.SQUARE_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java b/gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java
new file mode 100644
index 000000000..0defdd1fd
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java
@@ -0,0 +1,53 @@
+/* OMacTripleDESImpl.java -- OMAC-TRIPLEDES adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacTripleDESImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacTripleDESImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.TRIPLEDES_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/OMacTwofishImpl.java b/gnu/javax/crypto/jce/mac/OMacTwofishImpl.java
new file mode 100644
index 000000000..a12f9f30e
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/OMacTwofishImpl.java
@@ -0,0 +1,53 @@
+/* OMacTwofishImpl.java -- OMAC-TWOFISH adapter.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacTwofishImpl extends MacAdapter
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public OMacTwofishImpl()
+ {
+ super(Registry.OMAC_PREFIX + Registry.TWOFISH_CIPHER);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/TMMH16Spi.java b/gnu/javax/crypto/jce/mac/TMMH16Spi.java
new file mode 100644
index 000000000..0a4222237
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/TMMH16Spi.java
@@ -0,0 +1,91 @@
+/* TMMH16Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.mac.TMMH16;
+import gnu.javax.crypto.jce.spec.TMMHParameterSpec;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * The implementation of the TMMH16 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class TMMH16Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public TMMH16Spi()
+ {
+ super(Registry.TMMH16);
+ }
+
+ // Instance methods overriding MacAdapter.
+ // -----------------------------------------------------------------------
+
+ protected void engineInit(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ if (!(params instanceof TMMHParameterSpec))
+ {
+ throw new InvalidAlgorithmParameterException();
+ }
+ TMMHParameterSpec spec = (TMMHParameterSpec) params;
+ attributes.put(TMMH16.TAG_LENGTH, spec.getTagLength());
+ attributes.put(TMMH16.KEYSTREAM, spec.getKeystream());
+ attributes.put(TMMH16.PREFIX, spec.getPrefix());
+ try
+ {
+ mac.reset();
+ mac.init(attributes);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new InvalidAlgorithmParameterException(iae.getMessage());
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/UHash32Spi.java b/gnu/javax/crypto/jce/mac/UHash32Spi.java
new file mode 100644
index 000000000..a24b8e59c
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/UHash32Spi.java
@@ -0,0 +1,59 @@
+/* UHash32Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the UHash-32 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class UHash32Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public UHash32Spi()
+ {
+ super(Registry.UHASH32);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/mac/UMac32Spi.java b/gnu/javax/crypto/jce/mac/UMac32Spi.java
new file mode 100644
index 000000000..52c58f36f
--- /dev/null
+++ b/gnu/javax/crypto/jce/mac/UMac32Spi.java
@@ -0,0 +1,91 @@
+/* UMac32Spi.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.mac.UMac32;
+import gnu.javax.crypto.jce.spec.UMac32ParameterSpec;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * The implementation of the UMAC-32 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class UMac32Spi extends MacAdapter
+{
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ public UMac32Spi()
+ {
+ super(Registry.UMAC32);
+ }
+
+ // Instance methods overriding MacAdapter.
+ // -----------------------------------------------------------------------
+
+ protected void engineInit(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ if (!(params instanceof UMac32ParameterSpec))
+ {
+ throw new InvalidAlgorithmParameterException();
+ }
+ if (params != null)
+ {
+ attributes.put(UMac32.NONCE_MATERIAL,
+ ((UMac32ParameterSpec) params).getNonce());
+ }
+ try
+ {
+ super.engineInit(key, null);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new InvalidAlgorithmParameterException(iae.getMessage());
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/params/BlockCipherParameters.java b/gnu/javax/crypto/jce/params/BlockCipherParameters.java
new file mode 100644
index 000000000..bae7cbf88
--- /dev/null
+++ b/gnu/javax/crypto/jce/params/BlockCipherParameters.java
@@ -0,0 +1,209 @@
+/* BlockCipherParameters.java --
+ Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.params;
+
+import gnu.javax.crypto.jce.spec.BlockCipherParameterSpec;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import java.security.AlgorithmParametersSpi;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+/**
+ * An implementation of algorithm parameters for the GNU Crypto block
+ * ciphers. This encompasses the cipher's block size, its key size, and
+ * an optional initialization vector (IV).
+ */
+public class BlockCipherParameters extends AlgorithmParametersSpi
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ /**
+ * The underlying block cipher specification.
+ */
+ protected BlockCipherParameterSpec cipherSpec;
+
+ private static final String DEFAULT_FORMAT = "ASN.1";
+
+ // Instance methods implementing AlgorithmParametersSpi.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Return these parameters encoded in ASN.1 (DER).
+ *
+ * <p>For GNU Crypto block ciphers we will define these parameters as
+ *
+ * <blockquote>
+ * <pre>BlockCipherParameters ::= SEQUENCE {
+ * blockSize INTEGER,
+ * keySize INTEGER,
+ * initializationVector OCTET STRING OPTIONAL }</pre>
+ * </blockquote>
+ *
+ * @return The parameters, encoded an an ASN.1 DER sequence.
+ * @throws java.io.IOException If encoding these parameters fails.
+ */
+ protected byte[] engineGetEncoded() throws IOException
+ {
+ return engineGetEncoded(DEFAULT_FORMAT);
+ }
+
+ protected byte[] engineGetEncoded(String format) throws IOException
+ {
+ if (!format.equalsIgnoreCase(DEFAULT_FORMAT)
+ && !format.equalsIgnoreCase("asn1"))
+ {
+ throw new IOException("unknown format \"" + format + "\"");
+ }
+ // This is probably a bad idea.
+ /*
+ int len = 12 + ((cipherSpec.getIV() != null)
+ ? cipherSpec.getIV().length + 2 : 0);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ out.write(0x30);
+ out.write(len);
+ out.write(0x02);
+ out.write(4);
+ out.write(cipherSpec.getBlockSize() >>> 24 & 0xff);
+ out.write(cipherSpec.getBlockSize() >>> 16 & 0xff);
+ out.write(cipherSpec.getBlockSize() >>> 8 & 0xff);
+ out.write(cipherSpec.getBlockSize() & 0xff);
+ out.write(0x02);
+ out.write(4);
+ out.write(cipherSpec.getKeySize() >>> 24 & 0xff);
+ out.write(cipherSpec.getKeySize() >>> 16 & 0xff);
+ out.write(cipherSpec.getKeySize() >>> 8 & 0xff);
+ out.write(cipherSpec.getKeySize() & 0xff);
+ if (cipherSpec.getIV() != null) {
+ out.write(0x04);
+ len = cipherSpec.getIV().length;
+ out.write(len & 0xff);
+ out.write(cipherSpec.getIV());
+ }
+ out.write(0); out.write(0);
+ return out.toByteArray();*/
+ DERWriter writer = new DERWriter();
+ return writer.joinarrays(
+ writer.writeBigInteger(BigInteger.valueOf(cipherSpec.getBlockSize())),
+ writer.writeBigInteger(BigInteger.valueOf(cipherSpec.getKeySize())),
+ (cipherSpec.getIV() != null) ? writer.writeBigInteger(new BigInteger(
+ cipherSpec.getIV()))
+ : new byte[0]);
+ }
+
+ protected void engineInit(AlgorithmParameterSpec spec)
+ throws InvalidParameterSpecException
+ {
+ if (spec instanceof BlockCipherParameterSpec)
+ {
+ cipherSpec = (BlockCipherParameterSpec) spec;
+ }
+ else
+ {
+ throw new InvalidParameterSpecException();
+ }
+ }
+
+ protected void engineInit(byte[] encoded, String format) throws IOException
+ {
+ if (!format.equalsIgnoreCase(DEFAULT_FORMAT)
+ && !format.equalsIgnoreCase("ASN1"))
+ {
+ throw new IOException("invalid format: only accepts ASN.1");
+ }
+ engineInit(encoded);
+ }
+
+ protected void engineInit(byte[] encoded) throws IOException
+ {
+ // This is probably an equally bad idea.
+ /*if (encoded[0] != 0x30) {
+ throw new IOException("malformed ASN.1 sequence");
+ }
+ if (encoded[2] != 0x02 || encoded[3] != 4) {
+ throw new IOException("malformed ASN.1 sequence");
+ }
+ int blockSize = encoded[4] << 24 | encoded[5] << 16
+ | encoded[6] << 8 | encoded[7];
+ if (encoded[8] != 0x02 || encoded[9] != 4) {
+ throw new IOException("malformed ASN.1 sequence");
+ }
+ int keySize = encoded[10] << 24 | encoded[11] << 16
+ | encoded[12] << 8 | encoded[13];
+ if (encoded[14] == 0x04) {
+ int len = encoded[15] & 0xff;
+ byte[] iv = new byte[len];
+ System.arraycopy(encoded, 16, iv, 0, len);
+ cipherSpec = new BlockCipherParameterSpec(iv, blockSize, keySize);
+ } else if (encoded[14] == 0) {
+ cipherSpec = new BlockCipherParameterSpec(blockSize, keySize);
+ } else {
+ throw new IOException("malformed ASN.1 sequence");
+ }*/
+ DERReader reader = new DERReader(encoded);
+ int bs = reader.getBigInteger().intValue();
+ int ks = reader.getBigInteger().intValue();
+ byte[] iv = null;
+ if (reader.hasMorePrimitives())
+ {
+ iv = reader.getBigInteger().toByteArray();
+ }
+ cipherSpec = new BlockCipherParameterSpec(iv, bs, ks);
+ System.out.println(cipherSpec);
+ }
+
+ protected AlgorithmParameterSpec engineGetParameterSpec(Class c)
+ throws InvalidParameterSpecException
+ {
+ if (c.isInstance(cipherSpec))
+ {
+ return cipherSpec;
+ }
+ throw new InvalidParameterSpecException();
+ }
+
+ protected String engineToString()
+ {
+ return cipherSpec.toString();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/params/DEREncodingException.java b/gnu/javax/crypto/jce/params/DEREncodingException.java
new file mode 100644
index 000000000..ddfa6e1de
--- /dev/null
+++ b/gnu/javax/crypto/jce/params/DEREncodingException.java
@@ -0,0 +1,53 @@
+/* DEREncodingException.java --
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.params;
+
+class DEREncodingException extends java.io.IOException
+{
+
+ public DEREncodingException()
+ {
+ super();
+ }
+
+ public DEREncodingException(String msg)
+ {
+ super(msg);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/params/DERReader.java b/gnu/javax/crypto/jce/params/DERReader.java
new file mode 100644
index 000000000..f61423255
--- /dev/null
+++ b/gnu/javax/crypto/jce/params/DERReader.java
@@ -0,0 +1,160 @@
+/* DERReader.java --
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.params;
+
+import java.math.BigInteger;
+
+class DERReader
+{
+ byte source[];
+
+ int pos;
+
+ static final int UNIVERSAL = 1;
+
+ static final int APPLICATION = 2;
+
+ static final int CONTEXT_SPECIFIC = 3;
+
+ static final int PRIVATE = 4;
+
+ public DERReader()
+ {
+ source = null;
+ pos = 0;
+ }
+
+ public DERReader(byte source[])
+ {
+ init(source);
+ }
+
+ public void init(String source)
+ {
+ init(source.getBytes());
+ }
+
+ public void init(byte source[])
+ {
+ this.source = source;
+ pos = 0;
+ }
+
+ public boolean hasMorePrimitives()
+ {
+ return pos < source.length;
+ }
+
+ public BigInteger getBigInteger() throws DEREncodingException
+ {
+ return new BigInteger(getPrimitive());
+ }
+
+ //Reads Primitive, definite-length method
+ private byte[] getPrimitive() throws DEREncodingException
+ {
+ int tmp = pos;
+
+ //Read Identifier
+ byte identifier = source[tmp++];
+ if ((0x20 & identifier) != 0)
+ throw new DEREncodingException();
+ int type = translateLeadIdentifierByte(identifier);
+ //System.out.println("Type: " + type);
+
+ //get tag
+ int tag = (0x1f & identifier);
+ //if( tag == 0x1f)
+ // tag = getIdentifier(tmp);
+ //System.out.println("Tag: " + tag);
+
+ //get length
+ byte len = source[tmp]; //may be length of length parameter
+ long length = 0x7f & len;
+ int i;
+ if ((0x80 & len) != 0)
+ {
+ //System.out.println("Extra Long Length");
+ len &= 0x7f;
+ //System.out.println("Length of Length: " + len);
+ //get length here
+ length = 0;
+ for (i = 0; i < len; i++)
+ {
+ tmp++;
+ length <<= 8;
+ length += (source[tmp] < 0) ? (256 + source[tmp]) : source[tmp];
+ //System.out.println("Length of Length: " + length);
+ }
+ tmp++;
+ }
+ else
+ tmp++;
+
+ /*System.out.println("Position: " + tmp);
+ System.out.println("Length: " + length);
+ for( i = 0; i < 10; i++)
+ System.out.print(source[tmp + i] + " ");
+ System.out.println();*/
+
+ byte tmpb[] = new byte[(int) length];
+ System.arraycopy(source, tmp, tmpb, 0, (int) length);
+ pos = (int) (tmp + length);
+ return tmpb;
+ }
+
+ private int translateLeadIdentifierByte(byte b)
+ {
+ if ((0x3f & b) == b)
+ return UNIVERSAL;
+ else if ((0x7f & b) == b)
+ return APPLICATION;
+ else if ((0xbf & b) == b)
+ return CONTEXT_SPECIFIC;
+ else
+ return PRIVATE;
+ }
+
+ private int getIdentifier(int tpos)
+ {
+ while ((0x80 & source[tpos]) != 0)
+ tpos++;
+ return tpos;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/params/DERWriter.java b/gnu/javax/crypto/jce/params/DERWriter.java
new file mode 100644
index 000000000..876c2cd6c
--- /dev/null
+++ b/gnu/javax/crypto/jce/params/DERWriter.java
@@ -0,0 +1,154 @@
+/* DERWriter.java --
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.params;
+
+import java.math.BigInteger;
+
+class DERWriter
+{
+ static final int UNIVERSAL = 1;
+
+ static final int APPLICATION = 2;
+
+ static final int CONTEXT_SPECIFIC = 3;
+
+ static final int PRIVATE = 4;
+
+ public DERWriter()
+ {
+ }
+
+ public byte[] writeBigInteger(BigInteger i)
+ {
+ return writePrimitive(0x02, UNIVERSAL,
+ (int) Math.ceil((double) i.bitLength() / 8),
+ i.toByteArray());
+ }
+
+ private byte[] writePrimitive(int identifier, int identifierencoding,
+ int length, byte contents[])
+ {
+ return joinarrays(generateIdentifier(identifier, identifierencoding),
+ generateLength(length), contents);
+ }
+
+ public byte[] joinarrays(byte a[], byte b[])
+ {
+ byte d[] = new byte[a.length + b.length];
+ System.arraycopy(a, 0, d, 0, a.length);
+ System.arraycopy(b, 0, d, a.length, b.length);
+ return d;
+ }
+
+ public byte[] joinarrays(byte a[], byte b[], byte c[])
+ {
+ byte d[] = new byte[a.length + b.length + c.length];
+ System.arraycopy(a, 0, d, 0, a.length);
+ System.arraycopy(b, 0, d, a.length, b.length);
+ System.arraycopy(c, 0, d, a.length + b.length, c.length);
+ return d;
+ }
+
+ private byte[] generateIdentifier(int identifier, int identifierencoding)
+ {
+ byte b[];
+ if (identifier > 31)
+ {
+ int count = (int) (Math.log(identifier) / Math.log(256));
+ b = new byte[count + 1];
+ b[0] = (byte) (translateLeadIdentifierByte(identifierencoding) | 0x1f);
+ int i;
+ for (i = 1; i < (count + 1); i++)
+ {
+ b[i] = (byte) (0x7f & (identifier >> (7 * (count - i))));
+ b[i] |= 0x80;
+ }
+ b[i - 1] ^= 0x80;
+ //System.out.println("Identifier1: " + b[0]);
+ return b;
+ }
+ else
+ {
+ b = new byte[1];
+ b[0] = (byte) ((translateLeadIdentifierByte(identifierencoding) | (byte) (identifier & 0x1f)) & 0xdf);
+ //System.out.println("Identifier2: " + b[0]);
+ return b;
+ }
+ }
+
+ private byte translateLeadIdentifierByte(int b)
+ {
+ if (b == UNIVERSAL)
+ return (byte) 0x3f;
+ else if (b == APPLICATION)
+ return (byte) 0x7f;
+ else if (b == CONTEXT_SPECIFIC)
+ return (byte) 0xbf;
+ else
+ return (byte) 0xC0;
+ }
+
+ private byte[] generateLength(int length)
+ {
+ byte b[];
+ if (length > 127)
+ {
+ int count = (int) Math.ceil(Math.log(length) / Math.log(256));
+ //System.out.println("Length byte count: " + count);
+ b = new byte[count + 1];
+ b[0] = (byte) ((count & 0x7f) | 0x80);
+ for (int i = 1; i < (count + 1); i++)
+ {
+ b[i] = (byte) (length >>> (8 * (count - i)));
+ //System.out.println("Length1 byte1: " + (length >>> (8 * ( count - i) )));
+ //System.out.println("Length1 byte2: " + b[i]);
+ }
+
+ //System.out.println("Length1: " + length);
+ return b;
+ }
+ else
+ {
+ b = new byte[1];
+ b[0] = (byte) (length & 0x7f);
+ //System.out.println("Length2: " + length);
+ return b;
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java b/gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java
new file mode 100644
index 000000000..0c071561b
--- /dev/null
+++ b/gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java
@@ -0,0 +1,120 @@
+/* ARCFourRandomSpi.java --
+ Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.prng;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.prng.ARCFour;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.prng.PRNGFactory;
+
+import java.security.SecureRandomSpi;
+import java.util.HashMap;
+
+/**
+ * Implementation of the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the ARCFOUR keystream generator.
+ */
+public class ARCFourRandomSpi extends SecureRandomSpi
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying prng instance. */
+ private IRandom adaptee;
+
+ /** Have we been initialized? */
+ private boolean virgin;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Default 0-arguments constructor.
+ */
+ public ARCFourRandomSpi()
+ {
+ super();
+ adaptee = PRNGFactory.getInstance(Registry.ARCFOUR_PRNG);
+ virgin = true;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.SecureRandomSpi interface implementation ------------------
+
+ public byte[] engineGenerateSeed(int numBytes)
+ {
+ if (numBytes < 1)
+ {
+ return new byte[0];
+ }
+ byte[] result = new byte[numBytes];
+ this.engineNextBytes(result);
+ return result;
+ }
+
+ public void engineNextBytes(byte[] bytes)
+ {
+ if (virgin)
+ {
+ this.engineSetSeed(new byte[0]);
+ }
+ try
+ {
+ adaptee.nextBytes(bytes, 0, bytes.length);
+ }
+ catch (LimitReachedException ignored)
+ {
+ }
+ }
+
+ public void engineSetSeed(byte[] seed)
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(ARCFour.ARCFOUR_KEY_MATERIAL, seed);
+ adaptee.init(attributes);
+ virgin = false;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/prng/CSPRNGSpi.java b/gnu/javax/crypto/jce/prng/CSPRNGSpi.java
new file mode 100644
index 000000000..c0aa015b0
--- /dev/null
+++ b/gnu/javax/crypto/jce/prng/CSPRNGSpi.java
@@ -0,0 +1,114 @@
+/* CSPRNGSpi.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.prng;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.prng.CSPRNG;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+import java.net.MalformedURLException;
+import java.security.SecureRandomSpi;
+
+/**
+ * The implementation of the continuously-seeded SecureRandom
+ * <i>Service Provider Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class CSPRNGSpi extends SecureRandomSpi
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private final IRandom adaptee;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public CSPRNGSpi() throws ClassNotFoundException, MalformedURLException,
+ NumberFormatException
+ {
+ super();
+
+ adaptee = CSPRNG.getSystemInstance();
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ protected byte[] engineGenerateSeed(final int count)
+ {
+ if (count < 0)
+ {
+ throw new IllegalArgumentException("count must be nonnegative");
+ }
+ byte[] buf = new byte[count];
+ if (count == 0)
+ {
+ return buf;
+ }
+ engineNextBytes(buf);
+ return buf;
+ }
+
+ protected void engineNextBytes(final byte[] buffer)
+ {
+ if (buffer == null)
+ {
+ throw new NullPointerException();
+ }
+ try
+ {
+ adaptee.nextBytes(buffer, 0, buffer.length);
+ }
+ catch (LimitReachedException lre)
+ {
+ throw new RuntimeException("random-number generator has been exhausted");
+ }
+ }
+
+ protected void engineSetSeed(final byte[] seed)
+ {
+ if (seed == null)
+ {
+ throw new NullPointerException();
+ }
+ adaptee.addRandomBytes(seed, 0, seed.length);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/prng/FortunaImpl.java b/gnu/javax/crypto/jce/prng/FortunaImpl.java
new file mode 100644
index 000000000..7006bbbad
--- /dev/null
+++ b/gnu/javax/crypto/jce/prng/FortunaImpl.java
@@ -0,0 +1,85 @@
+/* FortunaImpl.java -- Fortuna SecureRandom adapter.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.prng;
+
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.prng.Fortuna;
+import java.security.SecureRandomSpi;
+import java.util.Collections;
+
+public final class FortunaImpl extends SecureRandomSpi
+{
+ private final Fortuna adaptee;
+
+ public FortunaImpl ()
+ {
+ adaptee = new Fortuna ();
+ adaptee.init (Collections.singletonMap (Fortuna.SEED, new byte[0]));
+ }
+
+ protected void engineSetSeed (byte[] seed)
+ {
+ synchronized (adaptee)
+ {
+ adaptee.addRandomBytes (seed);
+ }
+ }
+
+ protected void engineNextBytes(byte[] buffer)
+ {
+ synchronized (adaptee)
+ {
+ try
+ {
+ adaptee.nextBytes (buffer);
+ }
+ catch (LimitReachedException shouldNotHappen)
+ {
+ throw new Error (shouldNotHappen);
+ }
+ }
+ }
+
+ protected byte[] engineGenerateSeed (int numbytes)
+ {
+ byte[] seed = new byte[numbytes];
+ engineNextBytes (seed);
+ return seed;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/prng/ICMRandomSpi.java b/gnu/javax/crypto/jce/prng/ICMRandomSpi.java
new file mode 100644
index 000000000..d04b782f9
--- /dev/null
+++ b/gnu/javax/crypto/jce/prng/ICMRandomSpi.java
@@ -0,0 +1,260 @@
+/* ICMRandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.prng;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.prng.ICMGenerator;
+import gnu.java.security.prng.LimitReachedException;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.SecureRandomSpi;
+import java.util.HashMap;
+import java.util.Random;
+
+/**
+ * <p>An <em>Adapter</em> class around {@link ICMGenerator} to allow using this
+ * algorithm as a JCE {@link java.security.SecureRandom}.</p>
+ */
+public class ICMRandomSpi extends SecureRandomSpi
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "ICMRandomSpi";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 0;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Class-wide prng to generate random material for the underlying prng.*/
+ private static final ICMGenerator prng; // blank final
+ static
+ {
+ prng = new ICMGenerator();
+ resetLocalPRNG();
+ }
+
+ // error messages
+ private static final String MSG = "Exception while setting up an "
+ + Registry.ICM_PRNG + " SPI: ";
+
+ private static final String RETRY = "Retry...";
+
+ private static final String LIMIT_REACHED_MSG = "Limit reached: ";
+
+ private static final String RESEED = "Re-seed...";
+
+ /** Our underlying prng instance. */
+ private ICMGenerator adaptee = new ICMGenerator();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ private static void resetLocalPRNG()
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(">>> resetLocalPRNG()");
+ HashMap attributes = new HashMap();
+ attributes.put(ICMGenerator.CIPHER, Registry.AES_CIPHER);
+ byte[] key = new byte[128 / 8]; // AES default key size
+ Random rand = new Random(System.currentTimeMillis());
+ rand.nextBytes(key);
+ attributes.put(IBlockCipher.KEY_MATERIAL, key);
+ int aesBlockSize = 128 / 8; // AES block size in bytes
+ byte[] offset = new byte[aesBlockSize];
+ rand.nextBytes(offset);
+ attributes.put(ICMGenerator.OFFSET, offset);
+ int ndxLen = 0; // the segment length
+ // choose a random value between 1 and aesBlockSize / 2
+ int limit = aesBlockSize / 2;
+ while (ndxLen < 1 || ndxLen > limit)
+ {
+ ndxLen = rand.nextInt(limit + 1);
+ }
+ attributes.put(ICMGenerator.SEGMENT_INDEX_LENGTH, new Integer(ndxLen));
+ byte[] index = new byte[ndxLen];
+ rand.nextBytes(index);
+ attributes.put(ICMGenerator.SEGMENT_INDEX, new BigInteger(1, index));
+
+ prng.setup(attributes);
+ if (DEBUG && debuglevel > 8)
+ debug("<<< resetLocalPRNG()");
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.SecureRandomSpi interface implementation ------------------
+
+ public byte[] engineGenerateSeed(int numBytes)
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(">>> engineGenerateSeed()");
+ if (numBytes < 1)
+ {
+ if (DEBUG && debuglevel > 8)
+ debug("<<< engineGenerateSeed()");
+ return new byte[0];
+ }
+ byte[] result = new byte[numBytes];
+ this.engineNextBytes(result);
+ if (DEBUG && debuglevel > 8)
+ debug("<<< engineGenerateSeed()");
+ return result;
+ }
+
+ public void engineNextBytes(byte[] bytes)
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(">>> engineNextBytes()");
+ if (!adaptee.isInitialised())
+ {
+ this.engineSetSeed(new byte[0]);
+ }
+
+ while (true)
+ {
+ try
+ {
+ adaptee.nextBytes(bytes, 0, bytes.length);
+ break;
+ }
+ catch (LimitReachedException x)
+ { // reseed the generator
+ if (DEBUG)
+ {
+ debug(LIMIT_REACHED_MSG + String.valueOf(x));
+ x.printStackTrace(err);
+ debug(RESEED);
+ }
+ resetLocalPRNG();
+ }
+ }
+ if (DEBUG && debuglevel > 8)
+ debug("<<< engineNextBytes()");
+ }
+
+ public void engineSetSeed(byte[] seed)
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(">>> engineSetSeed()");
+ // compute the total number of random bytes required to setup adaptee
+ int materialLength = 0;
+ materialLength += 16; // key material size
+ materialLength += 16; // offset size
+ materialLength += 8; // index size == half of an AES block
+ byte[] material = new byte[materialLength];
+
+ // use as much as possible bytes from the seed
+ int materialOffset = 0;
+ int materialLeft = material.length;
+ if (seed.length > 0)
+ { // copy some bytes into key and update indices
+ int lenToCopy = Math.min(materialLength, seed.length);
+ System.arraycopy(seed, 0, material, 0, lenToCopy);
+ materialOffset += lenToCopy;
+ materialLeft -= lenToCopy;
+ }
+ if (materialOffset > 0)
+ { // generate the rest
+ while (true)
+ {
+ try
+ {
+ prng.nextBytes(material, materialOffset, materialLeft);
+ break;
+ }
+ catch (IllegalStateException x)
+ { // should not happen
+ throw new InternalError(MSG + String.valueOf(x));
+ }
+ catch (LimitReachedException x)
+ {
+ if (DEBUG)
+ {
+ debug(MSG + String.valueOf(x));
+ debug(RETRY);
+ }
+ }
+ }
+ }
+
+ // setup the underlying adaptee instance
+ HashMap attributes = new HashMap();
+
+ // use AES cipher with 128-bit block size
+ attributes.put(ICMGenerator.CIPHER, Registry.AES_CIPHER);
+ // use an index the size of quarter of an AES block
+ attributes.put(ICMGenerator.SEGMENT_INDEX_LENGTH, new Integer(4));
+ // specify the key
+ byte[] key = new byte[16];
+ System.arraycopy(material, 0, key, 0, 16);
+ attributes.put(IBlockCipher.KEY_MATERIAL, key);
+ // specify the offset
+ byte[] offset = new byte[16];
+ System.arraycopy(material, 16, offset, 0, 16);
+ attributes.put(ICMGenerator.OFFSET, offset);
+ // specify the index
+ byte[] index = new byte[8];
+ System.arraycopy(material, 32, index, 0, 8);
+ attributes.put(ICMGenerator.SEGMENT_INDEX, new BigInteger(1, index));
+
+ adaptee.init(attributes);
+ if (DEBUG && debuglevel > 8)
+ debug("<<< engineSetSeed()");
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/prng/UMacRandomSpi.java b/gnu/javax/crypto/jce/prng/UMacRandomSpi.java
new file mode 100644
index 000000000..7dad68b2f
--- /dev/null
+++ b/gnu/javax/crypto/jce/prng/UMacRandomSpi.java
@@ -0,0 +1,207 @@
+/* UMacRandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.prng;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.prng.UMacGenerator;
+
+import java.io.PrintWriter;
+import java.security.SecureRandomSpi;
+import java.util.HashMap;
+import java.util.Random;
+
+/**
+ * <p>An <em>Adapter</em> class around {@link UMacGenerator} to allow using this
+ * algorithm as a JCE {@link java.security.SecureRandom}.</p>
+ */
+public class UMacRandomSpi extends SecureRandomSpi
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "UMacRandomSpi";
+
+ private static final boolean DEBUG = false;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Class-wide prng to generate random material for the underlying prng.*/
+ private static final UMacGenerator prng; // blank final
+ static
+ {
+ prng = new UMacGenerator();
+ resetLocalPRNG();
+ }
+
+ // error messages
+ private static final String MSG = "Exception while setting up a "
+ + Registry.UMAC_PRNG + " SPI: ";
+
+ private static final String RETRY = "Retry...";
+
+ /** Our underlying prng instance. */
+ private UMacGenerator adaptee = new UMacGenerator();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ private static void resetLocalPRNG()
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(UMacGenerator.CIPHER, Registry.AES_CIPHER);
+ byte[] key = new byte[128 / 8]; // AES default key size
+ Random rand = new Random(System.currentTimeMillis());
+ rand.nextBytes(key);
+ attributes.put(IBlockCipher.KEY_MATERIAL, key);
+ int index = rand.nextInt() & 0xFF;
+ attributes.put(UMacGenerator.INDEX, new Integer(index));
+
+ prng.setup(attributes);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.SecureRandomSpi interface implementation ------------------
+
+ public byte[] engineGenerateSeed(int numBytes)
+ {
+ if (numBytes < 1)
+ {
+ return new byte[0];
+ }
+ byte[] result = new byte[numBytes];
+ this.engineNextBytes(result);
+ return result;
+ }
+
+ public void engineNextBytes(byte[] bytes)
+ {
+ if (!adaptee.isInitialised())
+ {
+ this.engineSetSeed(new byte[0]);
+ }
+
+ while (true)
+ {
+ try
+ {
+ adaptee.nextBytes(bytes, 0, bytes.length);
+ break;
+ }
+ catch (LimitReachedException x)
+ { // reseed the generator
+ resetLocalPRNG();
+ }
+ }
+ }
+
+ public void engineSetSeed(byte[] seed)
+ {
+ // compute the total number of random bytes required to setup adaptee
+ int materialLength = 0;
+ materialLength += 16; // key material size
+ materialLength++; // index size
+ byte[] material = new byte[materialLength];
+
+ // use as much as possible bytes from the seed
+ int materialOffset = 0;
+ int materialLeft = material.length;
+ if (seed.length > 0)
+ { // copy some bytes into key and update indices
+ int lenToCopy = Math.min(materialLength, seed.length);
+ System.arraycopy(seed, 0, material, 0, lenToCopy);
+ materialOffset += lenToCopy;
+ materialLeft -= lenToCopy;
+ }
+ if (materialOffset > 0)
+ { // generate the rest
+ while (true)
+ {
+ try
+ {
+ prng.nextBytes(material, materialOffset, materialLeft);
+ break;
+ }
+ catch (IllegalStateException x)
+ { // should not happen
+ throw new InternalError(MSG + String.valueOf(x));
+ }
+ catch (LimitReachedException x)
+ {
+ if (DEBUG)
+ {
+ debug(MSG + String.valueOf(x));
+ debug(RETRY);
+ }
+ }
+ }
+ }
+
+ // setup the underlying adaptee instance
+ HashMap attributes = new HashMap();
+
+ // use AES cipher with 128-bit block size
+ attributes.put(UMacGenerator.CIPHER, Registry.AES_CIPHER);
+ // specify the key
+ byte[] key = new byte[16];
+ System.arraycopy(material, 0, key, 0, 16);
+ attributes.put(IBlockCipher.KEY_MATERIAL, key);
+ // use a 1-byte index
+ attributes.put(UMacGenerator.INDEX, new Integer(material[16] & 0xFF));
+
+ adaptee.init(attributes);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java b/gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java
new file mode 100644
index 000000000..63e7740ec
--- /dev/null
+++ b/gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java
@@ -0,0 +1,139 @@
+/* BlockCipherParameterSpec.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.spec;
+
+import gnu.java.security.util.Util;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * Block cipher parameters in GNU Crypto are the cipher's name, its block
+ * and key sizes, and an optional initialization vector.
+ */
+public class BlockCipherParameterSpec implements AlgorithmParameterSpec
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ /**
+ * The initialization vector.
+ */
+ protected byte[] iv;
+
+ /**
+ * The cipher's block size, in bytes.
+ */
+ protected int blockSize;
+
+ /**
+ * The cipher's key size, in bytes.
+ */
+ protected int keySize;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Create a new parameter specification.
+ *
+ * @param iv The initialization vector, or <code>null</code> if
+ * there is no IV.
+ * @param blockSize The cipher's block size, in bytes.
+ * @param keySize The cipher's key size, in bytes.
+ */
+ public BlockCipherParameterSpec(byte[] iv, int blockSize, int keySize)
+ {
+ this.iv = (iv != null) ? (byte[]) iv.clone() : null;
+ this.blockSize = blockSize;
+ this.keySize = keySize;
+ }
+
+ /**
+ * Create a new parameter specification with no IV.
+ *
+ * @param blockSize The cipher's block size, in bytes.
+ * @param keySize The cipher's key size, in bytes.
+ */
+ public BlockCipherParameterSpec(int blockSize, int keySize)
+ {
+ this(null, blockSize, keySize);
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Get the initialization vector for the cipher, or <code>null</code>
+ * if there is no IV.
+ *
+ * @return The IV.
+ */
+ public byte[] getIV()
+ {
+ return iv;
+ }
+
+ /**
+ * Get the block size of the cipher these parameters are for.
+ *
+ * @return The block size.
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Get the key size of the cipher these parameters are for.
+ *
+ * @return The block size.
+ */
+ public int getKeySize()
+ {
+ return keySize;
+ }
+
+ public String toString()
+ {
+ return getClass().getName() + " { "
+ + ((iv != null) ? ("IV=" + Util.toString(iv)) + ", " : "") + "BS="
+ + blockSize + ", KS=" + keySize + " }";
+ }
+}
diff --git a/gnu/javax/crypto/jce/spec/TMMHParameterSpec.java b/gnu/javax/crypto/jce/spec/TMMHParameterSpec.java
new file mode 100644
index 000000000..0ebec0991
--- /dev/null
+++ b/gnu/javax/crypto/jce/spec/TMMHParameterSpec.java
@@ -0,0 +1,129 @@
+/* TMMHParameterSpec.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.spec;
+
+import gnu.java.security.prng.IRandom;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class represents the algorithm parameters for the Truncated
+ * Multi-Modular Hash function for use with JCE-derived instances of
+ * {@link gnu.crypto.mac.TMMH16}.
+ *
+ * <p>This class is little more than a container for the key stream, tag
+ * length, and prefix parameters for the TMMH algorithm.
+ */
+public class TMMHParameterSpec implements AlgorithmParameterSpec
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ /** The keystream. */
+ protected IRandom keystream;
+
+ /** The tag length. */
+ protected Integer tagLength;
+
+ /** The prefix. */
+ protected byte[] prefix;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Create a new parameter specification.
+ *
+ * @param keystream The (PRNG) key stream.
+ * @param tagLength The tag length.
+ * @param prefix The prefix.
+ */
+ public TMMHParameterSpec(IRandom keystream, Integer tagLength, byte[] prefix)
+ {
+ this.keystream = keystream;
+ this.tagLength = tagLength;
+ this.prefix = prefix;
+ }
+
+ /**
+ * Create a new parameter specification with no prefix.
+ *
+ * @param keystream The (PRNG) key stream.
+ * @param tagLength The tag length.
+ */
+ public TMMHParameterSpec(IRandom keystream, Integer tagLength)
+ {
+ this(keystream, tagLength, null);
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Return the key stream this specification was initialized with.
+ *
+ * @return The key stream.
+ */
+ public IRandom getKeystream()
+ {
+ return keystream;
+ }
+
+ /**
+ * Return the tag length this specification was initialized with.
+ *
+ * @return The tag length.
+ */
+ public Integer getTagLength()
+ {
+ return tagLength;
+ }
+
+ /**
+ * Return the prefix, or <code>null</code> if no prefix was
+ * specified.
+ *
+ * @return The prefix.
+ */
+ public byte[] getPrefix()
+ {
+ return prefix;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java b/gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java
new file mode 100644
index 000000000..47d807d49
--- /dev/null
+++ b/gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java
@@ -0,0 +1,82 @@
+/* UMac32ParameterSpec.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class represents the parameters for the UMAC-32 message
+ * authentication code algorithm. In practice this means the
+ * <i>Nonce</i> material used to initialize the algorithm.
+ */
+public class UMac32ParameterSpec implements AlgorithmParameterSpec
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ /** The <i>Nonce</i> material. */
+ protected byte[] nonce;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Create a new parameter instance.
+ *
+ * @param nonce The nonce material.
+ */
+ public UMac32ParameterSpec(byte[] nonce)
+ {
+ this.nonce = nonce;
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Return the nonce material.
+ *
+ * @return The nonce material.
+ */
+ public byte[] getNonce()
+ {
+ return nonce;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/key/BaseKeyAgreementParty.java b/gnu/javax/crypto/key/BaseKeyAgreementParty.java
new file mode 100644
index 000000000..5aba47448
--- /dev/null
+++ b/gnu/javax/crypto/key/BaseKeyAgreementParty.java
@@ -0,0 +1,198 @@
+/* BaseKeyAgreementParty.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key;
+
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Map;
+
+/**
+ * <p>A base abstract class to facilitate implementations of concrete key
+ * agreement protocol handlers.</p>
+ */
+public abstract class BaseKeyAgreementParty implements IKeyAgreementParty
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ protected static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ /** The canonical name of the protocol. */
+ protected String name;
+
+ /** Whether the instance is initialised or not. */
+ protected boolean initialised = false;
+
+ /** The current step index of the protocol exchange. */
+ protected int step = -1;
+
+ /** Whether the exchange has concluded or not. */
+ protected boolean complete = false;
+
+ /** The optional {@link SecureRandom} instance to use. */
+ protected SecureRandom rnd = null;
+
+ /** The optional {@link IRandom} instance to use. */
+ protected IRandom irnd = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected BaseKeyAgreementParty(String name)
+ {
+ super();
+
+ this.name = name;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public String name()
+ {
+ return name;
+ }
+
+ public void init(Map attributes) throws KeyAgreementException
+ {
+ if (initialised)
+ {
+ throw new IllegalStateException("already initialised");
+ }
+
+ this.engineInit(attributes);
+
+ initialised = true;
+ this.step = -1;
+ this.complete = false;
+ }
+
+ public OutgoingMessage processMessage(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("not initialised");
+ }
+ if (complete)
+ {
+ throw new IllegalStateException("exchange has already concluded");
+ }
+
+ step++;
+ return this.engineProcessMessage(in);
+ }
+
+ public boolean isComplete()
+ {
+ return complete;
+ }
+
+ public byte[] getSharedSecret() throws KeyAgreementException
+ {
+ if (!initialised)
+ {
+ throw new KeyAgreementException("not yet initialised");
+ }
+ if (!isComplete())
+ {
+ throw new KeyAgreementException("not yet computed");
+ }
+ return engineSharedSecret();
+ }
+
+ public void reset()
+ {
+ if (initialised)
+ {
+ this.engineReset();
+ initialised = false;
+ }
+ }
+
+ // abstract methods to be implemented by concrete subclasses ---------------
+
+ protected abstract void engineInit(Map attributes)
+ throws KeyAgreementException;
+
+ protected abstract OutgoingMessage engineProcessMessage(IncomingMessage in)
+ throws KeyAgreementException;
+
+ protected abstract byte[] engineSharedSecret() throws KeyAgreementException;
+
+ protected abstract void engineReset();
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ * Fills the designated byte array with random data.
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ protected void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else if (irnd != null)
+ {
+ try
+ {
+ irnd.nextBytes(buffer, 0, buffer.length);
+ }
+ catch (LimitReachedException lre)
+ {
+ irnd = null;
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/key/GnuSecretKey.java b/gnu/javax/crypto/key/GnuSecretKey.java
new file mode 100644
index 000000000..93b21a67c
--- /dev/null
+++ b/gnu/javax/crypto/key/GnuSecretKey.java
@@ -0,0 +1,149 @@
+/* GnuSecretKey.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key;
+
+import gnu.java.security.util.Util;
+import java.security.Key;
+
+/**
+ * A secret key composed of a sequence of raw, unformatted octets. This class
+ * is analogous to the {@link javax.crypto.spec.SecretKeySpec} class, but is
+ * provided for platforms that do not or cannot contain that class.
+ */
+public class GnuSecretKey implements Key
+{
+
+ // Field.
+ // ------------------------------------------------------------------------
+
+ private final byte[] key;
+
+ private final String algorithm;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new secret key. The supplied byte array is copied by this
+ * constructor.
+ *
+ * @param key The raw, secret key.
+ * @param algorithm The algorithm name, which can be null or empty.
+ */
+ public GnuSecretKey(byte[] key, String algorithm)
+ {
+ this(key, 0, key.length, algorithm);
+ }
+
+ /**
+ * Creates a new secret key from a portion of a byte array.
+ *
+ * @param key The raw, secret key.
+ * @param offset The offset at which the key begins.
+ * @param length The number of bytes that comprise the key.
+ * @param algorithm The algorithm name, which can be null or empty.
+ */
+ public GnuSecretKey(byte[] key, int offset, int length, String algorithm)
+ {
+ this.key = new byte[length];
+ System.arraycopy(key, offset, this.key, 0, length);
+ this.algorithm = algorithm;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the algorithm name, if any.
+ *
+ * @return The algorithm name.
+ */
+ public String getAlgorithm()
+ {
+ return null;
+ }
+
+ /**
+ * Returns the encoded key, which is merely the byte array this class was
+ * created with. A reference to the internal byte array is returned, so the
+ * caller can delete this key from memory by modifying the returned array.
+ *
+ * @return The raw key.
+ */
+ public byte[] getEncoded()
+ {
+ return key;
+ }
+
+ /**
+ * Returns the string "RAW".
+ *
+ * @return The string "RAW".
+ */
+ public String getFormat()
+ {
+ return "RAW";
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof GnuSecretKey))
+ {
+ return false;
+ }
+ if (key.length != ((GnuSecretKey) o).key.length)
+ {
+ return false;
+ }
+ byte[] key2 = ((GnuSecretKey) o).key;
+ for (int i = 0; i < key.length; i++)
+ {
+ if (key[i] != key2[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public String toString()
+ {
+ return "GnuSecretKey [ " + algorithm + " " + Util.toString(key) + " ]";
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/key/IKeyAgreementParty.java b/gnu/javax/crypto/key/IKeyAgreementParty.java
new file mode 100644
index 000000000..05aef5e51
--- /dev/null
+++ b/gnu/javax/crypto/key/IKeyAgreementParty.java
@@ -0,0 +1,105 @@
+/* IKeyAgreementParty.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key;
+
+import java.util.Map;
+
+/**
+ * <p>The visible methods of an key agreement protocol participating party.</p>
+ */
+public interface IKeyAgreementParty
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of the key agreement protocol.</p>
+ *
+ * @return the canonical name of the key agreement protocol.
+ */
+ String name();
+
+ /**
+ * <p>Sets up the instance to operate with specific attributes.</p>
+ *
+ * @param attributes a map of name-values used by concrete implementations.
+ * @throws KeyAgreementException if an exception occurs during the setup.
+ */
+ void init(Map attributes) throws KeyAgreementException;
+
+ /**
+ * <p>Processes an incoming message at one end, generating a message that
+ * will be processed by the other party(ies).</p>
+ *
+ * @param in the incoming message.
+ * @return an outgoing message, or <code>null</code> if this is an
+ * intermediary step that does not cause any output.
+ * @throws KeyAgreementException if an exception occurs during the processing
+ * of the incoming message, or during the generation of the outgoing message.
+ */
+ OutgoingMessage processMessage(IncomingMessage in)
+ throws KeyAgreementException;
+
+ /**
+ * <p>Returns <code>true</code> if the party in the key agreement protocol
+ * exchange has completed its part of the exchange. If this is the case an
+ * {@link IllegalStateException} is thrown for any method invocation except
+ * <code>init()</code> or <code>reset()</code>.
+ * @return <code>true</code> if this party has completed its part of the key
+ * agreement protocol exchange; <code>false</code> otherwise.
+ */
+ boolean isComplete();
+
+ /**
+ * <p>Returns the byte array containing the shared secret as generated by
+ * this party.</p>
+ *
+ * @return the generated shared secret.
+ * @throws KeyAgreementException if the key agreement is not yet initialised,
+ * or is initialised but the exchange is still in progress.
+ */
+ byte[] getSharedSecret() throws KeyAgreementException;
+
+ /** Resets this instance for re-use with another set of attributes. */
+ void reset();
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/key/IncomingMessage.java b/gnu/javax/crypto/key/IncomingMessage.java
new file mode 100644
index 000000000..721b0faed
--- /dev/null
+++ b/gnu/javax/crypto/key/IncomingMessage.java
@@ -0,0 +1,293 @@
+/* IncomingMessage.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.key.KeyPairCodecFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>An implementation of an incoming message for use with key agreement
+ * protocols.</p>
+ */
+public class IncomingMessage
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The internal buffer stream containing the message's contents. */
+ protected ByteArrayInputStream in;
+
+ /** The length of the message contents, according to its 4-byte header. */
+ protected int length;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Constructs an incoming message given the message's encoded form,
+ * including its header bytes.</p>
+ *
+ * @param b the encoded form, including the header bytes, of an incoming
+ * message.
+ * @throws KeyAgreementException if the buffer is malformed.
+ */
+ public IncomingMessage(byte[] b) throws KeyAgreementException
+ {
+ this();
+
+ if (b.length < 4)
+ {
+ throw new KeyAgreementException("message header too short");
+ }
+ length = b[0] << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8
+ | (b[3] & 0xFF);
+ if (length > Registry.SASL_BUFFER_MAX_LIMIT || length < 0)
+ {
+ throw new KeyAgreementException("message size limit exceeded");
+ }
+ in = new ByteArrayInputStream(b, 4, length);
+ }
+
+ /** Trivial private constructor for use by the class method. */
+ private IncomingMessage()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a message given its encoded contents, excluding
+ * the message's header bytes.</p>
+ *
+ * <p>Calls the method with the same name and three arguments as:
+ * <code>getInstance(raw, 0, raw.length)</code>.
+ *
+ * @param raw the encoded form, excluding the header bytes.
+ * @return a new instance of <code>IncomingMessage</code>.
+ */
+ public static IncomingMessage getInstance(byte[] raw)
+ {
+ return getInstance(raw, 0, raw.length);
+ }
+
+ /**
+ * <p>Returns an instance of a message given its encoded contents, excluding
+ * the message's header bytes.</p>
+ *
+ * @param raw the encoded form, excluding the header bytes.
+ * @param offset offset where to start using raw bytes from.
+ * @param len number of bytes to use.
+ * @return a new instance of <code>IncomingMessage</code>.
+ */
+ public static IncomingMessage getInstance(byte[] raw, int offset, int len)
+ {
+ IncomingMessage result = new IncomingMessage();
+ result.in = new ByteArrayInputStream(raw, offset, len);
+ return result;
+ }
+
+ /**
+ * <p>Converts two octets into the number that they represent.</p>
+ *
+ * @param b the two octets.
+ * @return the length.
+ */
+ public static int twoBytesToLength(byte[] b) throws KeyAgreementException
+ {
+ int result = (b[0] & 0xFF) << 8 | (b[1] & 0xFF);
+ if (result > Registry.SASL_TWO_BYTE_MAX_LIMIT)
+ {
+ throw new KeyAgreementException("encoded MPI size limit exceeded");
+ }
+ return result;
+ }
+
+ /**
+ * <p>Converts four octets into the number that they represent.</p>
+ *
+ * @param b the four octets.
+ * @return the length.
+ */
+ public static int fourBytesToLength(byte[] b) throws KeyAgreementException
+ {
+ int result = b[0] << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8
+ | (b[3] & 0xFF);
+ if (result > Registry.SASL_FOUR_BYTE_MAX_LIMIT || result < 0)
+ {
+ throw new KeyAgreementException("encoded entity size limit exceeded");
+ }
+ return result;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public boolean hasMoreElements()
+ {
+ return (in.available() > 0);
+ }
+
+ public PublicKey readPublicKey() throws KeyAgreementException
+ {
+ if (in.available() < 4)
+ {
+ throw new KeyAgreementException(
+ "not enough bytes for a public key in message");
+ }
+
+ byte[] elementLengthBytes = new byte[4];
+ in.read(elementLengthBytes, 0, 4);
+ int elementLength = fourBytesToLength(elementLengthBytes);
+ if (in.available() < elementLength)
+ {
+ throw new KeyAgreementException("illegal public key encoding");
+ }
+
+ byte[] kb = new byte[elementLength];
+ in.read(kb, 0, elementLength);
+
+ // instantiate the right codec and decode
+ IKeyPairCodec kpc = KeyPairCodecFactory.getInstance(kb);
+ if (kpc == null)
+ {
+ throw new KeyAgreementException(
+ "invalid public key, or encoded with an unknown codec");
+ }
+
+ return kpc.decodePublicKey(kb);
+ }
+
+ public PrivateKey readPrivateKey() throws KeyAgreementException
+ {
+ if (in.available() < 4)
+ {
+ throw new KeyAgreementException(
+ "not enough bytes for a private key in message");
+ }
+
+ byte[] elementLengthBytes = new byte[4];
+ in.read(elementLengthBytes, 0, 4);
+ int elementLength = fourBytesToLength(elementLengthBytes);
+ if (in.available() < elementLength)
+ {
+ throw new KeyAgreementException("illegal private key encoding");
+ }
+
+ byte[] kb = new byte[elementLength];
+ in.read(kb, 0, elementLength);
+
+ // instantiate the right codec and decode
+ IKeyPairCodec kpc = KeyPairCodecFactory.getInstance(kb);
+ if (kpc == null)
+ {
+ throw new KeyAgreementException(
+ "invalid private key, or encoded with an unknown codec");
+ }
+
+ return kpc.decodePrivateKey(kb);
+ }
+
+ /**
+ * <p>Decodes an MPI from the current message's contents.</p>
+ *
+ * @return a native representation of an MPI.
+ * @throws KeyAgreementException if an encoding exception occurs during the
+ * operation.
+ */
+ public BigInteger readMPI() throws KeyAgreementException
+ {
+ if (in.available() < 2)
+ {
+ throw new KeyAgreementException(
+ "not enough bytes for an MPI in message");
+ }
+ byte[] elementLengthBytes = new byte[2];
+ in.read(elementLengthBytes, 0, 2);
+ int elementLength = twoBytesToLength(elementLengthBytes);
+ if (in.available() < elementLength)
+ {
+ throw new KeyAgreementException("illegal MPI encoding");
+ }
+
+ byte[] element = new byte[elementLength];
+ in.read(element, 0, element.length);
+
+ return new BigInteger(1, element);
+ }
+
+ public String readString() throws KeyAgreementException
+ {
+ if (in.available() < 2)
+ {
+ throw new KeyAgreementException(
+ "not enough bytes for a text in message");
+ }
+ byte[] elementLengthBytes = new byte[2];
+ in.read(elementLengthBytes, 0, 2);
+ int elementLength = twoBytesToLength(elementLengthBytes);
+ if (in.available() < elementLength)
+ {
+ throw new KeyAgreementException("illegal text encoding");
+ }
+
+ byte[] element = new byte[elementLength];
+ in.read(element, 0, element.length);
+ String result = null;
+ try
+ {
+ result = new String(element, "UTF8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new KeyAgreementException("unxupported UTF8 encoding", x);
+ }
+
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/key/KeyAgreementException.java b/gnu/javax/crypto/key/KeyAgreementException.java
new file mode 100644
index 000000000..c2fa434a2
--- /dev/null
+++ b/gnu/javax/crypto/key/KeyAgreementException.java
@@ -0,0 +1,187 @@
+/* KeyAgreementException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.security.KeyManagementException;
+
+/**
+ * A generic exception indicating that an unexpected condition has
+ * been detected during the setup and/or processing of a key agreement
+ * protocol exchange.
+ */
+public class KeyAgreementException extends KeyManagementException implements
+ Serializable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** @serial The possibly <code>null</code> <i>root</i> cause exception. */
+ private Throwable cause = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Constructs a new instance of <code>KeyAgreementException</code>. The
+ * root exception and the detailed message are <code>null</code>.</p>
+ */
+ public KeyAgreementException()
+ {
+ super();
+ }
+
+ /**
+ * <p>Constructs a new instance of <code>KeyAgreementException</code> with a
+ * detailed message. The <i>root</i> exception is <code>null</code>.</p>
+ *
+ * @param detail a possibly <code>null</code> string containing details of
+ * the exception.
+ * @see Throwable#getMessage()
+ */
+ public KeyAgreementException(String detail)
+ {
+ super(detail);
+ }
+
+ /**
+ * <p>Constructs a new instance of <code>KeyAgreementException</code> with a
+ * detailed message and a <i>root</i> exception.</p>
+ *
+ * @param detail a possibly <code>null</code> string containing details of
+ * the exception.
+ * @param cause a possibly <code>null</code> root exception that caused this
+ * exception.
+ * @see Throwable#getMessage()
+ * @see #getCause()
+ */
+ public KeyAgreementException(String detail, Throwable cause)
+ {
+ super(detail);
+ this.cause = cause;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the cause of this throwable or <code>null</code> if the cause
+ * is nonexistent or unknown. The <i>cause</i> is the throwable that caused
+ * this exception to be thrown.</p>
+ *
+ * @return the possibly <code>null</code> exception that caused this one.
+ */
+ public Throwable getCause()
+ {
+ return cause;
+ }
+
+ /**
+ * <p>Prints this exception's stack trace to <code>System.err</code>. If this
+ * exception has a <i>root</i> exception; the stack trace of the <i>root</i>
+ * exception is also printed to <code>System.err</code>.</p>
+ */
+ public void printStackTrace()
+ {
+ super.printStackTrace();
+ if (cause != null)
+ {
+ cause.printStackTrace();
+ }
+ }
+
+ /**
+ * <p>Prints this exception's stack trace to a print stream. If this
+ * exception has a <i>root</i> exception; the stack trace of the <i>root</i>
+ * exception is also printed to the print stream.</p>
+ *
+ * @param ps the non-null print stream to which to print.
+ */
+ public void printStackTrace(PrintStream ps)
+ {
+ super.printStackTrace(ps);
+ if (cause != null)
+ {
+ cause.printStackTrace(ps);
+ }
+ }
+
+ /**
+ * <p>Prints this exception's stack trace to a print writer. If this
+ * exception has a <i>root</i> exception; the stack trace of the <i>root</i>
+ * exception is also printed to the print writer.</p>
+ *
+ * @param pw the non-null print writer to use for output.
+ */
+ public void printStackTrace(PrintWriter pw)
+ {
+ super.printStackTrace(pw);
+ if (cause != null)
+ {
+ cause.printStackTrace(pw);
+ }
+ }
+
+ /**
+ * <p>Returns the string representation of this exception. The string
+ * representation contains this exception's class name, its detailed
+ * messsage, and if it has a <i>root</i> exception, the string representation
+ * of the root exception. This string representation is meant for debugging
+ * and is not meant to be interpreted programmatically.</p>
+ *
+ * @return the non-null string representation of this exception.
+ * @see Throwable#getMessage()
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer(this.getClass().getName()).append(": ").append(
+ super.toString());
+ if (cause != null)
+ {
+ sb.append("; caused by: ").append(cause.toString());
+ }
+ return sb.toString();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/key/KeyAgreementFactory.java b/gnu/javax/crypto/key/KeyAgreementFactory.java
new file mode 100644
index 000000000..e2a7faba1
--- /dev/null
+++ b/gnu/javax/crypto/key/KeyAgreementFactory.java
@@ -0,0 +1,181 @@
+/* KeyAgreementFactory.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key;
+
+import gnu.java.security.Registry;
+
+import gnu.javax.crypto.key.dh.DiffieHellmanSender;
+import gnu.javax.crypto.key.dh.DiffieHellmanReceiver;
+import gnu.javax.crypto.key.dh.ElGamalSender;
+import gnu.javax.crypto.key.dh.ElGamalReceiver;
+import gnu.javax.crypto.key.srp6.SRP6Host;
+import gnu.javax.crypto.key.srp6.SRP6User;
+import gnu.javax.crypto.key.srp6.SRP6SaslClient;
+import gnu.javax.crypto.key.srp6.SRP6SaslServer;
+import gnu.javax.crypto.key.srp6.SRP6TLSClient;
+import gnu.javax.crypto.key.srp6.SRP6TLSServer;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>A <i>Factory</i> class to generate key agreement protocol handlers.</p>
+ */
+public class KeyAgreementFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce <i>Singleton</i> pattern. */
+ private KeyAgreementFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a key agreeent protocol handler, for party
+ * <code>A</code> in a two-party <code>A..B</code> exchange, given the
+ * canonical name of this protocol. Party <code>A</code> is usually the
+ * initiator of the exchange.</p>
+ *
+ * @param name the case-insensitive key agreement protocol name.
+ * @return an instance of the key agreement protocol handler for party
+ * <code>A</code>, or <code>null</code> if none found.
+ */
+ public static IKeyAgreementParty getPartyAInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ IKeyAgreementParty result = null;
+ if (name.equalsIgnoreCase(Registry.DH_KA))
+ {
+ result = new DiffieHellmanSender();
+ }
+ else if (name.equalsIgnoreCase(Registry.ELGAMAL_KA))
+ {
+ result = new ElGamalSender();
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP6_KA))
+ {
+ result = new SRP6User();
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP_SASL_KA))
+ {
+ result = new SRP6SaslClient();
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP_TLS_KA))
+ {
+ result = new SRP6TLSClient();
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns an instance of a key agreeent protocol handler, for party
+ * <code>B</code> in a two-party <code>A..B</code> exchange, given the
+ * canonical name of this protocol.</p>
+ *
+ * @param name the case-insensitive key agreement protocol name.
+ * @return an instance of the key agreement protocol handler for party
+ * <code>B</code>, or <code>null</code> if none found.
+ */
+ public static IKeyAgreementParty getPartyBInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ IKeyAgreementParty result = null;
+ if (name.equalsIgnoreCase(Registry.DH_KA))
+ {
+ result = new DiffieHellmanReceiver();
+ }
+ else if (name.equalsIgnoreCase(Registry.ELGAMAL_KA))
+ {
+ result = new ElGamalReceiver();
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP6_KA))
+ {
+ result = new SRP6Host();
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP_SASL_KA))
+ {
+ result = new SRP6SaslServer();
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP_TLS_KA))
+ {
+ result = new SRP6TLSServer();
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of key agreement protocol names supported by this
+ * <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of key agreement protocol names (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.DH_KA);
+ hs.add(Registry.ELGAMAL_KA);
+ hs.add(Registry.SRP6_KA);
+ hs.add(Registry.SRP_SASL_KA);
+ hs.add(Registry.SRP_TLS_KA);
+
+ return Collections.unmodifiableSet(hs);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/key/OutgoingMessage.java b/gnu/javax/crypto/key/OutgoingMessage.java
new file mode 100644
index 000000000..7a74370cc
--- /dev/null
+++ b/gnu/javax/crypto/key/OutgoingMessage.java
@@ -0,0 +1,212 @@
+/* OutgoingMessage.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.key.KeyPairCodecFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.math.BigInteger;
+
+/**
+ * <p>An implementation of outgoing messages for use with key agreement
+ * protocols.</p>
+ */
+public class OutgoingMessage
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The internal output stream. */
+ private ByteArrayOutputStream out;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public OutgoingMessage()
+ {
+ super();
+
+ out = new ByteArrayOutputStream();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of the current message including the 4-byte
+ * length header.</p>
+ *
+ * @throws KeyAgreementException if an encoding size constraint is violated.
+ */
+ public byte[] toByteArray() throws KeyAgreementException
+ {
+ byte[] buffer = wrap();
+ int length = buffer.length;
+ byte[] result = new byte[length + 4];
+ result[0] = (byte) (length >>> 24);
+ result[1] = (byte) (length >>> 16);
+ result[2] = (byte) (length >>> 8);
+ result[3] = (byte) length;
+ System.arraycopy(buffer, 0, result, 4, length);
+
+ return result;
+ }
+
+ /**
+ * <p>Returns the encoded form of the current message excluding the 4-byte
+ * length header.</p>
+ *
+ * @throws KeyAgreementException if an encoding size constraint is violated.
+ */
+ public byte[] wrap() throws KeyAgreementException
+ {
+ int length = out.size();
+ if (length > Registry.SASL_BUFFER_MAX_LIMIT || length < 0)
+ {
+ throw new KeyAgreementException("message content is too long");
+ }
+ return out.toByteArray();
+ }
+
+ /**
+ * <p>Encodes a public key into the message.</p>
+ *
+ * @param k the public key to encode.
+ * @throws KeyAgreementException if an encoding size constraint is violated.
+ */
+ public void writePublicKey(PublicKey k) throws KeyAgreementException
+ {
+ IKeyPairCodec kpc = KeyPairCodecFactory.getInstance(k);
+ if (kpc == null)
+ {
+ throw new KeyAgreementException("");
+ }
+ byte[] b = kpc.encodePublicKey(k);
+ int length = b.length;
+ if (length > Registry.SASL_FOUR_BYTE_MAX_LIMIT)
+ {
+ throw new KeyAgreementException("encoded public key is too long");
+ }
+ byte[] lengthBytes = { (byte) (length >>> 24), (byte) (length >>> 16),
+ (byte) (length >>> 8), (byte) length };
+ out.write(lengthBytes, 0, 4);
+ out.write(b, 0, b.length);
+ }
+
+ /**
+ * <p>Encodes a private key into the message.</p>
+ *
+ * @param k the private key to encode.
+ * @throws KeyAgreementException if an encoding size constraint is violated.
+ */
+ public void writePrivateKey(PrivateKey k) throws KeyAgreementException
+ {
+ IKeyPairCodec kpc = KeyPairCodecFactory.getInstance(k);
+ if (kpc == null)
+ {
+ throw new KeyAgreementException("");
+ }
+ byte[] b = kpc.encodePrivateKey(k);
+ int length = b.length;
+ if (length > Registry.SASL_FOUR_BYTE_MAX_LIMIT)
+ {
+ throw new KeyAgreementException("encoded private key is too long");
+ }
+ byte[] lengthBytes = { (byte) (length >>> 24), (byte) (length >>> 16),
+ (byte) (length >>> 8), (byte) length };
+ out.write(lengthBytes, 0, 4);
+ out.write(b, 0, b.length);
+ }
+
+ /**
+ * <p>Encodes an MPI into the message.</p>
+ *
+ * @param val the MPI to encode.
+ * @throws KeyAgreementException if an encoding size constraint is violated.
+ */
+ public void writeMPI(BigInteger val) throws KeyAgreementException
+ {
+ byte[] b = val.toByteArray();
+ int length = b.length;
+ if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
+ {
+ throw new KeyAgreementException("MPI is too long");
+ }
+ byte[] lengthBytes = { (byte) (length >>> 8), (byte) length };
+ out.write(lengthBytes, 0, 2);
+ out.write(b, 0, b.length);
+ }
+
+ /**
+ * <p>Encodes a string into the message.</p>
+ *
+ * @param s the string to encode.
+ * @throws KeyAgreementException if the UTF8 encoding is not supported on
+ * this platform, or if an encoding size constraint is violated.
+ */
+ public void writeString(String s) throws KeyAgreementException
+ {
+ byte[] b = null;
+ try
+ {
+ b = s.getBytes("UTF8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new KeyAgreementException("unxupported UTF8 encoding", x);
+ }
+ int length = b.length;
+ if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
+ {
+ throw new KeyAgreementException("text too long");
+ }
+ byte[] lengthBytes = { (byte) (length >>> 8), (byte) length };
+ out.write(lengthBytes, 0, 2);
+ out.write(b, 0, b.length);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java b/gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java
new file mode 100644
index 000000000..c0ff82bea
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java
@@ -0,0 +1,370 @@
+/* DHKeyPairRawCodec.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>An object that implements the {@link IKeyPairCodec} operations for the
+ * <i>Raw</i> format to use with Diffie-Hellman keypairs.</p>
+ */
+public class DHKeyPairRawCodec implements IKeyPairCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments ctor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.keys.IKeyPairCodec interface implementation -------------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated Diffie-Hellman public key
+ * according to the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for a DH public key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_DH_PUBLIC_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the DH parameter
+ * <code>q</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DH parameter <code>q</code>,</li>
+ * <li>4-byte count of following bytes representing the DH parameter
+ * <code>p</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DH parameter <code>p</code>,</li>
+ * <li>4-byte count of following bytes representing the DH parameter
+ * <code>g</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DH parameter <code>g</code>,</li>
+ * <li>4-byte count of following bytes representing the DH parameter
+ * <code>y</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DH parameter <code>y</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @throws IllegalArgumentException if the designated key is not a DH one.
+ * @see Registry#MAGIC_RAW_DH_PUBLIC_KEY
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (!(key instanceof GnuDHPublicKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ GnuDHPublicKey dhKey = (GnuDHPublicKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // q
+ byte[] buffer = dhKey.getQ().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // p
+ buffer = dhKey.getParams().getP().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // g
+ buffer = dhKey.getParams().getG().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // y
+ buffer = dhKey.getY().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PublicKey decodePublicKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+ int l;
+ byte[] buffer;
+
+ // q
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger q = new BigInteger(1, buffer);
+
+ // p
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger p = new BigInteger(1, buffer);
+
+ // g
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger g = new BigInteger(1, buffer);
+
+ // y
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger y = new BigInteger(1, buffer);
+
+ return new GnuDHPublicKey(q, p, g, y);
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated Diffie-Hellman private key
+ * according to the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for a DH private key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_DH_PRIVATE_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the DH parameter
+ * <code>q</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DH parameter <code>q</code>,</li>
+ * <li>4-byte count of following bytes representing the DH parameter
+ * <code>p</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DH parameter <code>p</code>,</li>
+ * <li>4-byte count of following bytes representing the DH parameter
+ * <code>g</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DH parameter <code>g</code>,</li>
+ * <li>4-byte count of following bytes representing the DH parameter
+ * <code>x</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DH parameter <code>x</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @throws IllegalArgumentException if the designated key is not a DH one.
+ * @see Registry#MAGIC_RAW_DH_PRIVATE_KEY
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (!(key instanceof GnuDHPrivateKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ GnuDHPrivateKey dhKey = (GnuDHPrivateKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // q
+ byte[] buffer = dhKey.getQ().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // p
+ buffer = dhKey.getParams().getP().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // g
+ buffer = dhKey.getParams().getG().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // x
+ buffer = dhKey.getX().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PrivateKey decodePrivateKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+ int l;
+ byte[] buffer;
+
+ // q
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger q = new BigInteger(1, buffer);
+
+ // p
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger p = new BigInteger(1, buffer);
+
+ // g
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger g = new BigInteger(1, buffer);
+
+ // x
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger x = new BigInteger(1, buffer);
+
+ return new GnuDHPrivateKey(q, p, g, x);
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java b/gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java
new file mode 100644
index 000000000..5b1caa7d1
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java
@@ -0,0 +1,134 @@
+/* DiffieHellmanKeyAgreement.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.key.BaseKeyAgreementParty;
+import gnu.javax.crypto.key.KeyAgreementException;
+
+import java.math.BigInteger;
+
+import javax.crypto.interfaces.DHPrivateKey;
+
+/**
+ * <p>The basic version of the Diffie-Hellman key agreement is described in the
+ * Handbook of Applied Cryptography [HAC] as follows:</p>
+ * <ul>
+ * <li>An appropriate prime p and generator g of Z<sub>p</sub><sup>*</sup>
+ * (2 &lt;= g &lt;= p-2) are selected and published.</li>
+ * <li>A and B each send the other one message over an open channel; as a
+ * result, they both can then compute a shared secret key K which they can
+ * use to protect their future communication.</li>
+ * <li>A chooses a random secret x, 1 &lt;= x &lt;= p-2, and sends B message
+ * (1) which is g^x mod p.</li>
+ * <li>B chooses a random secret y, 1 &lt;= y &lt;= p-2, and sends A message
+ * (2) which is g^y mod p.</li>
+ * <li>B receives message (1) and computes the shared key as K = (g^x)^y mod
+ * p.</li>
+ * <li>A receives message (2) and computes the shared key as K = (g^y)^x mod
+ * p.</li>
+ * </ul>
+ *
+ * <p>RFC-2631 describes a <i>Static-Static Mode</i> of operations with
+ * Diffie-Hellman keypairs as follows:</p>
+ * <pre>
+ * "In Static-Static mode, both the sender and the recipient have a
+ static (and certified) key pair. Since the sender's and recipient's
+ keys are therefore the same for each message, ZZ will be the same for
+ each message. Thus, partyAInfo MUST be used (and different for each
+ message) in order to ensure that different messages use different
+ KEKs. Implementations MAY implement Static-Static mode."
+ * </pre>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
+ * Agreement Method</a><br>
+ * Eric Rescorla.</li>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
+ * Applied Cryptography.<br>
+ * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
+ * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
+ * </ol>
+ */
+public abstract class DiffieHellmanKeyAgreement extends BaseKeyAgreementParty
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dh.ka.prng";
+
+ public static final String KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY = "gnu.crypto.dh.ka.owner.private.key";
+
+ /** The key agreement party's private key. */
+ protected DHPrivateKey ownerKey;
+
+ /** The shared secret key. */
+ protected BigInteger ZZ;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected DiffieHellmanKeyAgreement()
+ {
+ super(Registry.DH_KA);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of common abstract methods in BaseKeyAGreementParty ------
+
+ protected byte[] engineSharedSecret() throws KeyAgreementException
+ {
+ return Util.trim(ZZ);
+ }
+
+ protected void engineReset()
+ {
+ ownerKey = null;
+ ZZ = null;
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java b/gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java
new file mode 100644
index 000000000..4a3664d6a
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java
@@ -0,0 +1,147 @@
+/* DiffieHellmanReceiver.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.prng.IRandom;
+
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Map;
+
+import javax.crypto.interfaces.DHPrivateKey;
+
+/**
+ * <p>This implementation is the receiver's part of the basic version of the
+ * Diffie-Hellman key agreement exchange (B in [HAC]).</p>
+ *
+ * @see DiffieHellmanKeyAgreement
+ */
+public class DiffieHellmanReceiver extends DiffieHellmanKeyAgreement
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private BigInteger y; // the receiver's random secret
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in base class ------------------------
+
+ protected void engineInit(Map attributes) throws KeyAgreementException
+ {
+ Object random = attributes.get(SOURCE_OF_RANDOMNESS);
+ rnd = null;
+ irnd = null;
+ if (random instanceof SecureRandom)
+ {
+ rnd = (SecureRandom) random;
+ }
+ else if (random instanceof IRandom)
+ {
+ irnd = (IRandom) random;
+ }
+ ownerKey = (DHPrivateKey) attributes.get(KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY);
+ if (ownerKey == null)
+ {
+ throw new KeyAgreementException("missing owner's private key");
+ }
+ }
+
+ protected OutgoingMessage engineProcessMessage(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ switch (step)
+ {
+ case 0:
+ return computeSharedSecret(in);
+ default:
+ throw new IllegalStateException("unexpected state");
+ }
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private OutgoingMessage computeSharedSecret(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ BigInteger m1 = in.readMPI();
+ if (m1 == null)
+ {
+ throw new KeyAgreementException("missing message (1)");
+ }
+
+ BigInteger p = ownerKey.getParams().getP();
+ BigInteger g = ownerKey.getParams().getG();
+
+ // B chooses a random integer y, 1 <= y <= p-2
+ // rfc-2631 restricts y to only be in [2, p-1]
+ BigInteger p_minus_2 = p.subtract(TWO);
+ byte[] xBytes = new byte[(p_minus_2.bitLength() + 7) / 8];
+ do
+ {
+ nextRandomBytes(xBytes);
+ y = new BigInteger(1, xBytes);
+ }
+ while (!(y.compareTo(TWO) >= 0 && y.compareTo(p_minus_2) <= 0));
+
+ ZZ = m1.modPow(y, p); // ZZ = (yb ^ xa) mod p
+
+ complete = true;
+
+ // B sends A the message: g^y mod p
+ OutgoingMessage result = new OutgoingMessage();
+ result.writeMPI(g.modPow(y, p)); // message (2)
+
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/DiffieHellmanSender.java b/gnu/javax/crypto/key/dh/DiffieHellmanSender.java
new file mode 100644
index 000000000..6b9cf70b6
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/DiffieHellmanSender.java
@@ -0,0 +1,156 @@
+/* DiffieHellmanSender.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.prng.IRandom;
+
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Map;
+
+import javax.crypto.interfaces.DHPrivateKey;
+
+/**
+ * <p>This implementation is the sender's part of the basic version of the
+ * Diffie-Hellman key agreement exchange (A in [HAC]).</p>
+ *
+ * @see DiffieHellmanKeyAgreement
+ * @version $Revision: 1.1 $
+ */
+public class DiffieHellmanSender extends DiffieHellmanKeyAgreement
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private BigInteger x; // the sender's random secret
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in base class ------------------------
+
+ protected void engineInit(Map attributes) throws KeyAgreementException
+ {
+ Object random = attributes.get(SOURCE_OF_RANDOMNESS);
+ rnd = null;
+ irnd = null;
+ if (random instanceof SecureRandom)
+ {
+ rnd = (SecureRandom) random;
+ }
+ else if (random instanceof IRandom)
+ {
+ irnd = (IRandom) random;
+ }
+ ownerKey = (DHPrivateKey) attributes.get(KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY);
+ if (ownerKey == null)
+ {
+ throw new KeyAgreementException("missing owner's private key");
+ }
+ }
+
+ protected OutgoingMessage engineProcessMessage(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ switch (step)
+ {
+ case 0:
+ return sendRandomSecret(in);
+ case 1:
+ return computeSharedSecret(in);
+ default:
+ throw new IllegalStateException("unexpected state");
+ }
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private OutgoingMessage sendRandomSecret(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ BigInteger p = ownerKey.getParams().getP();
+ BigInteger g = ownerKey.getParams().getG();
+
+ // A chooses a random integer x, 1 <= x <= p-2
+ // rfc-2631 restricts x to only be in [2, p-1]
+ BigInteger p_minus_2 = p.subtract(TWO);
+ byte[] xBytes = new byte[(p_minus_2.bitLength() + 7) / 8];
+ do
+ {
+ nextRandomBytes(xBytes);
+ x = new BigInteger(1, xBytes);
+ }
+ while (!(x.compareTo(TWO) >= 0 && x.compareTo(p_minus_2) <= 0));
+
+ // A sends B the message: g^x mod p
+ OutgoingMessage result = new OutgoingMessage();
+ result.writeMPI(g.modPow(x, p));
+
+ return result;
+ }
+
+ private OutgoingMessage computeSharedSecret(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ BigInteger m1 = in.readMPI();
+ if (m1 == null)
+ {
+ throw new KeyAgreementException("missing message (2)");
+ }
+
+ BigInteger p = ownerKey.getParams().getP();
+ ZZ = m1.modPow(x, p); // ZZ = (yb ^ xa) mod p
+
+ complete = true;
+ return null;
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java b/gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java
new file mode 100644
index 000000000..1c4e11ce2
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java
@@ -0,0 +1,130 @@
+/* ElGamalKeyAgreement.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.key.BaseKeyAgreementParty;
+import gnu.javax.crypto.key.KeyAgreementException;
+
+import java.math.BigInteger;
+
+/**
+ * <p>The ElGamal key agreement, also known as the half-certified Diffie-Hellman
+ * key agreement, is described in the Handbook of Applied Cryptography [HAC] as
+ * follows:</p>
+ * <ul>
+ * <li>A sends to B a single message allowing one-pass key agreement.</li>
+ * <li>A obtains an authentic copy of B's public key (p, g, yb), where
+ * yb = g**xb.</li>
+ * <li>A chooses a random integer x, 1 &lt;= x &lt;= p-2, and sends B the
+ * message g**x. A computes the shared secret key K as yb**x.</li>
+ * <li>B computes the same key K on receipt of the previous message as
+ * (g**x)**xb.</li>
+ * </ul>
+ *
+ * <p>RFC-2631 describes an <i>Ephemeral-Static Mode</i> of operations with
+ * Diffie-Hellman keypairs as follows:</p>
+ * <pre>
+ * "In Ephemeral-Static mode, the recipient has a static (and certified)
+ * key pair, but the sender generates a new key pair for each message
+ * and sends it using the originatorKey production. If the sender's key
+ * is freshly generated for each message, the shared secret ZZ will be
+ * similarly different for each message and partyAInfo MAY be omitted,
+ * since it serves merely to decouple multiple KEKs generated by the
+ * same set of pairwise keys. If, however, the same ephemeral sender key
+ * is used for multiple messages (e.g. it is cached as a performance
+ * optimization) then a separate partyAInfo MUST be used for each
+ * message. All implementations of this standard MUST implement
+ * Ephemeral-Static mode."
+ * </pre>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
+ * Agreement Method</a><br>
+ * Eric Rescorla.</li>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
+ * Applied Cryptography.<br>
+ * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
+ * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
+ * </ol>
+ */
+public abstract class ElGamalKeyAgreement extends BaseKeyAgreementParty
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.elgamal.ka.prng";
+
+ public static final String KA_ELGAMAL_RECIPIENT_PRIVATE_KEY = "gnu.crypto.elgamal.ka.recipient.private.key";
+
+ public static final String KA_ELGAMAL_RECIPIENT_PUBLIC_KEY = "gnu.crypto.elgamal.ka.recipient.public.key";
+
+ /** The shared secret key. */
+ protected BigInteger ZZ;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected ElGamalKeyAgreement()
+ {
+ super(Registry.ELGAMAL_KA);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of common abstract methods in BaseKeyAGreementParty ------
+
+ protected byte[] engineSharedSecret() throws KeyAgreementException
+ {
+ return Util.trim(ZZ);
+ }
+
+ protected void engineReset()
+ {
+ ZZ = null;
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/ElGamalReceiver.java b/gnu/javax/crypto/key/dh/ElGamalReceiver.java
new file mode 100644
index 000000000..24776cba1
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/ElGamalReceiver.java
@@ -0,0 +1,121 @@
+/* ElGamalReceiver.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Map;
+
+import javax.crypto.interfaces.DHPrivateKey;
+
+/**
+ * <p>This implementation is the receiver's part of the ElGamal key agreement
+ * exchange (B in [HAC]).</p>
+ *
+ * @see ElGamalKeyAgreement
+ */
+public class ElGamalReceiver extends ElGamalKeyAgreement
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The recipient's private key. */
+ private DHPrivateKey B;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in base class ------------------------
+
+ protected void engineInit(Map attributes) throws KeyAgreementException
+ {
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+ // One-time setup (key generation and publication). Each user B generates
+ // a keypair and publishes its public key
+ B = (DHPrivateKey) attributes.get(KA_ELGAMAL_RECIPIENT_PRIVATE_KEY);
+ if (B == null)
+ {
+ throw new KeyAgreementException("missing recipient private key");
+ }
+ }
+
+ protected OutgoingMessage engineProcessMessage(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ switch (step)
+ {
+ case 0:
+ return computeSharedSecret(in);
+ default:
+ throw new IllegalStateException("unexpected state");
+ }
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private OutgoingMessage computeSharedSecret(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ // (b) B computes the same key on receipt of message (1) as
+ // K = (g^x)^xb mod p
+ BigInteger m1 = in.readMPI();
+ if (m1 == null)
+ {
+ throw new KeyAgreementException("missing message (1)");
+ }
+
+ ZZ = m1.modPow(B.getX(), B.getParams().getP()); // ZZ = (ya ^ xb) mod p
+
+ complete = true;
+ return null;
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/ElGamalSender.java b/gnu/javax/crypto/key/dh/ElGamalSender.java
new file mode 100644
index 000000000..a2de80a67
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/ElGamalSender.java
@@ -0,0 +1,134 @@
+/* ElGamalSender.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Map;
+
+import javax.crypto.interfaces.DHPublicKey;
+
+/**
+ * <p>This implementation is the sender's part of the ElGamal key agreement
+ * exchange (A in [HAC]).</p>
+ *
+ * @see ElGamalKeyAgreement
+ */
+public class ElGamalSender extends ElGamalKeyAgreement
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The recipient's public key. */
+ private DHPublicKey B;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in base class ------------------------
+
+ protected void engineInit(Map attributes) throws KeyAgreementException
+ {
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+ // One-time setup (key generation and publication). Each user B generates
+ // a keypair and publishes its public key
+ B = (DHPublicKey) attributes.get(KA_ELGAMAL_RECIPIENT_PUBLIC_KEY);
+ if (B == null)
+ {
+ throw new KeyAgreementException("missing recipient public key");
+ }
+ }
+
+ protected OutgoingMessage engineProcessMessage(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ switch (step)
+ {
+ case 0:
+ return computeSharedSecret(in);
+ default:
+ throw new IllegalStateException("unexpected state");
+ }
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private OutgoingMessage computeSharedSecret(IncomingMessage in)
+ throws KeyAgreementException
+ {
+ BigInteger p = B.getParams().getP();
+ BigInteger g = B.getParams().getG();
+ BigInteger yb = B.getY();
+
+ // A chooses a random integer x, 1 <= x <= p-2
+ // rfc-2631 restricts x to only be in [2, p-1]
+ BigInteger p_minus_2 = p.subtract(TWO);
+ byte[] xBytes = new byte[(p_minus_2.bitLength() + 7) / 8];
+ BigInteger x;
+ do
+ {
+ nextRandomBytes(xBytes);
+ x = new BigInteger(1, xBytes);
+ }
+ while (x.compareTo(TWO) >= 0 && x.compareTo(p_minus_2) <= 0);
+
+ // A sends B the message: g^x mod p
+ OutgoingMessage result = new OutgoingMessage();
+ result.writeMPI(g.modPow(x, p));
+
+ // A computes the key as K = (yb)^x mod p
+ ZZ = yb.modPow(x, p); // ZZ = (yb ^ xa) mod p
+
+ complete = true;
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/GnuDHKey.java b/gnu/javax/crypto/key/dh/GnuDHKey.java
new file mode 100644
index 000000000..e6806684e
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/GnuDHKey.java
@@ -0,0 +1,163 @@
+/* GnuDHKey.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.Registry;
+
+import java.math.BigInteger;
+import java.security.Key;
+
+import javax.crypto.interfaces.DHKey;
+import javax.crypto.spec.DHParameterSpec;
+
+/**
+ * <p>A base asbtract class for both public and private Diffie-Hellman keys. It
+ * encapsulates the two DH numbers: <code>p</code>, and <code>g</code>.</p>
+ *
+ * <p>According to the JDK, cryptographic <i>Keys</i> all have a <i>format</i>.
+ * The format used in this implementation is called <i>Raw</i>, and basically
+ * consists of the raw byte sequences of algorithm parameters. The exact order
+ * of the byte sequences and the implementation details are given in each of
+ * the relevant <code>getEncoded()</code> methods of each of the private and
+ * public keys.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
+ * Agreement Method</a><br>
+ * Eric Rescorla.</li>
+ * </ol>
+ */
+public abstract class GnuDHKey implements Key, DHKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The public prime q. A prime divisor of p-1. */
+ protected BigInteger q;
+
+ /** The public prime p. */
+ protected BigInteger p;
+
+ /** The generator g. */
+ protected BigInteger g;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial protected constructor.</p>
+ *
+ * @param q a prime divisor of p-1.
+ * @param p the public prime.
+ * @param g the generator of the group.
+ */
+ protected GnuDHKey(BigInteger q, BigInteger p, BigInteger g)
+ {
+ super();
+
+ this.q = q;
+ this.p = p;
+ this.g = g;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // javax.crypto.interfaces.DHKey interface implementation ------------------
+
+ public DHParameterSpec getParams()
+ {
+ if (q == null)
+ {
+ return new DHParameterSpec(p, g);
+ }
+ else
+ {
+ return new DHParameterSpec(p, g, q.bitLength());
+ }
+ }
+
+ // java.security.Key interface implementation ------------------------------
+
+ public String getAlgorithm()
+ {
+ return Registry.DH_KPG;
+ }
+
+ public String getFormat()
+ {
+ return null;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link DHKey} and has the same Diffie-Hellman parameter values as this
+ * one.</p>
+ *
+ * @param obj the other non-null DH key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof DHKey))
+ {
+ return false;
+ }
+ DHKey that = (DHKey) obj;
+ return p.equals(that.getParams().getP())
+ && g.equals(that.getParams().getG());
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java b/gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java
new file mode 100644
index 000000000..5502fa7bf
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java
@@ -0,0 +1,254 @@
+/* GnuDHKeyPairGenerator.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.key.IKeyPairGenerator;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.util.Map;
+
+import javax.crypto.spec.DHGenParameterSpec;
+
+/**
+ * <p>An implementation of a Diffie-Hellman keypair generator.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
+ * Agreement Method</a><br>
+ * Eric Rescorla.</li>
+ * </ol>
+ */
+public class GnuDHKeyPairGenerator implements IKeyPairGenerator
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "dh";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * Property name of an optional {@link SecureRandom} instance to use. The
+ * default is to use a classloader singleton from {@link PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dh.prng";
+
+ /**
+ * Property name of an optional {@link DHGenParameterSpec} instance to use
+ * for this generator.
+ */
+ public static final String DH_PARAMETERS = "gnu.crypto.dh.params";
+
+ /** Property name of the size in bits (Integer) of the public prime (p). */
+ public static final String PRIME_SIZE = "gnu.crypto.dh.L";
+
+ /** Property name of the size in bits (Integer) of the private exponent (x). */
+ public static final String EXPONENT_SIZE = "gnu.crypto.dh.m";
+
+ /** Default value for the size in bits of the public prime (p). */
+ // private static final int DEFAULT_PRIME_SIZE = 1024;
+ private static final int DEFAULT_PRIME_SIZE = 512;
+
+ /** Default value for the size in bits of the private exponent (x). */
+ private static final int DEFAULT_EXPONENT_SIZE = 160;
+
+ /** The SHA instance to use. */
+ private Sha160 sha = new Sha160();
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ /** The desired size in bits of the public prime (p). */
+ private int l;
+
+ /** The desired size in bits of the private exponent (x). */
+ private int m;
+
+ private BigInteger seed;
+
+ private BigInteger counter;
+
+ private BigInteger q;
+
+ private BigInteger p;
+
+ private BigInteger j;
+
+ private BigInteger g;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.keys.IKeyPairGenerator interface implementation ---------------
+
+ public String name()
+ {
+ return Registry.DH_KPG;
+ }
+
+ public void setup(Map attributes)
+ {
+ // do we have a SecureRandom, or should we use our own?
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ // are we given a set of Diffie-Hellman generation parameters or we shall
+ // use our own?
+ DHGenParameterSpec params = (DHGenParameterSpec) attributes.get(DH_PARAMETERS);
+
+ // find out the desired sizes
+ if (params != null)
+ {
+ l = params.getPrimeSize();
+ m = params.getExponentSize();
+ }
+ else
+ {
+ Integer bi = (Integer) attributes.get(PRIME_SIZE);
+ l = (bi == null ? DEFAULT_PRIME_SIZE : bi.intValue());
+ bi = (Integer) attributes.get(EXPONENT_SIZE);
+ m = (bi == null ? DEFAULT_EXPONENT_SIZE : bi.intValue());
+ }
+
+ // if ((L % 256) != 0 || L < 1024) {
+ if ((l % 256) != 0 || l < DEFAULT_PRIME_SIZE)
+ {
+ throw new IllegalArgumentException("invalid modulus size");
+ }
+ if ((m % 8) != 0 || m < DEFAULT_EXPONENT_SIZE)
+ {
+ throw new IllegalArgumentException("invalid exponent size");
+ }
+ if (m > l)
+ {
+ throw new IllegalArgumentException("exponent size > modulus size");
+ }
+ }
+
+ public KeyPair generate()
+ {
+ if (p == null)
+ {
+ BigInteger[] params = new RFC2631(m, l, rnd).generateParameters();
+ seed = params[RFC2631.DH_PARAMS_SEED];
+ counter = params[RFC2631.DH_PARAMS_COUNTER];
+ q = params[RFC2631.DH_PARAMS_Q];
+ p = params[RFC2631.DH_PARAMS_P];
+ j = params[RFC2631.DH_PARAMS_J];
+ g = params[RFC2631.DH_PARAMS_G];
+ if (DEBUG && debuglevel > 0)
+ {
+ debug("seed: 0x" + seed.toString(16));
+ debug("counter: " + counter.intValue());
+ debug("q: 0x" + q.toString(16));
+ debug("p: 0x" + p.toString(16));
+ debug("j: 0x" + j.toString(16));
+ debug("g: 0x" + g.toString(16));
+ }
+ }
+
+ // generate a private number x of length m such as: 1 < x < q - 1
+ BigInteger q_minus_1 = q.subtract(BigInteger.ONE);
+ byte[] mag = new byte[(m + 7) / 8];
+ BigInteger x;
+ while (true)
+ {
+ nextRandomBytes(mag);
+ x = new BigInteger(1, mag);
+ if (x.bitLength() == m && x.compareTo(BigInteger.ONE) > 0
+ && x.compareTo(q_minus_1) < 0)
+ {
+ break;
+ }
+ }
+ BigInteger y = g.modPow(x, p);
+
+ PrivateKey secK = new GnuDHPrivateKey(q, p, g, x);
+ PublicKey pubK = new GnuDHPublicKey(q, p, g, y);
+
+ return new KeyPair(pubK, secK);
+ }
+
+ // other methods -----------------------------------------------------------
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java b/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java
new file mode 100644
index 000000000..8b11f2c63
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java
@@ -0,0 +1,155 @@
+/* GnuDHPrivateKey.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import javax.crypto.interfaces.DHPrivateKey;
+
+/**
+ * <p>An implementation of the Diffie-Hellman private key.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
+ * Agreement Method</a><br>
+ * Eric Rescorla.</li>
+ * </ol>
+ */
+public class GnuDHPrivateKey extends GnuDHKey implements DHPrivateKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The private exponent. */
+ private final BigInteger x;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public GnuDHPrivateKey(BigInteger q, BigInteger p, BigInteger g, BigInteger x)
+ {
+ super(q, p, g);
+
+ this.x = x;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A class method that takes the output of the <code>encodePrivateKey()</code>
+ * method of a DH keypair codec object (an instance implementing
+ * {@link IKeyPairCodec} for DH keys, and re-constructs an instance of this
+ * object.</p>
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough bytes,
+ * in <code>k</code>, to represent a valid encoding of an instance of
+ * this object.
+ * @exception IllegalArgumentException if the byte sequence does not
+ * represent a valid encoding of an instance of this object.
+ */
+ public static GnuDHPrivateKey valueOf(byte[] k)
+ {
+ // check magic...
+ // we should parse here enough bytes to know which codec to use, and
+ // direct the byte array to the appropriate codec. since we only have one
+ // codec, we could have immediately tried it; nevertheless since testing
+ // one byte is cheaper than instatiating a codec that will fail we test
+ // the first byte before we carry on.
+ if (k[0] == Registry.MAGIC_RAW_DH_PRIVATE_KEY[0])
+ {
+ // it's likely to be in raw format. get a raw codec and hand it over
+ IKeyPairCodec codec = new DHKeyPairRawCodec();
+ return (GnuDHPrivateKey) codec.decodePrivateKey(k);
+ }
+ else
+ {
+ throw new IllegalArgumentException("magic");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.Key interface implementation ------------------------------
+
+ /** @deprecated see getEncoded(int). */
+ public byte[] getEncoded()
+ {
+ return getEncoded(IKeyPairCodec.RAW_FORMAT);
+ }
+
+ // javax.crypto.interfaces.DHPrivateKey interface implementation -----------
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ // other methods -----------------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this private key according to the
+ * designated format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @exception IllegalArgumentException if the format is not supported.
+ * @see gnu.crypto.key.dh.DHKeyPairRawCodec
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new DHKeyPairRawCodec().encodePrivateKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("format");
+ }
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/GnuDHPublicKey.java b/gnu/javax/crypto/key/dh/GnuDHPublicKey.java
new file mode 100644
index 000000000..5166914eb
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/GnuDHPublicKey.java
@@ -0,0 +1,155 @@
+/* GnuDHPublicKey.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+
+import javax.crypto.interfaces.DHPublicKey;
+
+/**
+ * <p>An implementation of the Diffie-Hellman public key.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
+ * Agreement Method</a><br>
+ * Eric Rescorla.</li>
+ * </ol>
+ */
+public class GnuDHPublicKey extends GnuDHKey implements DHPublicKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private BigInteger y;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public GnuDHPublicKey(BigInteger q, BigInteger p, BigInteger g, BigInteger y)
+ {
+ super(q, p, g);
+
+ this.y = y;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A class method that takes the output of the <code>encodePublicKey()</code>
+ * method of a DH keypair codec object (an instance implementing
+ * {@link IKeyPairCodec} for DSS keys, and re-constructs an instance of this
+ * object.</p>
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough bytes,
+ * in <code>k</code>, to represent a valid encoding of an instance of this
+ * object.
+ * @exception IllegalArgumentException if the byte sequence does not
+ * represent a valid encoding of an instance of this object.
+ */
+ public static GnuDHPublicKey valueOf(byte[] k)
+ {
+ // check magic...
+ // we should parse here enough bytes to know which codec to use, and
+ // direct the byte array to the appropriate codec. since we only have one
+ // codec, we could have immediately tried it; nevertheless since testing
+ // one byte is cheaper than instatiating a codec that will fail we test
+ // the first byte before we carry on.
+ if (k[0] == Registry.MAGIC_RAW_DH_PUBLIC_KEY[0])
+ {
+ // it's likely to be in raw format. get a raw codec and hand it over
+ IKeyPairCodec codec = new DHKeyPairRawCodec();
+ return (GnuDHPublicKey) codec.decodePublicKey(k);
+ }
+ else
+ {
+ throw new IllegalArgumentException("magic");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.Key interface implementation ------------------------------
+
+ /** @deprecated see getEncoded(int). */
+ public byte[] getEncoded()
+ {
+ return getEncoded(IKeyPairCodec.RAW_FORMAT);
+ }
+
+ // javax.crypto.interfaces.DHPublicKey interface implementation ------------
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ // other methods -----------------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this public key according to the designated
+ * format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @exception IllegalArgumentException if the format is not supported.
+ * @see gnu.crypto.key.dh.DHKeyPairRawCodec
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new DHKeyPairRawCodec().encodePublicKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("format");
+ }
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/key/dh/RFC2631.java b/gnu/javax/crypto/key/dh/RFC2631.java
new file mode 100644
index 000000000..656253de1
--- /dev/null
+++ b/gnu/javax/crypto/key/dh/RFC2631.java
@@ -0,0 +1,245 @@
+/* RFC2631.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.dh;
+
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.util.Prime2;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * <p>An implementation of the Diffie-Hellman parameter generation as defined in
+ * RFC-2631.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
+ * Agreement Method</a><br>
+ * Eric Rescorla.</li>
+ * </ol>
+ */
+public class RFC2631
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int DH_PARAMS_SEED = 0;
+
+ public static final int DH_PARAMS_COUNTER = 1;
+
+ public static final int DH_PARAMS_Q = 2;
+
+ public static final int DH_PARAMS_P = 3;
+
+ public static final int DH_PARAMS_J = 4;
+
+ public static final int DH_PARAMS_G = 5;
+
+ private static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ /** The SHA instance to use. */
+ private Sha160 sha = new Sha160();
+
+ /** Length of private modulus and of q. */
+ private int m;
+
+ /** Length of public modulus p. */
+ private int L;
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RFC2631(int m, int L, SecureRandom rnd)
+ {
+ super();
+
+ this.m = m;
+ this.L = L;
+ this.rnd = rnd;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public BigInteger[] generateParameters()
+ {
+ int i, j, counter;
+ byte[] u1, u2, v;
+ byte[] seedBytes = new byte[m / 8];
+ BigInteger SEED, U, q, R, V, W, X, p, g;
+ // start by genrating p and q, where q is of length m and p is of length L
+ // 1. Set m' = m/160 where / represents integer division with rounding
+ // upwards. I.e. 200/160 = 2.
+ int m_ = (m + 159) / 160;
+ // 2. Set L'= L/160
+ int L_ = (L + 159) / 160;
+ // 3. Set N'= L/1024
+ int N_ = (L + 1023) / 1024;
+ algorithm: while (true)
+ {
+ step4: while (true)
+ {
+ // 4. Select an arbitrary bit string SEED such that length of SEED >= m
+ nextRandomBytes(seedBytes);
+ SEED = new BigInteger(1, seedBytes).setBit(m - 1).setBit(0);
+ // 5. Set U = 0
+ U = BigInteger.ZERO;
+ // 6. For i = 0 to m' - 1
+ // U = U + (SHA1[SEED + i] XOR SHA1[(SEED + m' + i)) * 2^(160 * i)
+ // Note that for m=160, this reduces to the algorithm of [FIPS-186]
+ // U = SHA1[SEED] XOR SHA1[(SEED+1) mod 2^160 ].
+ for (i = 0; i < m_; i++)
+ {
+ u1 = SEED.add(BigInteger.valueOf(i)).toByteArray();
+ u2 = SEED.add(BigInteger.valueOf(m_ + i)).toByteArray();
+ sha.update(u1, 0, u1.length);
+ u1 = sha.digest();
+ sha.update(u2, 0, u2.length);
+ u2 = sha.digest();
+ for (j = 0; j < u1.length; j++)
+ {
+ u1[j] ^= u2[j];
+ }
+ U = U.add(new BigInteger(1, u1).multiply(TWO.pow(160 * i)));
+ }
+ // 5. Form q from U by computing U mod (2^m) and setting the most
+ // significant bit (the 2^(m-1) bit) and the least significant bit to
+ // 1. In terms of boolean operations, q = U OR 2^(m-1) OR 1. Note
+ // that 2^(m-1) < q < 2^m
+ q = U.setBit(m - 1).setBit(0);
+ // 6. Use a robust primality algorithm to test whether q is prime.
+ // 7. If q is not prime then go to 4.
+ if (Prime2.isProbablePrime(q))
+ {
+ break step4;
+ }
+ }
+ // 8. Let counter = 0
+ counter = 0;
+ step9: while (true)
+ {
+ // 9. Set R = seed + 2*m' + (L' * counter)
+ R = SEED.add(BigInteger.valueOf(2 * m_)).add(
+ BigInteger.valueOf(L_
+ * counter));
+ // 10. Set V = 0
+ V = BigInteger.ZERO;
+ // 12. For i = 0 to L'-1 do: V = V + SHA1(R + i) * 2^(160 * i)
+ for (i = 0; i < L_; i++)
+ {
+ v = R.toByteArray();
+ sha.update(v, 0, v.length);
+ v = sha.digest();
+ V = V.add(new BigInteger(1, v).multiply(TWO.pow(160 * i)));
+ }
+ // 13. Set W = V mod 2^L
+ W = V.mod(TWO.pow(L));
+ // 14. Set X = W OR 2^(L-1)
+ // Note that 0 <= W < 2^(L-1) and hence X >= 2^(L-1)
+ X = W.setBit(L - 1);
+ // 15. Set p = X - (X mod (2*q)) + 1
+ p = X.add(BigInteger.ONE).subtract(X.mod(TWO.multiply(q)));
+ // 16. If p > 2^(L-1) use a robust primality test to test whether p is
+ // prime. Else go to 18.
+ //17. If p is prime output p, q, seed, counter and stop.
+ if (Prime2.isProbablePrime(p))
+ {
+ break algorithm;
+ }
+ // 18. Set counter = counter + 1
+ counter++;
+ // 19. If counter < (4096 * N) then go to 8.
+ // 20. Output "failure"
+ if (counter >= 4096 * N_)
+ {
+ continue algorithm;
+ }
+ }
+ }
+
+ // compute g. from FIPS-186, Appendix 4:
+ // 1. Generate p and q as specified in Appendix 2.
+ // 2. Let e = (p - 1) / q
+ BigInteger e = p.subtract(BigInteger.ONE).divide(q);
+ BigInteger h = TWO;
+ BigInteger p_minus_1 = p.subtract(BigInteger.ONE);
+ g = TWO;
+ // 3. Set h = any integer, where 1 < h < p - 1 and h differs from any
+ // value previously tried
+ for (; h.compareTo(p_minus_1) < 0; h = h.add(BigInteger.ONE))
+ {
+ // 4. Set g = h**e mod p
+ g = h.modPow(e, p);
+ // 5. If g = 1, go to step 3
+ if (!g.equals(BigInteger.ONE))
+ {
+ break;
+ }
+ }
+
+ return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g };
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRP6Host.java b/gnu/javax/crypto/key/srp6/SRP6Host.java
new file mode 100644
index 000000000..192e877b7
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRP6Host.java
@@ -0,0 +1,213 @@
+/* SRP6Host.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+import gnu.javax.crypto.sasl.srp.SRP;
+import gnu.javax.crypto.sasl.srp.SRPAuthInfoProvider;
+import gnu.javax.crypto.sasl.srp.SRPRegistry;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>The implementation of the Host in the SRP-6 key agreement protocol.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRP6Host extends SRP6KeyAgreement
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The user's ephemeral key pair. */
+ private KeyPair hostKeyPair;
+
+ /** The SRP password database. */
+ private SRPAuthInfoProvider passwordDB;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in base class ------------------------
+
+ protected void engineInit(final Map attributes) throws KeyAgreementException
+ {
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+ N = (BigInteger) attributes.get(SHARED_MODULUS);
+ if (N == null)
+ {
+ throw new KeyAgreementException("missing shared modulus");
+ }
+ g = (BigInteger) attributes.get(GENERATOR);
+ if (g == null)
+ {
+ throw new KeyAgreementException("missing generator");
+ }
+
+ final String md = (String) attributes.get(HASH_FUNCTION);
+ if (md == null || "".equals(md.trim()))
+ {
+ throw new KeyAgreementException("missing hash function");
+ }
+ srp = SRP.instance(md);
+
+ passwordDB = (SRPAuthInfoProvider) attributes.get(HOST_PASSWORD_DB);
+ if (passwordDB == null)
+ {
+ throw new KeyAgreementException("missing SRP password database");
+ }
+ }
+
+ protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ switch (step)
+ {
+ case 0:
+ return computeSharedSecret(in);
+ default:
+ throw new IllegalStateException("unexpected state");
+ }
+ }
+
+ protected void engineReset()
+ {
+ hostKeyPair = null;
+ super.engineReset();
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private OutgoingMessage computeSharedSecret(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ final String I = in.readString();
+ final BigInteger A = in.readMPI();
+
+ // get s and v for user identified by I
+ // ----------------------------------------------------------------------
+ final Map credentials;
+ try
+ {
+ final Map userID = new HashMap();
+ userID.put(Registry.SASL_USERNAME, I);
+ userID.put(SRPRegistry.MD_NAME_FIELD, srp.getAlgorithm());
+ credentials = passwordDB.lookup(userID);
+ }
+ catch (IOException x)
+ {
+ throw new KeyAgreementException("computeSharedSecret()", x);
+ }
+
+ final BigInteger s = new BigInteger(
+ 1,
+ Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD)));
+ final BigInteger v = new BigInteger(
+ 1,
+ Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD)));
+
+ // Map configuration = null;
+ // try {
+ // String mode = (String) credentials.get(SRPRegistry.CONFIG_NDX_FIELD);
+ // configuration = passwordDB.getConfiguration(mode);
+ // } catch (IOException x) {
+ // throw new KeyAgreementException("computeSharedSecret()", x);
+ // }
+ //
+ // BigInteger N = new BigInteger(1, Util.fromBase64(
+ // (String) configuration.get(SRPRegistry.SHARED_MODULUS)));
+ // BigInteger g = new BigInteger(1, Util.fromBase64(
+ // (String) configuration.get(SRPRegistry.FIELD_GENERATOR)));
+ // ----------------------------------------------------------------------
+
+ final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
+ final Map attributes = new HashMap();
+ if (rnd != null)
+ {
+ attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
+ }
+ attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
+ attributes.put(SRPKeyPairGenerator.GENERATOR, g);
+ attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v);
+ kpg.setup(attributes);
+ hostKeyPair = kpg.generate();
+
+ final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
+ final BigInteger u = uValue(A, B); // u = H(A | B)
+
+ // compute S = (Av^u) ^ b
+ final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX();
+ final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N);
+
+ final byte[] sBytes = Util.trim(S);
+ final IMessageDigest hash = srp.newDigest();
+ hash.update(sBytes, 0, sBytes.length);
+ K = new BigInteger(1, hash.digest());
+
+ final OutgoingMessage result = new OutgoingMessage();
+ result.writeMPI(s);
+ result.writeMPI(B);
+
+ complete = true;
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java b/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java
new file mode 100644
index 000000000..63c981d80
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java
@@ -0,0 +1,172 @@
+/* SRP6KeyAgreement.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.key.BaseKeyAgreementParty;
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.sasl.srp.SRP;
+
+import java.math.BigInteger;
+
+/**
+ * <p>The Secure Remote Password (SRP) key agreement protocol, also known as
+ * SRP-6, is designed by Thomas J. Wu (see references). The protocol, and its
+ * elements are described as follows:</p>
+ *
+ * <pre>
+ * N A large safe prime (N = 2q+1, where q is prime)
+ * All arithmetic is done modulo N.
+ * g A generator modulo N
+ * s User's salt
+ * I Username
+ * p Cleartext Password
+ * H() One-way hash function
+ * ^ (Modular) Exponentiation
+ * u Random scrambling parameter
+ * a,b Secret ephemeral values
+ * A,B Public ephemeral values
+ * x Private key (derived from p and s)
+ * v Password verifier
+ *
+ * The host stores passwords using the following formula:
+ * x = H(s | H(I ":" p)) (s is chosen randomly)
+ * v = g^x (computes password verifier)
+ *
+ * The host then keeps {I, s, v} in its password database.
+ *
+ * The authentication protocol itself goes as follows:
+ * User -> Host: I, A = g^a (identifies self, a = random number)
+ * Host -> User: s, B = 3v + g^b (sends salt, b = random number)
+ *
+ * Both: u = H(A, B)
+ *
+ * User: x = H(s, p) (user enters password)
+ * User: S = (B - 3g^x) ^ (a + ux) (computes session key)
+ * User: K = H(S)
+ *
+ * Host: S = (Av^u) ^ b (computes session key)
+ * Host: K = H(S)
+ * </pre>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public abstract class SRP6KeyAgreement extends BaseKeyAgreementParty
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp6.ka.prng";
+
+ public static final String SHARED_MODULUS = "gnu.crypto.srp6.ka.N";
+
+ public static final String GENERATOR = "gnu.crypto.srp6.ka.g";
+
+ public static final String HASH_FUNCTION = "gnu.crypto.srp6.ka.H";
+
+ public static final String USER_IDENTITY = "gnu.crypto.srp6.ka.I";
+
+ public static final String USER_PASSWORD = "gnu.crypto.srp6.ka.p";
+
+ public static final String HOST_PASSWORD_DB = "gnu.crypto.srp6.ka.password.db";
+
+ protected static final BigInteger THREE = BigInteger.valueOf(3L);
+
+ protected SRP srp;
+
+ protected BigInteger N;
+
+ protected BigInteger g;
+
+ /** The shared secret key. */
+ protected BigInteger K;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected SRP6KeyAgreement()
+ {
+ super(Registry.SRP6_KA);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of common abstract methods in BaseKeyAGreementParty ------
+
+ protected byte[] engineSharedSecret() throws KeyAgreementException
+ {
+ return Util.trim(K);
+ }
+
+ protected void engineReset()
+ {
+ // mda = null;
+ srp = null;
+ N = null;
+ g = null;
+ K = null;
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ protected BigInteger uValue(final BigInteger A, final BigInteger B)
+ {
+ // IMessageDigest hash = (IMessageDigest) mda.clone();
+ final IMessageDigest hash = srp.newDigest();
+ byte[] b;
+ b = Util.trim(A);
+ hash.update(b, 0, b.length);
+ b = Util.trim(B);
+ hash.update(b, 0, b.length);
+
+ return new BigInteger(1, hash.digest());
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRP6SaslClient.java b/gnu/javax/crypto/key/srp6/SRP6SaslClient.java
new file mode 100644
index 000000000..ef460b13b
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRP6SaslClient.java
@@ -0,0 +1,101 @@
+/* SRP6SaslClient.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+
+import java.math.BigInteger;
+
+/**
+ * <p>A variation of the SRP-6 protocol as used in the SASL-SRP mechanism, for
+ * the User (client side).</p>
+ *
+ * <p>In this alternative, the exchange goes as follows:</p>
+ * <pre>
+ * C -> S: I (identifies self)
+ * S -> C: N, g, s, B = 3v + g^b (sends salt, b = random number)
+ * C -> S: A = g^a (a = random number)
+ * </pre>
+ *
+ * <p>All elements are computed the same way as in the standard version.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
+ * Secure Remote Password Authentication Mechanism</a><br>
+ * K. Burdis, R. Naffah.</li>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRP6SaslClient extends SRP6TLSClient
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ final OutgoingMessage result = super.computeSharedSecret(in);
+
+ final byte[] sBytes = Util.trim(K);
+ final IMessageDigest hash = srp.newDigest();
+ hash.update(sBytes, 0, sBytes.length);
+ K = new BigInteger(1, hash.digest());
+
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRP6SaslServer.java b/gnu/javax/crypto/key/srp6/SRP6SaslServer.java
new file mode 100644
index 000000000..5e759964e
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRP6SaslServer.java
@@ -0,0 +1,101 @@
+/* SRP6SaslServer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+
+import java.math.BigInteger;
+
+/**
+ * <p>A variation of the SRP-6 protocol as used in the SASL-SRP mechanism, for
+ * the Host (server side).</p>
+ *
+ * <p>In this alternative, the exchange goes as follows:</p>
+ * <pre>
+ * C -> S: I (identifies self)
+ * S -> C: N, g, s, B = 3v + g^b (sends salt, b = random number)
+ * C -> S: A = g^a (a = random number)
+ * </pre>
+ *
+ * <p>All elements are computed the same way as in the standard version.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
+ * Secure Remote Password Authentication Mechanism</a><br>
+ * K. Burdis, R. Naffah.</li>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRP6SaslServer extends SRP6TLSServer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ super.computeSharedSecret(in);
+
+ final byte[] sBytes = Util.trim(K);
+ final IMessageDigest hash = srp.newDigest();
+ hash.update(sBytes, 0, sBytes.length);
+ K = new BigInteger(1, hash.digest());
+
+ return null;
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRP6TLSClient.java b/gnu/javax/crypto/key/srp6/SRP6TLSClient.java
new file mode 100644
index 000000000..5474a1e8e
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRP6TLSClient.java
@@ -0,0 +1,191 @@
+/* SRP6TLSClient.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+import gnu.javax.crypto.sasl.srp.SRP;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>A variation of the SRP6 key agreement protocol, for the client-side as
+ * proposed in
+ * <a href="http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-05.txt">Using
+ * SRP for TLS Authentication</a>. The only difference between it and the SASL
+ * variant is that the shared secret is the entity <code>S</code> and not
+ * <code>H(S)</code>.</p>
+ */
+public class SRP6TLSClient extends SRP6KeyAgreement
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The user's identity. */
+ private String I;
+
+ /** The user's cleartext password. */
+ private byte[] p;
+
+ /** The user's ephemeral key pair. */
+ private KeyPair userKeyPair;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in base class ------------------------
+
+ protected void engineInit(final Map attributes) throws KeyAgreementException
+ {
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ final String md = (String) attributes.get(HASH_FUNCTION);
+ if (md == null || "".equals(md.trim()))
+ {
+ throw new KeyAgreementException("missing hash function");
+ }
+ srp = SRP.instance(md);
+
+ I = (String) attributes.get(USER_IDENTITY);
+ if (I == null)
+ {
+ throw new KeyAgreementException("missing user identity");
+ }
+ p = (byte[]) attributes.get(USER_PASSWORD);
+ if (p == null)
+ {
+ throw new KeyAgreementException("missing user password");
+ }
+ }
+
+ protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ switch (step)
+ {
+ case 0:
+ return sendIdentity(in);
+ case 1:
+ return computeSharedSecret(in);
+ default:
+ throw new IllegalStateException("unexpected state");
+ }
+ }
+
+ protected void engineReset()
+ {
+ I = null;
+ p = null;
+ userKeyPair = null;
+ super.engineReset();
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private OutgoingMessage sendIdentity(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ final OutgoingMessage result = new OutgoingMessage();
+ result.writeString(I);
+
+ return result;
+ }
+
+ protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ N = in.readMPI();
+ g = in.readMPI();
+ final BigInteger s = in.readMPI();
+ final BigInteger B = in.readMPI();
+
+ // generate an ephemeral keypair
+ final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
+ final Map attributes = new HashMap();
+ if (rnd != null)
+ {
+ attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
+ }
+ attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
+ attributes.put(SRPKeyPairGenerator.GENERATOR, g);
+ kpg.setup(attributes);
+ userKeyPair = kpg.generate();
+
+ final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY();
+ final BigInteger u = uValue(A, B); // u = H(A | B)
+ final BigInteger x;
+ try
+ {
+ x = new BigInteger(1, srp.computeX(Util.trim(s), I, p));
+ }
+ catch (Exception e)
+ {
+ throw new KeyAgreementException("computeSharedSecret()", e);
+ }
+
+ // compute S = (B - 3g^x) ^ (a + ux)
+ final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX();
+ final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N))).modPow(
+ a.add(u.multiply(x)),
+ N);
+
+ K = S;
+
+ final OutgoingMessage result = new OutgoingMessage();
+ result.writeMPI(A);
+
+ complete = true;
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRP6TLSServer.java b/gnu/javax/crypto/key/srp6/SRP6TLSServer.java
new file mode 100644
index 000000000..23e444077
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRP6TLSServer.java
@@ -0,0 +1,220 @@
+/* SRP6TLSServer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.OutgoingMessage;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.sasl.srp.SRP;
+import gnu.javax.crypto.sasl.srp.SRPAuthInfoProvider;
+import gnu.javax.crypto.sasl.srp.SRPRegistry;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>A variation of the SRP6 key agreement protocol, for the server-side as
+ * proposed in
+ * <a href="http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-05.txt">Using
+ * SRP for TLS Authentication</a>. The only difference between it and the SASL
+ * variant is that the shared secret is the entity <code>S</code> and not
+ * <code>H(S)</code>.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class SRP6TLSServer extends SRP6KeyAgreement
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The user's ephemeral key pair. */
+ private KeyPair hostKeyPair;
+
+ /** The SRP password database. */
+ private SRPAuthInfoProvider passwordDB;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in base class ------------------------
+
+ protected void engineInit(final Map attributes) throws KeyAgreementException
+ {
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ final String md = (String) attributes.get(HASH_FUNCTION);
+ if (md == null || "".equals(md.trim()))
+ {
+ throw new KeyAgreementException("missing hash function");
+ }
+ srp = SRP.instance(md);
+
+ passwordDB = (SRPAuthInfoProvider) attributes.get(HOST_PASSWORD_DB);
+ if (passwordDB == null)
+ {
+ throw new KeyAgreementException("missing SRP password database");
+ }
+ }
+
+ protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ switch (step)
+ {
+ case 0:
+ return sendParameters(in);
+ case 1:
+ return computeSharedSecret(in);
+ default:
+ throw new IllegalStateException("unexpected state");
+ }
+ }
+
+ protected void engineReset()
+ {
+ hostKeyPair = null;
+ super.engineReset();
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private OutgoingMessage sendParameters(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ final String I = in.readString();
+
+ // get s and v for user identified by I
+ // ----------------------------------------------------------------------
+ final Map credentials;
+ try
+ {
+ final Map userID = new HashMap();
+ userID.put(Registry.SASL_USERNAME, I);
+ userID.put(SRPRegistry.MD_NAME_FIELD, srp.getAlgorithm());
+ credentials = passwordDB.lookup(userID);
+ }
+ catch (IOException x)
+ {
+ throw new KeyAgreementException("computeSharedSecret()", x);
+ }
+
+ final BigInteger s = new BigInteger(
+ 1,
+ Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD)));
+ final BigInteger v = new BigInteger(
+ 1,
+ Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD)));
+
+ final Map configuration;
+ try
+ {
+ final String mode = (String) credentials.get(SRPRegistry.CONFIG_NDX_FIELD);
+ configuration = passwordDB.getConfiguration(mode);
+ }
+ catch (IOException x)
+ {
+ throw new KeyAgreementException("computeSharedSecret()", x);
+ }
+
+ N = new BigInteger(
+ 1,
+ Util.fromBase64((String) configuration.get(SRPRegistry.SHARED_MODULUS)));
+ g = new BigInteger(
+ 1,
+ Util.fromBase64((String) configuration.get(SRPRegistry.FIELD_GENERATOR)));
+ // ----------------------------------------------------------------------
+
+ // generate an ephemeral keypair
+ final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
+ final Map attributes = new HashMap();
+ if (rnd != null)
+ {
+ attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
+ }
+ attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
+ attributes.put(SRPKeyPairGenerator.GENERATOR, g);
+ attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v);
+ kpg.setup(attributes);
+ hostKeyPair = kpg.generate();
+
+ final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
+
+ final OutgoingMessage result = new OutgoingMessage();
+ result.writeMPI(N);
+ result.writeMPI(g);
+ result.writeMPI(s);
+ result.writeMPI(B);
+
+ return result;
+ }
+
+ protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ final BigInteger A = in.readMPI();
+
+ final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
+ final BigInteger u = uValue(A, B); // u = H(A | B)
+
+ // compute S = (Av^u) ^ b
+ final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX();
+ final BigInteger v = ((SRPPrivateKey) hostKeyPair.getPrivate()).getV();
+ final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N);
+
+ K = S;
+
+ complete = true;
+ return null;
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRP6User.java b/gnu/javax/crypto/key/srp6/SRP6User.java
new file mode 100644
index 000000000..d300d6f76
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRP6User.java
@@ -0,0 +1,203 @@
+/* SRP6User.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.OutgoingMessage;
+import gnu.javax.crypto.sasl.srp.SRP;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>The implementation of the User in the SRP-6 protocol.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRP6User extends SRP6KeyAgreement
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The user's identity. */
+ private String I;
+
+ /** The user's cleartext password. */
+ private byte[] p;
+
+ /** The user's ephemeral key pair. */
+ private KeyPair userKeyPair;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in base class ------------------------
+
+ protected void engineInit(final Map attributes) throws KeyAgreementException
+ {
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+ N = (BigInteger) attributes.get(SHARED_MODULUS);
+ if (N == null)
+ {
+ throw new KeyAgreementException("missing shared modulus");
+ }
+ g = (BigInteger) attributes.get(GENERATOR);
+ if (g == null)
+ {
+ throw new KeyAgreementException("missing generator");
+ }
+
+ final String md = (String) attributes.get(HASH_FUNCTION);
+ if (md == null || "".equals(md.trim()))
+ {
+ throw new KeyAgreementException("missing hash function");
+ }
+ srp = SRP.instance(md);
+
+ I = (String) attributes.get(USER_IDENTITY);
+ if (I == null)
+ {
+ throw new KeyAgreementException("missing user identity");
+ }
+ p = (byte[]) attributes.get(USER_PASSWORD);
+ if (p == null)
+ {
+ throw new KeyAgreementException("missing user password");
+ }
+ }
+
+ protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ switch (step)
+ {
+ case 0:
+ return sendIdentity(in);
+ case 1:
+ return computeSharedSecret(in);
+ default:
+ throw new IllegalStateException("unexpected state");
+ }
+ }
+
+ protected void engineReset()
+ {
+ I = null;
+ p = null;
+ userKeyPair = null;
+ super.engineReset();
+ }
+
+ // own methods -------------------------------------------------------------
+
+ private OutgoingMessage sendIdentity(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ // generate an ephemeral keypair
+ final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
+ final Map attributes = new HashMap();
+ if (rnd != null)
+ {
+ attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
+ }
+ attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
+ attributes.put(SRPKeyPairGenerator.GENERATOR, g);
+ kpg.setup(attributes);
+ userKeyPair = kpg.generate();
+
+ final OutgoingMessage result = new OutgoingMessage();
+ result.writeString(I);
+ result.writeMPI(((SRPPublicKey) userKeyPair.getPublic()).getY());
+
+ return result;
+ }
+
+ private OutgoingMessage computeSharedSecret(final IncomingMessage in)
+ throws KeyAgreementException
+ {
+ final BigInteger s = in.readMPI();
+ final BigInteger B = in.readMPI();
+
+ final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY();
+ final BigInteger u = uValue(A, B); // u = H(A | B)
+
+ final BigInteger x;
+ try
+ {
+ x = new BigInteger(1, srp.computeX(Util.trim(s), I, p));
+ }
+ catch (Exception e)
+ {
+ throw new KeyAgreementException("computeSharedSecret()", e);
+ }
+
+ // compute S = (B - 3g^x) ^ (a + ux)
+ final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX();
+ final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N))).modPow(
+ a.add(u.multiply(x)),
+ N);
+
+ final byte[] sBytes = Util.trim(S);
+ final IMessageDigest hash = srp.newDigest();
+ hash.update(sBytes, 0, sBytes.length);
+ K = new BigInteger(1, hash.digest());
+
+ complete = true;
+ return null;
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRPAlgorithm.java b/gnu/javax/crypto/key/srp6/SRPAlgorithm.java
new file mode 100644
index 000000000..b068863ed
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRPAlgorithm.java
@@ -0,0 +1,175 @@
+/* SRPAlgorithm.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.util.Prime2;
+import gnu.javax.crypto.sasl.srp.SRPRegistry;
+
+import java.math.BigInteger;
+
+/**
+ * <p>Utilities for use with SRP-6 based methods and protocols.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRPAlgorithm
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // lifted from draft-burdis-cat-srp-sasl-09
+ public static final BigInteger N_2048 = new BigInteger(
+ "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050"
+ + "A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50"
+ + "E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B8"
+ + "55F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773B"
+ + "CA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748"
+ + "544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6"
+ + "AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6"
+ + "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73",
+ 16);
+
+ public static final BigInteger N_1536 = new BigInteger(
+ "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D"
+ + "5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DC"
+ + "DF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC"
+ + "764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C486"
+ + "65772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E"
+ + "5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB",
+ 16);
+
+ public static final BigInteger N_1280 = new BigInteger(
+ "D77946826E811914B39401D56A0A7843A8E7575D738C672A090AB1187D690DC4"
+ + "3872FC06A7B6A43F3B95BEAEC7DF04B9D242EBDC481111283216CE816E004B78"
+ + "6C5FCE856780D41837D95AD787A50BBE90BD3A9C98AC0F5FC0DE744B1CDE1891"
+ + "690894BC1F65E00DE15B4B2AA6D87100C9ECC2527E45EB849DEB14BB2049B163"
+ + "EA04187FD27C1BD9C7958CD40CE7067A9C024F9B7C5A0B4F5003686161F0605B",
+ 16);
+
+ public static final BigInteger N_1024 = new BigInteger(
+ "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576"
+ + "D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD1"
+ + "5DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC"
+ + "68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3",
+ 16);
+
+ public static final BigInteger N_768 = new BigInteger(
+ "B344C7C4F8C495031BB4E04FF8F84EE95008163940B9558276744D91F7CC9F40"
+ + "2653BE7147F00F576B93754BCDDF71B636F2099E6FFF90E79575F3D0DE694AFF"
+ + "737D9BE9713CEF8D837ADA6380B1093E94B6A529A8C6C2BE33E0867C60C3262B",
+ 16);
+
+ public static final BigInteger N_640 = new BigInteger(
+ "C94D67EB5B1A2346E8AB422FC6A0EDAEDA8C7F894C9EEEC42F9ED250FD7F0046"
+ + "E5AF2CF73D6B2FA26BB08033DA4DE322E144E7A8E9B12A0E4637F6371F34A207"
+ + "1C4B3836CBEEAB15034460FAA7ADF483",
+ 16);
+
+ public static final BigInteger N_512 = new BigInteger(
+ "D4C7F8A2B32C11B8FBA9581EC4BA4F1B04215642EF7355E37C0FC0443EF756EA"
+ + "2C6B8EEB755A1C723027663CAA265EF785B8FF6A9B35227A52D86633DBDFCA43",
+ 16);
+
+ public static final BigInteger N_384 = new BigInteger(
+ "8025363296FB943FCE54BE717E0E2958A02A9672EF561953B2BAA3BAACC3ED57"
+ + "54EB764C7AB7184578C57D5949CCB41B",
+ 16);
+
+ public static final BigInteger N_264 = new BigInteger(
+ "115B8B692E0E045692CF280B436735C77A5A9E8A9E7ED56C965F87DB5B2A2ECE3",
+ 16);
+
+ private static final BigInteger ZERO = BigInteger.ZERO;
+
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ private static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce usage through class methods. */
+ private SRPAlgorithm()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static void checkParams(final BigInteger N, final BigInteger g)
+ {
+ // 1. N should be at least 512-bit long
+ final int blen = N.bitLength();
+ if (blen < SRPRegistry.MINIMUM_MODULUS_BITLENGTH)
+ {
+ throw new IllegalArgumentException(
+ "Bit length of N ("
+ + blen
+ + ") is too low. Should be at least "
+ + SRPRegistry.MINIMUM_MODULUS_BITLENGTH);
+ }
+ // 2. N should be a prime
+ if (!Prime2.passEulerCriterion(N))
+ {
+ throw new IllegalArgumentException("N should be prime but isn't");
+ }
+ // 3. N should be of the form 2*q + 1, where q is prime
+ final BigInteger q = N.subtract(ONE).divide(TWO);
+ if (!Prime2.passEulerCriterion(q))
+ {
+ throw new IllegalArgumentException("(N-1)/2 should be prime but isn't");
+ }
+ // 4. g**q should be -1 mod N
+ final BigInteger gq = g.modPow(q, N).add(ONE).mod(N);
+ if (gq.compareTo(ZERO) != 0)
+ {
+ throw new IllegalArgumentException(
+ "g**q should be -1 (mod N) but isn't");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/javax/crypto/key/srp6/SRPKey.java b/gnu/javax/crypto/key/srp6/SRPKey.java
new file mode 100644
index 000000000..79f4f07bc
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRPKey.java
@@ -0,0 +1,170 @@
+/* SRPKey.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.security.Key;
+
+/**
+ * <p>An abstract representation of a base SRP ephemeral key.</p>
+ *
+ * <p>This object encapsulates the two numbers:</p>
+ * <ul>
+ * <li><b>N</b>: A large safe prime (N = 2q+1, where q is prime).</li>
+ * <li><b>g</b>: A generator modulo N.</li>
+ * </ul>
+ *
+ * <p>Note that in SRP, all arithmetic is done modulo N.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public abstract class SRPKey implements Key, Serializable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The public, Germaine prime, shared modulus. */
+ protected final BigInteger N;
+
+ /** The generator. */
+ protected final BigInteger g;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected SRPKey(BigInteger N, BigInteger g)
+ {
+ super();
+
+ this.N = N;
+ this.g = g;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.Key interface implementation ------------------------------
+
+ /**
+ * <p>Returns the standard algorithm name for this key.</p>
+ *
+ * @return the standard algorithm name for this key.
+ */
+ public String getAlgorithm()
+ {
+ return Registry.SRP_KPG;
+ }
+
+ /** @deprecated see getEncoded(int). */
+ public byte[] getEncoded()
+ {
+ return getEncoded(IKeyPairCodec.RAW_FORMAT);
+ }
+
+ /**
+ * <p>Returns <code>null</code> since this implementation does not encode SRP
+ * keys.</p>
+ *
+ * @return null since this implementation does not encode SRP keys.
+ */
+ public String getFormat()
+ {
+ return null;
+ }
+
+ // other methods -----------------------------------------------------------
+
+ /**
+ * <p>Returns the public shared modulus.</p>
+ *
+ * @return <code>N</code>.
+ */
+ public BigInteger getN()
+ {
+ return N;
+ }
+
+ /**
+ * <p>Returns the generator.</p>
+ *
+ * @return <code>g</code>.
+ */
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * <code>SRPKey</code> and has the same SRP parameter values as this one.</p>
+ *
+ * @param obj the other non-null SRP key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof SRPKey))
+ {
+ return false;
+ }
+ SRPKey that = (SRPKey) obj;
+ return N.equals(that.getN()) && g.equals(that.getG());
+ }
+
+ // abstract methods to be implemented by subclasses ------------------------
+
+ public abstract byte[] getEncoded(int format);
+}
diff --git a/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java b/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java
new file mode 100644
index 000000000..3c8baaa7a
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java
@@ -0,0 +1,341 @@
+/* SRPKeyPairGenerator.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairGenerator;
+import gnu.java.security.util.Prime2;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.SecureRandom;
+import java.util.Map;
+
+/**
+ *
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRPKeyPairGenerator implements IKeyPairGenerator
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "srp";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final BigInteger ZERO = BigInteger.ZERO;
+
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ private static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ private static final BigInteger THREE = BigInteger.valueOf(3L);
+
+ /** Property name of the length (Integer) of the modulus (N) of an SRP key. */
+ public static final String MODULUS_LENGTH = "gnu.crypto.srp.L";
+
+ /** Property name of the Boolean indicating wether or not to use defaults. */
+ public static final String USE_DEFAULTS = "gnu.crypto.srp.use.defaults";
+
+ /** Property name of the modulus (N) of an SRP key. */
+ public static final String SHARED_MODULUS = "gnu.crypto.srp.N";
+
+ /** Property name of the generator (g) of an SRP key. */
+ public static final String GENERATOR = "gnu.crypto.srp.g";
+
+ /** Property name of the user's verifier (v) for a Server SRP key. */
+ public static final String USER_VERIFIER = "gnu.crypto.srp.v";
+
+ /**
+ * Property name of an optional {@link SecureRandom} instance to use. The
+ * default is to use a classloader singleton from {@link PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp.prng";
+
+ /** Default value for the modulus length. */
+ private static final int DEFAULT_MODULUS_LENGTH = 1024;
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ /** Bit length of the shared modulus. */
+ private int l;
+
+ /** The shared public modulus. */
+ private BigInteger N;
+
+ /** The Field generator. */
+ private BigInteger g;
+
+ /** The user's verifier MPI. */
+ private BigInteger v;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
+
+ public String name()
+ {
+ return Registry.SRP_KPG;
+ }
+
+ public void setup(Map attributes)
+ {
+ // do we have a SecureRandom, or should we use our own?
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ N = (BigInteger) attributes.get(SHARED_MODULUS);
+ if (N != null)
+ {
+ l = N.bitLength();
+ g = (BigInteger) attributes.get(GENERATOR);
+ if (g == null)
+ {
+ g = TWO;
+ }
+ SRPAlgorithm.checkParams(N, g);
+ }
+ else
+ { // generate or use default values for N and g
+ Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
+ if (useDefaults == null)
+ {
+ useDefaults = Boolean.TRUE;
+ }
+ Integer L = (Integer) attributes.get(MODULUS_LENGTH);
+ l = DEFAULT_MODULUS_LENGTH;
+ if (useDefaults.equals(Boolean.TRUE))
+ {
+ if (L != null)
+ {
+ l = L.intValue();
+ switch (l)
+ {
+ case 512:
+ N = SRPAlgorithm.N_512;
+ break;
+ case 640:
+ N = SRPAlgorithm.N_640;
+ break;
+ case 768:
+ N = SRPAlgorithm.N_768;
+ break;
+ case 1024:
+ N = SRPAlgorithm.N_1024;
+ break;
+ case 1280:
+ N = SRPAlgorithm.N_1280;
+ break;
+ case 1536:
+ N = SRPAlgorithm.N_1536;
+ break;
+ case 2048:
+ N = SRPAlgorithm.N_2048;
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "unknown default shared modulus bit length");
+ }
+ g = TWO;
+ l = N.bitLength();
+ }
+ }
+ else
+ { // generate new N and g
+ if (L != null)
+ {
+ l = L.intValue();
+ if ((l % 256) != 0 || l < 512 || l > 2048)
+ {
+ throw new IllegalArgumentException(
+ "invalid shared modulus bit length");
+ }
+ }
+ }
+ }
+
+ // are we using this generator on the server side, or the client side?
+ v = (BigInteger) attributes.get(USER_VERIFIER);
+ }
+
+ public KeyPair generate()
+ {
+ if (N == null)
+ {
+ BigInteger[] params = generateParameters();
+ BigInteger q = params[0];
+ N = params[1];
+ g = params[2];
+ if (DEBUG && debuglevel > 0)
+ {
+ debug("q: " + q.toString(16));
+ debug("N: " + N.toString(16));
+ debug("g: " + g.toString(16));
+ }
+ }
+
+ return (v != null ? hostKeyPair() : userKeyPair());
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ private synchronized BigInteger[] generateParameters()
+ {
+ // N A large safe prime (N = 2q+1, where q is prime)
+ // g A generator modulo N
+ BigInteger q, p, g;
+ byte[] qBytes = new byte[l / 8];
+ do
+ {
+ do
+ {
+ nextRandomBytes(qBytes);
+ q = new BigInteger(1, qBytes);
+ q = q.setBit(0).setBit(l - 2).clearBit(l - 1);
+ }
+ while (!Prime2.isProbablePrime(q));
+ p = q.multiply(TWO).add(ONE);
+ }
+ while (p.bitLength() != l || !Prime2.isProbablePrime(p));
+
+ // compute g. from FIPS-186, Appendix 4: e == 2
+ BigInteger p_minus_1 = p.subtract(ONE);
+ g = TWO;
+ // Set h = any integer, where 1 < h < p - 1 and
+ // h differs from any value previously tried
+ for (BigInteger h = TWO; h.compareTo(p_minus_1) < 0; h = h.add(ONE))
+ {
+ // Set g = h**2 mod p
+ g = h.modPow(TWO, p);
+ // If g = 1, go to step 3
+ if (!g.equals(ONE))
+ {
+ break;
+ }
+ }
+
+ return new BigInteger[] { q, p, g };
+ }
+
+ private KeyPair hostKeyPair()
+ {
+ byte[] bBytes = new byte[(l + 7) / 8];
+ BigInteger b, B;
+ do
+ {
+ do
+ {
+ nextRandomBytes(bBytes);
+ b = new BigInteger(1, bBytes);
+ }
+ while (b.compareTo(ONE) <= 0 || b.compareTo(N) >= 0);
+ B = THREE.multiply(v).add(g.modPow(b, N)).mod(N);
+ }
+ while (B.compareTo(ZERO) == 0 || B.compareTo(N) >= 0);
+
+ KeyPair result = new KeyPair(
+ new SRPPublicKey(new BigInteger[] { N, g, B }),
+ new SRPPrivateKey(new BigInteger[] { N, g, b,
+ v }));
+ return result;
+ }
+
+ private KeyPair userKeyPair()
+ {
+ byte[] aBytes = new byte[(l + 7) / 8];
+ BigInteger a, A;
+ do
+ {
+ do
+ {
+ nextRandomBytes(aBytes);
+ a = new BigInteger(1, aBytes);
+ }
+ while (a.compareTo(ONE) <= 0 || a.compareTo(N) >= 0);
+ A = g.modPow(a, N);
+ }
+ while (A.compareTo(ZERO) == 0 || A.compareTo(N) >= 0);
+
+ KeyPair result = new KeyPair(
+ new SRPPublicKey(new BigInteger[] { N, g, A }),
+ new SRPPrivateKey(new BigInteger[] { N, g, a }));
+ return result;
+ }
+
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java b/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java
new file mode 100644
index 000000000..39234b627
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java
@@ -0,0 +1,380 @@
+/* SRPKeyPairRawCodec.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>An object that implements the {@link IKeyPairCodec} operations for the
+ * <i>Raw</i> format to use with SRP keypairs.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRPKeyPairRawCodec implements IKeyPairCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.keys.IKeyPairCodec interface implementation ------------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated SRP public key according to
+ * the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for an SRP public key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_SRP_PUBLIC_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the SRP parameter
+ * <code>N</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the SRP parameter
+ * <code>N</code>,</li>
+ * <li>4-byte count of following bytes representing the SRP parameter
+ * <code>g</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the SRP parameter
+ * <code>g</code>,</li>
+ * <li>4-byte count of following bytes representing the SRP parameter
+ * <code>y</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the SRP parameter
+ * <code>y</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @throws IllegalArgumentException if the designated key is not an SRP one.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (!(key instanceof SRPPublicKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ SRPPublicKey srpKey = (SRPPublicKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // N
+ byte[] buffer = srpKey.getN().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // g
+ buffer = srpKey.getG().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // y
+ buffer = srpKey.getY().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PublicKey decodePublicKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // N
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger N = new BigInteger(1, buffer);
+
+ // g
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger g = new BigInteger(1, buffer);
+
+ // y
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger y = new BigInteger(1, buffer);
+
+ return new SRPPublicKey(N, g, y);
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated SRP private key according to
+ * the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for an SRP private key, in this implementation,
+ * is a byte sequence consisting of the following:</p>
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_SRP_PRIVATE_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the SRP parameter
+ * <code>N</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the SRP parameter
+ * <code>N</code>,</li>
+ * <li>4-byte count of following bytes representing the SRP parameter
+ * <code>g</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the SRP parameter
+ * <code>g</code>,</li>
+ * <li>4-byte count of following bytes representing the SRP parameter
+ * <code>x</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the SRP parameter
+ * <code>x</code>,</li>
+ * <li>one byte which indicates whether the SRP parameter <code>v</code>
+ * is included in this encoding (value <code>0x01</code>) or not
+ * (value <code>0x00</code>).</li>
+ * <li>4-byte count of following bytes representing the SRP parameter
+ * <code>v</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the SRP parameter
+ * <code>v</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @throws IllegalArgumentException if the designated key is not an SRP one.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (!(key instanceof SRPPrivateKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ SRPPrivateKey srpKey = (SRPPrivateKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // N
+ byte[] buffer = srpKey.getN().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // g
+ buffer = srpKey.getG().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // x
+ buffer = srpKey.getX().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // v
+ if (srpKey.getV() != null)
+ {
+ baos.write(0x01);
+
+ buffer = srpKey.getV().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+ }
+ else
+ {
+ baos.write(0x00);
+ }
+
+ return baos.toByteArray();
+ }
+
+ public PrivateKey decodePrivateKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // N
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger N = new BigInteger(1, buffer);
+
+ // g
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger g = new BigInteger(1, buffer);
+
+ // x
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger x = new BigInteger(1, buffer);
+
+ // v
+ l = k[i++];
+ if (l == 0x01)
+ {
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger v = new BigInteger(1, buffer);
+
+ return new SRPPrivateKey(N, g, x, v);
+ }
+ else
+ {
+ return new SRPPrivateKey(N, g, x);
+ }
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRPPrivateKey.java b/gnu/javax/crypto/key/srp6/SRPPrivateKey.java
new file mode 100644
index 000000000..d9f7a19a6
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRPPrivateKey.java
@@ -0,0 +1,250 @@
+/* SRPPrivateKey.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+
+/**
+ * <p>A representation of an SRP ephemeral private key.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRPPrivateKey extends SRPKey implements PrivateKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * The private exponent for either the server or the client engaged in the
+ * SRP protocol exchange.
+ */
+ private final BigInteger X;
+
+ /**
+ * The user's verifier (v) --for the server-- also computed at the client
+ * side as g.modPow(x, N), where x is the hashed output of the user name and
+ * password .
+ */
+ private final BigInteger v;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Public constructor for use from outside this package.</p>
+ *
+ * @param N the public shared modulus.
+ * @param g the generator.
+ * @param x the private exponent of the ephemeral key.
+ */
+ public SRPPrivateKey(BigInteger N, BigInteger g, BigInteger x)
+ {
+ this(N, g, x, null);
+ }
+
+ /**
+ * <p>Public constructor for use from outside this package.</p>
+ *
+ * @param N the public shared modulus.
+ * @param g the generator.
+ * @param x the private exponent of the ephemeral key.
+ * @param v the user's verifier value (for the server side only).
+ */
+ public SRPPrivateKey(BigInteger N, BigInteger g, BigInteger x, BigInteger v)
+ {
+ super(N, g);
+
+ SRPAlgorithm.checkParams(N, g);
+ this.X = x;
+ this.v = v;
+ }
+
+ /**
+ * <p>Default constructor. Assumes N and g are already validated.</p>
+ *
+ * @param params an array of either 3 or 4 values representing N, g, and
+ * either v and X for the server, or just X for the client. Those values
+ * represent the following:
+ * <ol>
+ * <li>v (server side): the user's verifier.</li>
+ * <li>X (both sides): the server's or client's ephemeral private exponent.</li>
+ * </ol>
+ */
+ SRPPrivateKey(BigInteger[] params)
+ {
+ super(params[0], params[1]);
+
+ if (params.length == 3)
+ {
+ X = params[2];
+ v = null;
+ }
+ else if (params.length == 4)
+ {
+ X = params[2];
+ v = params[3];
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid number of SRP parameters");
+ }
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A class method that takes the output of the <code>encodePrivateKey()</code>
+ * method of an SRP keypair codec object (an instance implementing
+ * {@link IKeyPairCodec} for DSS keys, and re-constructs an instance of this
+ * object.</p>
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an instance of this object.
+ * @throws IllegalArgumentException if the byte sequence does not represent a
+ * valid encoding of an instance of this object.
+ */
+ public static SRPPrivateKey valueOf(byte[] k)
+ {
+ // check magic...
+ // we should parse here enough bytes to know which codec to use, and
+ // direct the byte array to the appropriate codec. since we only have one
+ // codec, we could have immediately tried it; nevertheless since testing
+ // one byte is cheaper than instatiating a codec that will fail we test
+ // the first byte before we carry on.
+ if (k[0] == Registry.MAGIC_RAW_SRP_PRIVATE_KEY[0])
+ {
+ // it's likely to be in raw format. get a raw codec and hand it over
+ IKeyPairCodec codec = new SRPKeyPairRawCodec();
+ return (SRPPrivateKey) codec.decodePrivateKey(k);
+ }
+ else
+ {
+ throw new IllegalArgumentException("magic");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the private exponent of the key as a {@link BigInteger}.</p>
+ *
+ * @return the private exponent of the key as a {@link BigInteger}.
+ */
+ public BigInteger getX()
+ {
+ return X;
+ }
+
+ /**
+ * <p>Returns the user's verifier as a {@link BigInteger}.</p>
+ *
+ * @return the user's verifier as a {@link BigInteger} if this is an SRP
+ * private key of a Host, or <code>null</code> if this is a private SRP key
+ * for a User.
+ */
+ public BigInteger getV()
+ {
+ return v;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this private key according to the
+ * designated format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @throws IllegalArgumentException if the format is not supported.
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new SRPKeyPairRawCodec().encodePrivateKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("format");
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * <code>SRPPrivateKey</code> and has the same SRP parameter values as this
+ * one.</p>
+ *
+ * @param obj the other non-null SRP key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof SRPPrivateKey))
+ {
+ return false;
+ }
+ SRPPrivateKey that = (SRPPrivateKey) obj;
+ boolean result = super.equals(that) && X.equals(that.getX());
+ if (v != null)
+ {
+ result = result && v.equals(that.getV());
+ }
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/key/srp6/SRPPublicKey.java b/gnu/javax/crypto/key/srp6/SRPPublicKey.java
new file mode 100644
index 000000000..7283fd3da
--- /dev/null
+++ b/gnu/javax/crypto/key/srp6/SRPPublicKey.java
@@ -0,0 +1,194 @@
+/* SRPPublicKey.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key.srp6;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+
+/**
+ * <p>A representation of an SRP ephemeral public key.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class SRPPublicKey extends SRPKey implements PublicKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * The public exponent for either the server or the client engaged in the
+ * SRP protocol exchange.
+ */
+ private final BigInteger Y;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Public constructor for use from outside this package.</p>
+ *
+ * @param N the public shared modulus.
+ * @param g the generator.
+ * @param Y the public exponent of the ephemeral key.
+ */
+ public SRPPublicKey(BigInteger N, BigInteger g, BigInteger Y)
+ {
+ super(N, g);
+
+ SRPAlgorithm.checkParams(N, g);
+ this.Y = Y;
+ }
+
+ /**
+ * <p>Default constructor. Assumes that N and g are already validated.</p>
+ *
+ * @param params an array of 3 values representing N, g and Y; the latter
+ * being the client's or server's public exponent.
+ */
+ SRPPublicKey(BigInteger[] params)
+ {
+ super(params[0], params[1]);
+
+ this.Y = params[2];
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A class method that takes the output of the <code>encodePublicKey()</code>
+ * method of an SRP keypair codec object (an instance implementing
+ * {@link IKeyPairCodec} for SRP keys, and re-constructs an instance of this
+ * object.</p>
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an instance of this object.
+ * @throws IllegalArgumentException if the byte sequence does not represent a
+ * valid encoding of an instance of this object.
+ */
+ public static SRPPublicKey valueOf(byte[] k)
+ {
+ // check magic...
+ // we should parse here enough bytes to know which codec to use, and
+ // direct the byte array to the appropriate codec. since we only have one
+ // codec, we could have immediately tried it; nevertheless since testing
+ // one byte is cheaper than instatiating a codec that will fail we test
+ // the first byte before we carry on.
+ if (k[0] == Registry.MAGIC_RAW_SRP_PUBLIC_KEY[0])
+ {
+ // it's likely to be in raw format. get a raw codec and hand it over
+ IKeyPairCodec codec = new SRPKeyPairRawCodec();
+ return (SRPPublicKey) codec.decodePublicKey(k);
+ }
+ else
+ {
+ throw new IllegalArgumentException("magic");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the public exponent of the key as a {@link BigInteger}.</p>
+ *
+ * @return the public exponent of the key as a {@link BigInteger}.
+ */
+ public BigInteger getY()
+ {
+ return Y;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this public key according to the designated
+ * format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @throws IllegalArgumentException if the format is not supported.
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new SRPKeyPairRawCodec().encodePublicKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("format");
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * <code>SRPPublicKey</code>and has the same SRP parameter values as this one.
+ * </p>
+ *
+ * @param obj the other non-null SRP key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof SRPPublicKey))
+ {
+ return false;
+ }
+ SRPPublicKey that = (SRPPublicKey) obj;
+ return super.equals(that) && Y.equals(that.getY());
+ }
+}
diff --git a/gnu/javax/crypto/keyring/AuthenticatedEntry.java b/gnu/javax/crypto/keyring/AuthenticatedEntry.java
new file mode 100644
index 000000000..22b42b3ea
--- /dev/null
+++ b/gnu/javax/crypto/keyring/AuthenticatedEntry.java
@@ -0,0 +1,222 @@
+/* AuthenticatedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.InvalidKeyException;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+import gnu.javax.crypto.mac.MacInputStream;
+import gnu.javax.crypto.mac.MacOutputStream;
+
+public final class AuthenticatedEntry extends MaskableEnvelopeEntry implements
+ Registry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 2;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public AuthenticatedEntry(String mac, int macLen, Properties properties)
+ {
+ super(TYPE, properties);
+
+ if (macLen <= 0)
+ {
+ throw new IllegalArgumentException("invalid mac length");
+ }
+ this.properties.put("mac", mac);
+ this.properties.put("maclen", String.valueOf(macLen));
+ setMasked(false);
+ }
+
+ private AuthenticatedEntry()
+ {
+ super(TYPE);
+ setMasked(true);
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static AuthenticatedEntry decode(DataInputStream in)
+ throws IOException
+ {
+ AuthenticatedEntry entry = new AuthenticatedEntry();
+ entry.properties.decode(in);
+ if (!entry.properties.containsKey("mac"))
+ {
+ throw new MalformedKeyringException("no mac specified");
+ }
+ if (!entry.properties.containsKey("maclen"))
+ {
+ throw new MalformedKeyringException("no mac length specified");
+ }
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Computes the mac over this envelope's data. This method <b>must</b> be
+ * called before this entry in encoded.
+ *
+ * @param key The key to authenticate with.
+ * @throws IOException If encoding fails.
+ * @throws InvalidKeyException If the supplied key is bad.
+ */
+ public void authenticate(byte[] key) throws IOException, InvalidKeyException
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("entry is masked");
+ }
+ IMac m = getMac(key);
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ MacOutputStream macout = new MacOutputStream(bout, m);
+ DataOutputStream out2 = new DataOutputStream(macout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ entry.encode(out2);
+ }
+ bout.write(m.digest());
+ payload = bout.toByteArray();
+ }
+
+ /**
+ * Verifies this entry's payload. This method will unmask this entry,
+ * thus it must be called before accessing its contents.
+ *
+ * @param key The key to use to authenticate.
+ * @throws InvalidKeyException If the given key is improper.
+ */
+ public void verify(byte[] key) throws InvalidKeyException
+ {
+ if (!isMasked() || payload == null)
+ {
+ return;
+ }
+ IMac m = getMac(key);
+
+ m.update(payload, 0, payload.length - m.macSize());
+ byte[] macValue = new byte[m.macSize()];
+ System.arraycopy(payload, payload.length - macValue.length, macValue, 0,
+ macValue.length);
+ if (!Arrays.equals(macValue, m.digest()))
+ {
+ throw new IllegalArgumentException("MAC verification failed");
+ }
+ try
+ {
+ DataInputStream in = new DataInputStream(
+ new ByteArrayInputStream(
+ payload,
+ 0,
+ payload.length
+ - m.macSize()));
+ decodeEnvelope(in);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("malformed keyring fragment");
+ }
+ setMasked(false);
+ payload = null;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ if (payload == null)
+ {
+ throw new IllegalStateException("not authenticated");
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private IMac getMac(byte[] key) throws InvalidKeyException
+ {
+ IMac mac = MacFactory.getInstance(properties.get("mac"));
+ if (mac == null)
+ {
+ throw new IllegalArgumentException("no such mac: "
+ + properties.get("mac"));
+ }
+ int maclen = 0;
+ if (!properties.containsKey("maclen"))
+ {
+ throw new IllegalArgumentException("no MAC length");
+ }
+ try
+ {
+ maclen = Integer.parseInt(properties.get("maclen"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new IllegalArgumentException("bad MAC length");
+ }
+
+ HashMap macAttr = new HashMap();
+ macAttr.put(IMac.MAC_KEY_MATERIAL, key);
+ macAttr.put(IMac.TRUNCATED_SIZE, new Integer(maclen));
+ mac.init(macAttr);
+ return mac;
+ }
+}
diff --git a/gnu/javax/crypto/keyring/BaseKeyring.java b/gnu/javax/crypto/keyring/BaseKeyring.java
new file mode 100644
index 000000000..5fe7dbf4d
--- /dev/null
+++ b/gnu/javax/crypto/keyring/BaseKeyring.java
@@ -0,0 +1,198 @@
+/* BaseKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import gnu.java.security.Registry;
+
+public abstract class BaseKeyring implements IKeyring
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /**
+ * The top-level keyring data.
+ */
+ protected PasswordAuthenticatedEntry keyring;
+
+ protected CompressedEntry keyring2;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public BaseKeyring()
+ {
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public void load(Map attributes) throws IOException
+ {
+ InputStream in = (InputStream) attributes.get(KEYRING_DATA_IN);
+ if (in == null)
+ {
+ throw new IllegalArgumentException("no input stream");
+ }
+ char[] password = (char[]) attributes.get(KEYRING_PASSWORD);
+ if (password == null)
+ {
+ password = new char[0];
+ }
+
+ if (in.read() != Registry.GKR_MAGIC[0]
+ || in.read() != Registry.GKR_MAGIC[1]
+ || in.read() != Registry.GKR_MAGIC[2]
+ || in.read() != Registry.GKR_MAGIC[3])
+ {
+ throw new MalformedKeyringException("magic");
+ }
+
+ load(in, password);
+
+ List l = keyring.getEntries();
+ if (l.size() == 1 && (l.get(0) instanceof CompressedEntry))
+ {
+ keyring2 = (CompressedEntry) l.get(0);
+ }
+ }
+
+ public void store(Map attributes) throws IOException
+ {
+ OutputStream out = (OutputStream) attributes.get(KEYRING_DATA_OUT);
+ if (out == null)
+ {
+ throw new IllegalArgumentException("no output stream");
+ }
+ char[] password = (char[]) attributes.get(KEYRING_PASSWORD);
+ if (password == null)
+ {
+ password = new char[0];
+ }
+ if (keyring == null)
+ {
+ throw new IllegalStateException("empty keyring");
+ }
+
+ out.write(Registry.GKR_MAGIC);
+ store(out, password);
+ }
+
+ public void reset()
+ {
+ keyring = null;
+ }
+
+ public int size()
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException ("keyring not loaded");
+ }
+ return ((StringTokenizer) aliases()).countTokens();
+ }
+
+ public Enumeration aliases()
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException ("keyring not loaded");
+ }
+ return new StringTokenizer(keyring.getAliasList(), ";");
+ }
+
+ public boolean containsAlias(String alias)
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException("keyring not loaded");
+ }
+ return keyring.containsAlias(alias);
+ }
+
+ public List get(String alias)
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException("keyring not loaded");
+ }
+ return keyring.get(alias);
+ }
+
+ public void add(Entry entry)
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException("keyring not loaded");
+ }
+ if (keyring2 != null)
+ keyring2.add(entry);
+ else
+ keyring.add(entry);
+ }
+
+ public void remove(String alias)
+ {
+ if (keyring == null)
+ {
+ throw new IllegalStateException("keyring not loaded");
+ }
+ keyring.remove(alias);
+ }
+
+ protected String fixAlias(String alias)
+ {
+ return alias.replace(';', '_');
+ }
+
+ protected abstract void load(InputStream in, char[] password)
+ throws IOException;
+
+ protected abstract void store(OutputStream out, char[] password)
+ throws IOException;
+}
diff --git a/gnu/javax/crypto/keyring/BinaryDataEntry.java b/gnu/javax/crypto/keyring/BinaryDataEntry.java
new file mode 100644
index 000000000..2dcd5454f
--- /dev/null
+++ b/gnu/javax/crypto/keyring/BinaryDataEntry.java
@@ -0,0 +1,128 @@
+/* BinaryDataEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import java.util.Date;
+
+/**
+ * A binary data entry is a primitive entry that simply contains some amount
+ * of arbitrary binary data and an optional content type.
+ */
+public class BinaryDataEntry extends PrimitiveEntry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 9;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new binary data entry.
+ *
+ * @param contentType The content type of this entry. This parameter can
+ * be <code>null</code> if no content type is needed.
+ * @param data The data.
+ * @param creationDate The creation date.
+ * @param properties This entry's properties.
+ */
+ public BinaryDataEntry(String contentType, byte[] data, Date creationDate,
+ Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+ if (data == null)
+ {
+ throw new IllegalArgumentException("no data");
+ }
+ payload = (byte[]) data.clone();
+ if (contentType != null)
+ {
+ this.properties.put("content-type", contentType);
+ }
+ }
+
+ private BinaryDataEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static BinaryDataEntry decode(DataInputStream in) throws IOException
+ {
+ BinaryDataEntry entry = new BinaryDataEntry();
+ entry.defaultDecode(in);
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the content type of this entry, or <code>null</code> if this
+ * property is not set.
+ *
+ * @return The content type.
+ */
+ public String getContentType()
+ {
+ return properties.get("content-type");
+ }
+
+ /**
+ * Returns this object's data field.
+ *
+ * @return The data.
+ */
+ public byte[] getData()
+ {
+ return getPayload();
+ }
+
+ protected void encodePayload()
+ {
+ // Empty.
+ }
+}
diff --git a/gnu/javax/crypto/keyring/CertPathEntry.java b/gnu/javax/crypto/keyring/CertPathEntry.java
new file mode 100644
index 000000000..ef62347ec
--- /dev/null
+++ b/gnu/javax/crypto/keyring/CertPathEntry.java
@@ -0,0 +1,133 @@
+/* CertPathEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+
+import java.util.Date;
+
+/**
+ * A primitive entry that contains a path of X.509 certificates.
+ */
+public final class CertPathEntry extends PrimitiveEntry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 8;
+
+ private Certificate[] path;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public CertPathEntry(Certificate[] path, Date creationDate,
+ Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+ if (path == null || path.length == 0)
+ {
+ throw new IllegalArgumentException("no certificate path");
+ }
+ this.path = (Certificate[]) path.clone();
+ }
+
+ private CertPathEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class method.
+ // ------------------------------------------------------------------------
+
+ public static CertPathEntry decode(DataInputStream in) throws IOException
+ {
+ CertPathEntry entry = new CertPathEntry();
+ entry.properties.decode(in);
+ entry.makeCreationDate();
+ int len = in.readInt();
+ MeteredInputStream in2 = new MeteredInputStream(in, len);
+ try
+ {
+ CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ entry.path = (Certificate[]) fact.generateCertificates(in2).toArray(
+ new Certificate[0]);
+ }
+ catch (CertificateException ce)
+ {
+ throw new MalformedKeyringException(ce.toString());
+ }
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public Certificate[] getCertPath()
+ {
+ return path;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ byte[] enc = null;
+ try
+ {
+ for (int i = 0; i < path.length; i++)
+ {
+ bout.write(path[i].getEncoded());
+ }
+ }
+ catch (CertificateEncodingException cee)
+ {
+ throw new IOException(cee.toString());
+ }
+ payload = bout.toByteArray();
+ }
+}
diff --git a/gnu/javax/crypto/keyring/CertificateEntry.java b/gnu/javax/crypto/keyring/CertificateEntry.java
new file mode 100644
index 000000000..95a708ac5
--- /dev/null
+++ b/gnu/javax/crypto/keyring/CertificateEntry.java
@@ -0,0 +1,150 @@
+/* CertificateEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+/**
+ * <p>An immutable class representing a trusted certificate entry.</p>
+ */
+public final class CertificateEntry extends PrimitiveEntry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int TYPE = 5;
+
+ /** The certificate. */
+ private Certificate certificate;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a new certificate entry.
+ *
+ * @param certificate The certificate.
+ * @param creationDate The creation date.
+ * @param properties The alias.
+ * @throws IllegalArgumentException If any argument is null, or if the alias
+ * is empty.
+ */
+ public CertificateEntry(Certificate certificate, Date creationDate,
+ Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+
+ if (certificate == null)
+ {
+ throw new IllegalArgumentException("no certificate");
+ }
+ this.certificate = certificate;
+ this.properties.put("type", certificate.getType());
+ }
+
+ private CertificateEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static CertificateEntry decode(DataInputStream in) throws IOException
+ {
+ CertificateEntry entry = new CertificateEntry();
+ entry.properties.decode(in);
+ entry.makeCreationDate();
+ String type = entry.properties.get("type");
+ if (type == null)
+ {
+ throw new MalformedKeyringException("no certificate type");
+ }
+ int len = in.readInt();
+ MeteredInputStream in2 = new MeteredInputStream(in, len);
+ try
+ {
+ CertificateFactory fact = CertificateFactory.getInstance(type);
+ entry.certificate = fact.generateCertificate(in2);
+ }
+ catch (CertificateException ce)
+ {
+ throw new MalformedKeyringException(ce.toString());
+ }
+ if (!in2.limitReached())
+ {
+ throw new MalformedKeyringException("extra data at end of payload");
+ }
+ return entry;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns this entry's certificate.
+ *
+ * @return The certificate.
+ */
+ public Certificate getCertificate()
+ {
+ return certificate;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ try
+ {
+ payload = certificate.getEncoded();
+ }
+ catch (CertificateEncodingException cee)
+ {
+ throw new IOException(cee.toString());
+ }
+ }
+}
diff --git a/gnu/javax/crypto/keyring/CompressedEntry.java b/gnu/javax/crypto/keyring/CompressedEntry.java
new file mode 100644
index 000000000..cce930d73
--- /dev/null
+++ b/gnu/javax/crypto/keyring/CompressedEntry.java
@@ -0,0 +1,113 @@
+/* CompressedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.util.Iterator;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterInputStream;
+
+public class CompressedEntry extends EnvelopeEntry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 4;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public CompressedEntry(Properties properties)
+ {
+ super(TYPE, properties);
+ this.properties.put("algorithm", "DEFLATE");
+ }
+
+ private CompressedEntry()
+ {
+ this(new Properties());
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static CompressedEntry decode(DataInputStream in) throws IOException
+ {
+ CompressedEntry entry = new CompressedEntry();
+ entry.properties.decode(in);
+ String alg = entry.properties.get("algorithm");
+ if (alg == null)
+ {
+ throw new MalformedKeyringException("no compression algorithm");
+ }
+ if (!alg.equalsIgnoreCase("DEFLATE"))
+ {
+ throw new MalformedKeyringException(
+ "unsupported compression algorithm: "
+ + alg);
+ }
+ int len = in.readInt();
+ MeteredInputStream min = new MeteredInputStream(in, len);
+ InflaterInputStream infin = new InflaterInputStream(min);
+ DataInputStream in2 = new DataInputStream(infin);
+ entry.decodeEnvelope(in2);
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ protected void encodePayload() throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream(1024);
+ DeflaterOutputStream dout = new DeflaterOutputStream(buf);
+ DataOutputStream out2 = new DataOutputStream(dout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ ((Entry) it.next()).encode(out2);
+ }
+ dout.finish();
+ payload = buf.toByteArray();
+ }
+}
diff --git a/gnu/javax/crypto/keyring/EncryptedEntry.java b/gnu/javax/crypto/keyring/EncryptedEntry.java
new file mode 100644
index 000000000..fad5f54b2
--- /dev/null
+++ b/gnu/javax/crypto/keyring/EncryptedEntry.java
@@ -0,0 +1,235 @@
+/* EncryptedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.InvalidKeyException;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+import gnu.javax.crypto.pad.IPad;
+import gnu.javax.crypto.pad.PadFactory;
+import gnu.javax.crypto.pad.WrongPaddingException;
+
+public class EncryptedEntry extends MaskableEnvelopeEntry implements Registry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 0;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public EncryptedEntry(String cipher, String mode, Properties properties)
+ {
+ super(TYPE, properties);
+ if (cipher == null || mode == null)
+ {
+ throw new IllegalArgumentException(
+ "neither cipher nor mode can be null");
+ }
+ properties.put("cipher", cipher);
+ properties.put("mode", mode);
+ setMasked(false);
+ }
+
+ private EncryptedEntry()
+ {
+ super(TYPE, new Properties());
+ setMasked(true);
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static EncryptedEntry decode(DataInputStream in) throws IOException
+ {
+ EncryptedEntry entry = new EncryptedEntry();
+ entry.defaultDecode(in);
+ if (!entry.properties.containsKey("cipher"))
+ {
+ throw new MalformedKeyringException("no cipher");
+ }
+ if (!entry.properties.containsKey("cipher"))
+ {
+ throw new MalformedKeyringException("no cipher");
+ }
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public void decrypt(byte[] key, byte[] iv) throws IllegalArgumentException,
+ WrongPaddingException
+ {
+ if (!isMasked() || payload == null)
+ {
+ return;
+ }
+ IMode mode = getMode(key, iv, IMode.DECRYPTION);
+ IPad padding = null;
+ padding = PadFactory.getInstance("PKCS7");
+ padding.init(mode.currentBlockSize());
+ byte[] buf = new byte[payload.length];
+ int count = 0;
+ for (int i = 0; i < payload.length; i++)
+ {
+ mode.update(payload, count, buf, count);
+ count += mode.currentBlockSize();
+ }
+ int padlen = padding.unpad(buf, 0, buf.length);
+ DataInputStream in = new DataInputStream(
+ new ByteArrayInputStream(
+ buf,
+ 0,
+ buf.length
+ - padlen));
+ try
+ {
+ decodeEnvelope(in);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("decryption failed");
+ }
+ setMasked(false);
+ payload = null;
+ }
+
+ public void encrypt(byte[] key, byte[] iv) throws IOException
+ {
+ IMode mode = getMode(key, iv, IMode.ENCRYPTION);
+ IPad pad = PadFactory.getInstance("PKCS7");
+ pad.init(mode.currentBlockSize());
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ DataOutputStream out2 = new DataOutputStream(bout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ entry.encode(out2);
+ }
+ byte[] plaintext = bout.toByteArray();
+ byte[] padding = pad.pad(plaintext, 0, plaintext.length);
+ payload = new byte[plaintext.length + padding.length];
+ byte[] lastBlock = new byte[mode.currentBlockSize()];
+ int l = mode.currentBlockSize() - padding.length;
+ System.arraycopy(plaintext, plaintext.length - l, lastBlock, 0, l);
+ System.arraycopy(padding, 0, lastBlock, l, padding.length);
+ int count = 0;
+ while (count + mode.currentBlockSize() < plaintext.length)
+ {
+ mode.update(plaintext, count, payload, count);
+ count += mode.currentBlockSize();
+ }
+ mode.update(lastBlock, 0, payload, count);
+ }
+
+ public void encodePayload() throws IOException
+ {
+ if (payload == null)
+ {
+ throw new IOException("not encrypted");
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private IMode getMode(byte[] key, byte[] iv, int state)
+ {
+ IBlockCipher cipher = CipherFactory.getInstance(properties.get("cipher"));
+ if (cipher == null)
+ {
+ throw new IllegalArgumentException("no such cipher: "
+ + properties.get("cipher"));
+ }
+ int blockSize = cipher.defaultBlockSize();
+ if (properties.containsKey("block-size"))
+ {
+ try
+ {
+ blockSize = Integer.parseInt(properties.get("block-size"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new IllegalArgumentException("bad block size: "
+ + nfe.getMessage());
+ }
+ }
+ IMode mode = ModeFactory.getInstance(properties.get("mode"), cipher,
+ blockSize);
+ if (mode == null)
+ {
+ throw new IllegalArgumentException("no such mode: "
+ + properties.get("mode"));
+ }
+
+ HashMap modeAttr = new HashMap();
+ modeAttr.put(IMode.KEY_MATERIAL, key);
+ modeAttr.put(IMode.STATE, new Integer(state));
+ modeAttr.put(IMode.IV, iv);
+ try
+ {
+ mode.init(modeAttr);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new IllegalArgumentException(ike.toString());
+ }
+ return mode;
+ }
+}
diff --git a/gnu/javax/crypto/keyring/Entry.java b/gnu/javax/crypto/keyring/Entry.java
new file mode 100644
index 000000000..fa7f49679
--- /dev/null
+++ b/gnu/javax/crypto/keyring/Entry.java
@@ -0,0 +1,178 @@
+/* Entry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * An immutable class representing a single entry in a keyring.
+ */
+public abstract class Entry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** This entry's type identifier. */
+ protected int type;
+
+ /** This entry's property set. */
+ protected Properties properties;
+
+ /** This entry's payload. */
+ protected byte[] payload;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new Entry.
+ *
+ * @param type This entry's type.
+ * @param properties This entry's properties.
+ * @throws IllegalArgumentException If the properties argument is null,
+ * or if the type is out of range.
+ */
+ protected Entry(int type, Properties properties)
+ {
+ if (type < 0 || type > 255)
+ {
+ throw new IllegalArgumentException("invalid packet type");
+ }
+ if (properties == null)
+ {
+ throw new IllegalArgumentException("no properties");
+ }
+ this.type = type;
+ this.properties = (Properties) properties.clone();
+ }
+
+ /**
+ * Constructor for use by subclasses.
+ */
+ protected Entry(final int type)
+ {
+ if (type < 0 || type > 255)
+ {
+ throw new IllegalArgumentException("invalid packet type");
+ }
+ this.type = type;
+ properties = new Properties();
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns this entry's properties object. The properties are cloned before
+ * being returned.
+ *
+ * @return The properties.
+ */
+ public Properties getProperties()
+ {
+ return (Properties) properties.clone();
+ }
+
+ /**
+ * Returns this entry's payload data, or null if
+ */
+ public byte[] getPayload()
+ {
+ if (payload == null)
+ return null;
+ return (byte[]) payload.clone();
+ }
+
+ /**
+ * This method is called when this entry needs to be written to an
+ * output stream.
+ *
+ * @param out The stream to write to.
+ * @throws IOException If an I/O exception occurs.
+ */
+ public void encode(DataOutputStream out) throws IOException
+ {
+ if (payload == null)
+ {
+ encodePayload();
+ }
+ if (out == null)
+ {
+ return;
+ }
+ out.write(type);
+ properties.encode(out);
+ out.writeInt(payload.length);
+ out.write(payload);
+ }
+
+ /**
+ * Generic decoding method, which simply decodes the properties field
+ * and reads the payload field.
+ *
+ * @param in The input data stream.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected void defaultDecode(DataInputStream in) throws IOException
+ {
+ properties = new Properties();
+ properties.decode(in);
+ int len = in.readInt();
+ if (len < 0)
+ {
+ throw new IOException("corrupt length");
+ }
+ payload = new byte[len];
+ in.readFully(payload);
+ }
+
+ // Abstract methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * This method is called of subclasses when the payload data needs to be
+ * created.
+ *
+ * @throws IOException If an encoding error occurs.
+ */
+ protected abstract void encodePayload() throws IOException;
+}
diff --git a/gnu/javax/crypto/keyring/EnvelopeEntry.java b/gnu/javax/crypto/keyring/EnvelopeEntry.java
new file mode 100644
index 000000000..25b1dc2a0
--- /dev/null
+++ b/gnu/javax/crypto/keyring/EnvelopeEntry.java
@@ -0,0 +1,398 @@
+/* EnvelopeEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * An envelope entry is a generic container for some number of primitive
+ * and other envelope entries.
+ */
+public abstract class EnvelopeEntry extends Entry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The envelope that contains this one (if any). */
+ protected EnvelopeEntry containingEnvelope;
+
+ /** The contained entries. */
+ protected List entries;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public EnvelopeEntry(int type, Properties properties)
+ {
+ super(type, properties);
+ entries = new LinkedList();
+ if (this.properties.get("alias-list") != null)
+ {
+ this.properties.remove("alias-list");
+ }
+ }
+
+ protected EnvelopeEntry(int type)
+ {
+ super(type);
+ entries = new LinkedList();
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds an entry to this envelope.
+ *
+ * @param entry The entry to add.
+ */
+ public void add(Entry entry)
+ {
+ if (!containsEntry(entry))
+ {
+ if (entry instanceof EnvelopeEntry)
+ {
+ ((EnvelopeEntry) entry).setContainingEnvelope(this);
+ }
+ entries.add(entry);
+ payload = null;
+ makeAliasList();
+ }
+ }
+
+ /**
+ * Tests if this envelope contains a primitive entry with the
+ * given alias.
+ *
+ * @param alias The alias to test.
+ * @return True if this envelope (or one of the contained envelopes)
+ * contains a primitive entry with the given alias.
+ */
+ public boolean containsAlias(String alias)
+ {
+ String aliases = getAliasList();
+ if (aliases == null)
+ {
+ return false;
+ }
+ StringTokenizer tok = new StringTokenizer(aliases, ";");
+ while (tok.hasMoreTokens())
+ {
+ if (tok.nextToken().equals(alias))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests if this envelope contains the given entry.
+ *
+ * @param entry The entry to test.
+ * @return True if this envelope contains the given entry.
+ */
+ public boolean containsEntry(Entry entry)
+ {
+ if (entry instanceof EnvelopeEntry)
+ {
+ return entries.contains(entry);
+ }
+ else if (entry instanceof PrimitiveEntry)
+ {
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e.equals(entry))
+ return true;
+ if ((e instanceof EnvelopeEntry)
+ && ((EnvelopeEntry) e).containsEntry(entry))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a copy of all entries this envelope contains.
+ *
+ * @return All contained entries.
+ */
+ public List getEntries()
+ {
+ return new ArrayList(entries);
+ }
+
+ /**
+ * Gets all primitive entries that have the given alias. If there
+ * are any masked entries that contain the given alias, they will
+ * be returned as well.
+ *
+ * @param alias The alias of the entries to get.
+ * @return A list of all primitive entries that have the given alias.
+ */
+ public List get(String alias)
+ {
+ List result = new LinkedList();
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof EnvelopeEntry)
+ {
+ if (!((EnvelopeEntry) e).containsAlias(alias))
+ {
+ continue;
+ }
+ if (e instanceof MaskableEnvelopeEntry)
+ {
+ if (((MaskableEnvelopeEntry) e).isMasked())
+ {
+ result.add(e);
+ continue;
+ }
+ }
+ result.addAll(((EnvelopeEntry) e).get(alias));
+ }
+ else if (e instanceof PrimitiveEntry)
+ {
+ if (((PrimitiveEntry) e).getAlias().equals(alias))
+ {
+ result.add(e);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the list of all aliases contained by this envelope,
+ * separated by a semicolon (';').
+ *
+ * @return The list of aliases.
+ */
+ public String getAliasList()
+ {
+ String list = properties.get("alias-list");
+ if (list == null)
+ {
+ return "";
+ }
+ else
+ {
+ return list;
+ }
+ }
+
+ /**
+ * Removes the specified entry.
+ *
+ * @param entry The entry.
+ * @return True if an entry was removed.
+ */
+ public boolean remove(Entry entry)
+ {
+ boolean ret = false;
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof EnvelopeEntry)
+ {
+ if (e == entry)
+ {
+ it.remove();
+ ret = true;
+ break;
+ }
+ if (((EnvelopeEntry) e).remove(entry))
+ {
+ ret = true;
+ break;
+ }
+ }
+ else if (e instanceof PrimitiveEntry)
+ {
+ if (((PrimitiveEntry) e).equals(entry))
+ {
+ it.remove();
+ ret = true;
+ break;
+ }
+ }
+ }
+ if (ret)
+ {
+ payload = null;
+ makeAliasList();
+ }
+ return ret;
+ }
+
+ /**
+ * Removes all primitive entries that have the specified alias.
+ *
+ * @param alias The alias of the entries to remove.
+ */
+ public void remove(String alias)
+ {
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof EnvelopeEntry)
+ {
+ ((EnvelopeEntry) e).remove(alias);
+ }
+ else if (e instanceof PrimitiveEntry)
+ {
+ if (((PrimitiveEntry) e).getAlias().equals(alias))
+ {
+ it.remove();
+ }
+ }
+ }
+ payload = null;
+ makeAliasList();
+ }
+
+ // Protected methods.
+ // ------------------------------------------------------------------------
+
+ protected void encodePayload() throws IOException
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ DataOutputStream out = new DataOutputStream(bout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ ((Entry) it.next()).encode(out);
+ }
+ }
+
+ protected void setContainingEnvelope(EnvelopeEntry e)
+ {
+ if (containingEnvelope != null)
+ {
+ throw new IllegalArgumentException("envelopes may not be shared");
+ }
+ containingEnvelope = e;
+ }
+
+ protected void decodeEnvelope(DataInputStream in) throws IOException
+ {
+ while (true)
+ {
+ int type = in.read();
+ switch (type)
+ {
+ case EncryptedEntry.TYPE:
+ add(EncryptedEntry.decode(in));
+ break;
+ case PasswordEncryptedEntry.TYPE:
+ add(PasswordEncryptedEntry.decode(in));
+ break;
+ case PasswordAuthenticatedEntry.TYPE:
+ add(PasswordAuthenticatedEntry.decode(in));
+ break;
+ case AuthenticatedEntry.TYPE:
+ add(AuthenticatedEntry.decode(in));
+ break;
+ case CompressedEntry.TYPE:
+ add(CompressedEntry.decode(in));
+ break;
+ case CertificateEntry.TYPE:
+ add(CertificateEntry.decode(in));
+ break;
+ case PublicKeyEntry.TYPE:
+ add(PublicKeyEntry.decode(in));
+ break;
+ case PrivateKeyEntry.TYPE:
+ add(PrivateKeyEntry.decode(in));
+ break;
+ case CertPathEntry.TYPE:
+ add(CertPathEntry.decode(in));
+ break;
+ case BinaryDataEntry.TYPE:
+ add(BinaryDataEntry.decode(in));
+ break;
+ case -1:
+ return;
+ default:
+ throw new MalformedKeyringException("unknown type " + type);
+ }
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private void makeAliasList()
+ {
+ if (entries.isEmpty())
+ return;
+ StringBuffer buf = new StringBuffer();
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ if (entry instanceof EnvelopeEntry)
+ {
+ buf.append(((EnvelopeEntry) entry).getAliasList());
+ }
+ else if (entry instanceof PrimitiveEntry)
+ {
+ buf.append(((PrimitiveEntry) entry).getAlias());
+ }
+ if (it.hasNext())
+ buf.append(';');
+ }
+ properties.put("alias-list", buf.toString());
+ if (containingEnvelope != null)
+ {
+ containingEnvelope.makeAliasList();
+ }
+ }
+}
diff --git a/gnu/javax/crypto/keyring/GnuPrivateKeyring.java b/gnu/javax/crypto/keyring/GnuPrivateKeyring.java
new file mode 100644
index 000000000..d49bd0963
--- /dev/null
+++ b/gnu/javax/crypto/keyring/GnuPrivateKeyring.java
@@ -0,0 +1,328 @@
+/* GnuPrivateKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import gnu.java.security.Registry;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * <p>.</p>
+ */
+public class GnuPrivateKeyring extends BaseKeyring implements IPrivateKeyring
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int USAGE = Registry.GKR_PRIVATE_KEYS
+ | Registry.GKR_PUBLIC_CREDENTIALS;
+
+ protected String mac;
+
+ protected int maclen;
+
+ protected String cipher;
+
+ protected String mode;
+
+ protected int keylen;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public GnuPrivateKeyring(String mac, int maclen, String cipher, String mode,
+ int keylen)
+ {
+ keyring = new PasswordAuthenticatedEntry(mac, maclen, new Properties());
+ keyring2 = new CompressedEntry(new Properties());
+ keyring.add(keyring2);
+ this.mac = mac;
+ this.maclen = maclen;
+ this.cipher = cipher;
+ this.mode = mode;
+ this.keylen = keylen;
+ }
+
+ public GnuPrivateKeyring()
+ {
+ this("HMAC-SHA-1", 20, "AES", "OFB", 16);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public boolean containsPrivateKey(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return false;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof PasswordAuthenticatedEntry)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Key getPrivateKey(String alias, char[] password)
+ throws UnrecoverableKeyException
+ {
+ if (!containsAlias(alias))
+ {
+ return null;
+ }
+ List l = get(alias);
+ PasswordAuthenticatedEntry e1 = null;
+ PasswordEncryptedEntry e2 = null;
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof PasswordAuthenticatedEntry)
+ {
+ e1 = (PasswordAuthenticatedEntry) e;
+ break;
+ }
+ }
+ if (e1 == null)
+ {
+ return null;
+ }
+ try
+ {
+ e1.verify(password);
+ }
+ catch (Exception e)
+ {
+ throw new UnrecoverableKeyException("authentication failed");
+ }
+ for (Iterator it = e1.getEntries().iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof PasswordEncryptedEntry)
+ {
+ e2 = (PasswordEncryptedEntry) e;
+ break;
+ }
+ }
+ if (e2 == null)
+ {
+ return null;
+ }
+ try
+ {
+ e2.decrypt(password);
+ }
+ catch (Exception e)
+ {
+ throw new UnrecoverableKeyException("decryption failed");
+ }
+ for (Iterator it = e2.get(alias).iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof PrivateKeyEntry)
+ {
+ return ((PrivateKeyEntry) e).getKey();
+ }
+ }
+ return null;
+ }
+
+ public void putPrivateKey(String alias, Key key, char[] password)
+ {
+ if (containsPrivateKey(alias))
+ {
+ return;
+ }
+ alias = fixAlias(alias);
+ Properties p = new Properties();
+ p.put("alias", alias);
+ PrivateKeyEntry pke = new PrivateKeyEntry(key, new Date(), p);
+ PasswordEncryptedEntry enc = new PasswordEncryptedEntry(cipher, mode,
+ keylen,
+ new Properties());
+ PasswordAuthenticatedEntry auth = new PasswordAuthenticatedEntry(
+ mac,
+ maclen,
+ new Properties());
+ enc.add(pke);
+ auth.add(enc);
+ try
+ {
+ enc.encode(null, password);
+ auth.encode(null, password);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException(ioe.toString());
+ }
+ keyring.add(auth);
+ }
+
+ public boolean containsPublicKey(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return false;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof PublicKeyEntry)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public PublicKey getPublicKey(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return null;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof PublicKeyEntry)
+ {
+ return ((PublicKeyEntry) e).getKey();
+ }
+ }
+ return null;
+ }
+
+ public void putPublicKey(String alias, PublicKey key)
+ {
+ if (containsPublicKey(alias))
+ {
+ return;
+ }
+ Properties p = new Properties();
+ p.put("alias", fixAlias(alias));
+ add(new PublicKeyEntry(key, new Date(), p));
+ }
+
+ public boolean containsCertPath(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return false;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof CertPathEntry)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Certificate[] getCertPath(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return null;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof CertPathEntry)
+ {
+ return ((CertPathEntry) e).getCertPath();
+ }
+ }
+ return null;
+ }
+
+ public void putCertPath(String alias, Certificate[] path)
+ {
+ if (containsCertPath(alias))
+ {
+ return;
+ }
+ Properties p = new Properties();
+ p.put("alias", fixAlias(alias));
+ add(new CertPathEntry(path, new Date(), p));
+ }
+
+ protected void load(InputStream in, char[] password) throws IOException
+ {
+ if (in.read() != USAGE)
+ {
+ throw new MalformedKeyringException("incompatible keyring usage");
+ }
+ if (in.read() != PasswordAuthenticatedEntry.TYPE)
+ {
+ throw new MalformedKeyringException(
+ "expecting password-authenticated entry tag");
+ }
+ keyring = PasswordAuthenticatedEntry.decode(new DataInputStream(in),
+ password);
+ }
+
+ protected void store(OutputStream out, char[] password) throws IOException
+ {
+ out.write(USAGE);
+ keyring.encode(new DataOutputStream(out), password);
+ }
+}
diff --git a/gnu/javax/crypto/keyring/GnuPublicKeyring.java b/gnu/javax/crypto/keyring/GnuPublicKeyring.java
new file mode 100644
index 000000000..318eb036f
--- /dev/null
+++ b/gnu/javax/crypto/keyring/GnuPublicKeyring.java
@@ -0,0 +1,146 @@
+/* GnuPublicKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import java.security.cert.Certificate;
+
+import gnu.java.security.Registry;
+
+public class GnuPublicKeyring extends BaseKeyring implements IPublicKeyring
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ public static final int USAGE = Registry.GKR_CERTIFICATES;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public GnuPublicKeyring(String mac, int macLen)
+ {
+ keyring = new PasswordAuthenticatedEntry(mac, macLen, new Properties());
+ keyring2 = new CompressedEntry(new Properties());
+ keyring.add(keyring2);
+ }
+
+ public GnuPublicKeyring()
+ {
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public boolean containsCertificate(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return false;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ if (it.next() instanceof CertificateEntry)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Certificate getCertificate(String alias)
+ {
+ if (!containsAlias(alias))
+ {
+ return null;
+ }
+ List l = get(alias);
+ for (Iterator it = l.iterator(); it.hasNext();)
+ {
+ Entry e = (Entry) it.next();
+ if (e instanceof CertificateEntry)
+ {
+ return ((CertificateEntry) e).getCertificate();
+ }
+ }
+ return null;
+ }
+
+ public void putCertificate(String alias, Certificate cert)
+ {
+ if (containsCertificate(alias))
+ {
+ return;
+ }
+ Properties p = new Properties();
+ p.put("alias", fixAlias(alias));
+ add(new CertificateEntry(cert, new Date(), p));
+ }
+
+ protected void load(InputStream in, char[] password) throws IOException
+ {
+ if (in.read() != USAGE)
+ {
+ throw new MalformedKeyringException("incompatible keyring usage");
+ }
+ if (in.read() != PasswordAuthenticatedEntry.TYPE)
+ {
+ throw new MalformedKeyringException(
+ "expecting password-authenticated entry tag");
+ }
+ keyring = PasswordAuthenticatedEntry.decode(new DataInputStream(in),
+ password);
+ }
+
+ protected void store(OutputStream out, char[] password) throws IOException
+ {
+ out.write(USAGE);
+ keyring.encode(new DataOutputStream(out), password);
+ }
+}
diff --git a/gnu/javax/crypto/keyring/IKeyring.java b/gnu/javax/crypto/keyring/IKeyring.java
new file mode 100644
index 000000000..56f467df2
--- /dev/null
+++ b/gnu/javax/crypto/keyring/IKeyring.java
@@ -0,0 +1,164 @@
+/* IKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>The top-level interface to a <i>keyring:</i> a file that is used to
+ * store and protect public and private cryptographic keys.</p>
+ *
+ * <p>A <i>keyring</i> is modelled as a mapping of one <i>alias</i> to one or
+ * more <i>entries</i> (optionally of different types).</p>
+ *
+ * <p>See also the sub-interfaces {@link IPublicKeyring} and
+ * {@link IPrivateKeyring} for special types of <i>keyrings</i> --the difference
+ * being in the type of entries they contain.</p>
+ */
+public interface IKeyring
+{
+
+ /**
+ * <p>Property name for the source of data to load the keyring from. The
+ * value mapped must be a {@link java.io.InputStream}.</p>
+ */
+ public static final String KEYRING_DATA_IN = "gnu.crypto.keyring.data.in";
+
+ /**
+ * <p>Property name for the data sink to store the keyring to. The value
+ * mapped must be a {@link java.io.OutputStream}.</p>
+ */
+ public static final String KEYRING_DATA_OUT = "gun.crypto.keyring.data.out";
+
+ /**
+ * <p>Property name for the keyring's top-level password, used to
+ * authenticate and/or transform the store itself. The mapped value must be a
+ * char array.</p>
+ */
+ public static final String KEYRING_PASSWORD = "gnu.crypto.keyring.password";
+
+ /**
+ * <p>Loads a keyring into memory.</p>
+ *
+ * <p>What happens to the current contents of this keyring? are the new ones
+ * merged with the current ones or do they simply replace them?</p>
+ *
+ * @param attributes The attributes that designate the source where the store
+ * is to be loaded from. What happens
+ * @throws IllegalArgumentException If the attributes are inappropriate.
+ * @throws IOException If the keyring file cannot be read.
+ * @throws SecurityException If the given password is incorrect, or if the
+ * top-level authentication or decryption fails.
+ */
+ void load(Map attributes) throws IOException;
+
+ /**
+ * <p>Stores the contents of this keyring to persistent storage as specified
+ * by the designated <code>attributes</code>.</p>
+ *
+ * @param attributes the attributes that define where the contents of this
+ * keyring will be stored.
+ * @throws IOException if an exception occurs during the process.
+ */
+ void store(Map attributes) throws IOException;
+
+ /**
+ * <p>Resets this keyring, clearing all sensitive data. This method always
+ * suceeds.</p>
+ */
+ void reset();
+
+ /**
+ * <p>Returns the number of entries in this keyring.</p>
+ *
+ * @return The number of current entries in this keyring.
+ */
+ int size();
+
+ /**
+ * <p>Returns an {@link Enumeration} of all aliases (instances of
+ * {@link String}) in this keyring.</p>
+ *
+ * @return The enumeration of {@link String}s each representing an
+ * <i>alias</i> found in this keyring.
+ */
+ Enumeration aliases();
+
+ /**
+ * Tests whether or not this keyring contains the given alias.
+ *
+ * @param alias The alias to check.
+ * @return true if this keyring contains the alias.
+ */
+ boolean containsAlias(String alias);
+
+ /**
+ * <p>Returns a {@link List} of entries (instances of {@link Entry}) for the
+ * given <code>alias</code>, or <code>null</code> if there no such entry
+ * exists.</p>
+ *
+ * @param alias The alias of the entry(ies) to return.
+ * @return A list of all entries (instances of {@link Entry} that have the
+ * given <code>alias</code>, or <code>null</code> if no one {@link Entry} can
+ * be found with the designated <code>alias</code>.
+ */
+ List get(String alias);
+
+ /**
+ * <p>Adds a designated {@link Entry} to this keyring.</p>
+ *
+ * <p>What happens if there is already an entry with the same alias?</p>
+ *
+ * @param entry The entry to put in this keyring.
+ */
+ void add(Entry entry);
+
+ /**
+ * <p>Removes an entry with the designated <code>alias</code> from this
+ * keyring. Does nothing if there was no such entry.</p>
+ *
+ * <p>What happens if there are more than one?</p>
+ *
+ * @param alias The alias of the entry to remove.
+ */
+ void remove(String alias);
+}
diff --git a/gnu/javax/crypto/keyring/IPrivateKeyring.java b/gnu/javax/crypto/keyring/IPrivateKeyring.java
new file mode 100644
index 000000000..66bbd84f5
--- /dev/null
+++ b/gnu/javax/crypto/keyring/IPrivateKeyring.java
@@ -0,0 +1,142 @@
+/* IPrivateKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+
+/**
+ * <p>An interface to private, or "personal", keyrings, which contain private
+ * credentials. The contract is that each such entry is known by a unique
+ * <i>alias</i>.</p>
+ *
+ * <p>What about public keys? and certificate-path?</p>
+ */
+public interface IPrivateKeyring extends IKeyring
+{
+
+ /**
+ * <p>Tests if this keyring contains a private key entry with the given
+ * <code>alias</code>.</p>
+ *
+ * @param alias The alias to check.
+ * @return <code>true</code> if this keyring contains a private key with the
+ * given <code>alias</code>; <code>false</code> otherwise.</p>
+ */
+ boolean containsPrivateKey(String alias);
+
+ /**
+ * <p>Returns the private key with the given <code>alias</code>.</p>
+ *
+ * @param alias The alias of the private key to find.
+ * @param password The password of the private key.
+ * @return The private, or secret, key if one is found; <code>null</code> if
+ * none were found.
+ * @throws UnrecoverableKeyException If the private key could not be
+ * recovered, possibly due to a bad password.
+ */
+ Key getPrivateKey(String alias, char[] password)
+ throws UnrecoverableKeyException;
+
+ /**
+ * <p>Adds a private key to this keyring.</p>
+ *
+ * @param alias The alias of the private key.
+ * @param key The private key.
+ * @param password The password used to protect this private key.
+ */
+ void putPrivateKey(String alias, Key key, char[] password);
+
+ /**
+ * <p>Checks if this keyring contains a public key with the given
+ * <code>alias</code>.</p>
+ *
+ * @param alias The alias to test.
+ * @return <code>true</code> if this keyring contains a public key entry with
+ * the given <code>alias</code>; <code>false</code> otherwise.
+ */
+ boolean containsPublicKey(String alias);
+
+ /**
+ * <p>Returns the public key with the given <code>alias</code>, or
+ * <code>null</code> if there is no such entry.</p>
+ *
+ * @param alias The alias of the public key to find.
+ * @return The public key; or <code>null</code> if none were found.
+ */
+ PublicKey getPublicKey(String alias);
+
+ /**
+ * <p>Sets a public key entry.</p>
+ *
+ * @param alias The alias for this public key.
+ * @param key The public key.
+ */
+ void putPublicKey(String alias, PublicKey key);
+
+ /**
+ * <p>Checks if this keyring contains a certificate path with the given
+ * <code>alias</code>.</p>
+ *
+ * @param alias The alias to check.
+ * @return <code>true</code> if this keyring contains a certificate path with
+ * the given <code>alias</code>; <code>false</code> otherwise.
+ */
+ boolean containsCertPath(String alias);
+
+ /**
+ * <p>Returns the certificate path with the given <code>alias</code>, or
+ * <code>null</code> if there is no such entry.</p>
+ *
+ * @param alias The alias of the certificate path to find.
+ * @return The certificate path for the designated <code>alias</code>; or
+ * <code>null</code> if none were found.
+ */
+ Certificate[] getCertPath(String alias);
+
+ /**
+ * <p>Sets a certificate path entry.</p>
+ *
+ * @param alias The alias for this certificate path.
+ * @param path The certificate path.
+ */
+ void putCertPath(String alias, Certificate[] path);
+}
diff --git a/gnu/javax/crypto/keyring/IPublicKeyring.java b/gnu/javax/crypto/keyring/IPublicKeyring.java
new file mode 100644
index 000000000..ccf9ca73b
--- /dev/null
+++ b/gnu/javax/crypto/keyring/IPublicKeyring.java
@@ -0,0 +1,81 @@
+/* IPublicKeyring.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.security.cert.Certificate;
+
+/**
+ * <p>An interface for keyrings that contain trusted (by the owner) public
+ * credentials (incl. certificates).</p>
+ *
+ * @see IKeyring
+ */
+public interface IPublicKeyring extends IKeyring
+{
+
+ /**
+ * <p>Tests if this keyring contains a certificate entry with the specified
+ * <code>alias</code>.</p>
+ *
+ * @param alias The alias of the certificate to check.
+ * @return <code>true</code> if this keyring contains a certificate entry
+ * that has the given <code>alias</code>; <code>false</code> otherwise.
+ */
+ boolean containsCertificate(String alias);
+
+ /**
+ * <p>Returns a certificate that has the given <code>alias</code>, or
+ * <code>null</code> if this keyring has no such entry.</p>
+ *
+ * @param alias The alias of the certificate to find.
+ * @return The certificate with the designated <code>alias</code>, or
+ * <code>null</code> if none found.
+ */
+ Certificate getCertificate(String alias);
+
+ /**
+ * <p>Adds a certificate in this keyring, with the given <code>alias</code>.</p>
+ *
+ * <p>What happens if there is already a certificate entry with this alias?</p>
+ *
+ * @param alias The alias of this certificate entry.
+ * @param cert The certificate.
+ */
+ void putCertificate(String alias, Certificate cert);
+}
diff --git a/gnu/javax/crypto/keyring/MalformedKeyringException.java b/gnu/javax/crypto/keyring/MalformedKeyringException.java
new file mode 100644
index 000000000..44c953946
--- /dev/null
+++ b/gnu/javax/crypto/keyring/MalformedKeyringException.java
@@ -0,0 +1,58 @@
+/* MalformedKeyringException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.IOException;
+
+public class MalformedKeyringException extends IOException
+{
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public MalformedKeyringException()
+ {
+ super();
+ }
+
+ public MalformedKeyringException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java b/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java
new file mode 100644
index 000000000..7fed7c40c
--- /dev/null
+++ b/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java
@@ -0,0 +1,148 @@
+/* MaskableEnvelopeEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An envelope entry that can be "masked" -- placed in a state where the
+ * envelope's contents cannot be accessed, due to the envelope not being
+ * fully decoded, for example.
+ */
+public abstract class MaskableEnvelopeEntry extends EnvelopeEntry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The masked state. */
+ protected boolean masked;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public MaskableEnvelopeEntry(int type, Properties properties)
+ {
+ super(type, properties);
+ }
+
+ protected MaskableEnvelopeEntry(int type)
+ {
+ super(type);
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Sets the masked state to the specified value.
+ *
+ * @param masked The new masked state.
+ */
+ protected final void setMasked(boolean masked)
+ {
+ this.masked = masked;
+ }
+
+ /**
+ * Gets the masked state of this object. Certain operations on this object
+ * will fail if it is masked.
+ *
+ * @return The current masked state.
+ */
+ public boolean isMasked()
+ {
+ return masked;
+ }
+
+ public void add(Entry entry)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ super.add(entry);
+ }
+
+ public boolean containsEntry(Entry entry)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ return super.containsEntry(entry);
+ }
+
+ public List getEntries()
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ return new ArrayList(entries);
+ }
+
+ public List get(String alias)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ return super.get(alias);
+ }
+
+ public boolean remove(Entry entry)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ return super.remove(entry);
+ }
+
+ public void remove(String alias)
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("masked envelope");
+ }
+ super.remove(alias);
+ }
+}
diff --git a/gnu/javax/crypto/keyring/MeteredInputStream.java b/gnu/javax/crypto/keyring/MeteredInputStream.java
new file mode 100644
index 000000000..fcf2be746
--- /dev/null
+++ b/gnu/javax/crypto/keyring/MeteredInputStream.java
@@ -0,0 +1,137 @@
+/* MeteredInputStream.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+final class MeteredInputStream extends FilterInputStream
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ private int count;
+
+ private final int limit;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ MeteredInputStream(InputStream in, int limit)
+ {
+ super(in);
+ if (limit < 0)
+ throw new IllegalArgumentException("limit must be nonnegative");
+ this.limit = limit;
+ count = 0;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Tests if the number of bytes read has reached the limit.
+ *
+ * @return True if the limit has been reached.
+ */
+ public boolean limitReached()
+ {
+ return count == limit;
+ }
+
+ public int available() throws IOException
+ {
+ return Math.min(in.available(), limit - count);
+ }
+
+ public void close() throws IOException
+ {
+ in.close();
+ }
+
+ public void mark(int readLimit)
+ {
+ }
+
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ public int read() throws IOException
+ {
+ if (limitReached())
+ return -1;
+ int i = in.read();
+ if (i != -1)
+ count++;
+ return i;
+ }
+
+ public int read(byte[] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public int read(byte[] buf, int off, int len) throws IOException
+ {
+ if (limitReached())
+ return -1;
+ int i = in.read(buf, off, Math.min(len, limit - count));
+ if (i != -1)
+ count += i;
+ return i;
+ }
+
+ public void reset() throws IOException
+ {
+ }
+
+ public long skip(long len) throws IOException
+ {
+ if (limitReached())
+ return 0L;
+ len = Math.min(len, limit - count);
+ len = in.skip(len);
+ count += (int) len;
+ return len;
+ }
+}
diff --git a/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java b/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java
new file mode 100644
index 000000000..2e3a0d145
--- /dev/null
+++ b/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java
@@ -0,0 +1,285 @@
+/* PasswordAuthenticatedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+import gnu.javax.crypto.mac.MacInputStream;
+import gnu.javax.crypto.mac.MacOutputStream;
+import gnu.javax.crypto.prng.IPBE;
+import gnu.javax.crypto.prng.PRNGFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.HashMap;
+
+/**
+ * <p>An entry authenticated with a password-based MAC.</p>
+ */
+public final class PasswordAuthenticatedEntry extends MaskableEnvelopeEntry
+ implements PasswordProtectedEntry, Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int TYPE = 3;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public PasswordAuthenticatedEntry(String mac, int maclen,
+ Properties properties)
+ {
+ super(TYPE, properties);
+
+ if (mac == null || mac.length() == 0)
+ {
+ throw new IllegalArgumentException("no MAC specified");
+ }
+ this.properties.put("mac", mac);
+ this.properties.put("maclen", String.valueOf(maclen));
+ setMasked(false);
+ }
+
+ private PasswordAuthenticatedEntry()
+ {
+ super(TYPE);
+ setMasked(true);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static PasswordAuthenticatedEntry decode(DataInputStream in,
+ char[] password)
+ throws IOException
+ {
+ PasswordAuthenticatedEntry entry = new PasswordAuthenticatedEntry();
+ entry.properties.decode(in);
+ IMac mac = entry.getMac(password);
+ int len = in.readInt() - mac.macSize();
+ MeteredInputStream min = new MeteredInputStream(in, len);
+ MacInputStream macin = new MacInputStream(min, mac);
+ DataInputStream in2 = new DataInputStream(macin);
+ entry.setMasked(false);
+ entry.decodeEnvelope(in2);
+ byte[] macValue = new byte[mac.macSize()];
+ in.readFully(macValue);
+ if (!Arrays.equals(macValue, mac.digest()))
+ {
+ throw new MalformedKeyringException("MAC verification failed");
+ }
+ return entry;
+ }
+
+ public static PasswordAuthenticatedEntry decode(DataInputStream in)
+ throws IOException
+ {
+ PasswordAuthenticatedEntry entry = new PasswordAuthenticatedEntry();
+ entry.defaultDecode(in);
+ if (!entry.properties.containsKey("mac"))
+ {
+ throw new MalformedKeyringException("no MAC");
+ }
+ if (!entry.properties.containsKey("maclen"))
+ {
+ throw new MalformedKeyringException("no MAC length");
+ }
+ if (!entry.properties.containsKey("salt"))
+ {
+ throw new MalformedKeyringException("no salt");
+ }
+ return entry;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public void verify(char[] password)
+ {
+ if (!isMasked() || payload == null)
+ {
+ return;
+ }
+ IMac m = null;
+ try
+ {
+ m = getMac(password);
+ }
+ catch (Exception x)
+ {
+ throw new IllegalArgumentException(x.toString());
+ }
+
+ m.update(payload, 0, payload.length - m.macSize());
+ byte[] macValue = new byte[m.macSize()];
+ System.arraycopy(payload, payload.length - macValue.length, macValue, 0,
+ macValue.length);
+ if (!Arrays.equals(macValue, m.digest()))
+ {
+ throw new IllegalArgumentException("MAC verification failed");
+ }
+ try
+ {
+ DataInputStream in = new DataInputStream(
+ new ByteArrayInputStream(
+ payload,
+ 0,
+ payload.length
+ - m.macSize()));
+ decodeEnvelope(in);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("malformed keyring fragment");
+ }
+ setMasked(false);
+ payload = null;
+ }
+
+ public void authenticate(char[] password) throws IOException
+ {
+ if (isMasked())
+ {
+ throw new IllegalStateException("entry is masked");
+ }
+ byte[] salt = new byte[8];
+ new SecureRandom ().nextBytes (salt);
+ properties.put("salt", Util.toString(salt));
+ IMac m = getMac(password);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ MacOutputStream macout = new MacOutputStream(bout, m);
+ DataOutputStream out2 = new DataOutputStream(macout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ entry.encode(out2);
+ }
+ bout.write(m.digest());
+ payload = bout.toByteArray();
+ }
+
+ public void encode(DataOutputStream out, char[] password) throws IOException
+ {
+ authenticate(password);
+ encode(out);
+ }
+
+ protected void encodePayload(DataOutputStream out) throws IOException
+ {
+ if (payload == null)
+ {
+ throw new IllegalStateException("mac not computed");
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private IMac getMac(char[] password) throws MalformedKeyringException
+ {
+ if (!properties.containsKey("salt"))
+ {
+ throw new MalformedKeyringException("no salt");
+ }
+ byte[] salt = Util.toBytesFromString(properties.get("salt"));
+ IMac mac = MacFactory.getInstance(properties.get("mac"));
+ if (mac == null)
+ {
+ throw new MalformedKeyringException("no such mac: "
+ + properties.get("mac"));
+ }
+ int keylen = mac.macSize();
+ int maclen = 0;
+ if (!properties.containsKey("maclen"))
+ {
+ throw new MalformedKeyringException("no MAC length");
+ }
+ try
+ {
+ maclen = Integer.parseInt(properties.get("maclen"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new MalformedKeyringException("bad MAC length");
+ }
+
+ HashMap pbAttr = new HashMap();
+ pbAttr.put(IPBE.PASSWORD, password);
+ pbAttr.put(IPBE.SALT, salt);
+ pbAttr.put(IPBE.ITERATION_COUNT, ITERATION_COUNT);
+ IRandom kdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA");
+ kdf.init(pbAttr);
+
+ byte[] dk = new byte[keylen];
+ try
+ {
+ kdf.nextBytes(dk, 0, keylen);
+ }
+ catch (LimitReachedException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen.toString());
+ }
+
+ HashMap macAttr = new HashMap();
+ macAttr.put(IMac.MAC_KEY_MATERIAL, dk);
+ macAttr.put(IMac.TRUNCATED_SIZE, new Integer(maclen));
+ try
+ {
+ mac.init(macAttr);
+ }
+ catch (InvalidKeyException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen.toString());
+ }
+ return mac;
+ }
+}
diff --git a/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java b/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java
new file mode 100644
index 000000000..26b4032bd
--- /dev/null
+++ b/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java
@@ -0,0 +1,301 @@
+/* PasswordEncryptedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+import gnu.javax.crypto.pad.IPad;
+import gnu.javax.crypto.pad.PadFactory;
+import gnu.javax.crypto.pad.WrongPaddingException;
+import gnu.javax.crypto.prng.IPBE;
+import gnu.javax.crypto.prng.PRNGFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * An envelope that is encrypted with a password-derived key.
+ */
+public class PasswordEncryptedEntry extends MaskableEnvelopeEntry implements
+ PasswordProtectedEntry, Registry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 1;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ public PasswordEncryptedEntry(String cipher, String mode, int keylen,
+ Properties properties)
+ {
+ super(TYPE, properties);
+ if ((cipher == null || cipher.length() == 0)
+ || (mode == null || mode.length() == 0))
+ {
+ throw new IllegalArgumentException("cipher nor mode can be empty");
+ }
+ this.properties.put("cipher", cipher);
+ this.properties.put("mode", mode);
+ this.properties.put("keylen", String.valueOf(keylen));
+ setMasked(false);
+ }
+
+ private PasswordEncryptedEntry()
+ {
+ super(TYPE);
+ setMasked(true);
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ public static PasswordEncryptedEntry decode(DataInputStream in,
+ char[] password)
+ throws IOException
+ {
+ PasswordEncryptedEntry entry = decode(in);
+ try
+ {
+ entry.decrypt(password);
+ }
+ catch (WrongPaddingException wpe)
+ {
+ throw new MalformedKeyringException("wrong padding in decrypted data");
+ }
+ return entry;
+ }
+
+ public static PasswordEncryptedEntry decode(DataInputStream in)
+ throws IOException
+ {
+ PasswordEncryptedEntry entry = new PasswordEncryptedEntry();
+ entry.defaultDecode(in);
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public void decrypt(char[] password) throws IllegalArgumentException,
+ WrongPaddingException
+ {
+ if (!isMasked() || payload == null)
+ {
+ return;
+ }
+ IMode mode = getMode(password, IMode.DECRYPTION);
+ IPad padding = PadFactory.getInstance("PKCS7");
+ padding.init(mode.currentBlockSize());
+ byte[] buf = new byte[payload.length];
+ int count = 0;
+ for (int i = 0; i < payload.length; i++)
+ {
+ mode.update(payload, count, buf, count);
+ count += mode.currentBlockSize();
+ }
+ int padlen = padding.unpad(buf, 0, buf.length);
+ DataInputStream in = new DataInputStream(
+ new ByteArrayInputStream(
+ buf,
+ 0,
+ buf.length
+ - padlen));
+ try
+ {
+ decodeEnvelope(in);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException("decryption failed");
+ }
+ setMasked(false);
+ payload = null;
+ }
+
+ public void encrypt(char[] password) throws IOException
+ {
+ byte[] salt = new byte[8];
+ new SecureRandom ().nextBytes (salt);
+ properties.put("salt", Util.toString(salt));
+ IMode mode = getMode(password, IMode.ENCRYPTION);
+ IPad pad = PadFactory.getInstance("PKCS7");
+ pad.init(mode.currentBlockSize());
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ DataOutputStream out2 = new DataOutputStream(bout);
+ for (Iterator it = entries.iterator(); it.hasNext();)
+ {
+ Entry entry = (Entry) it.next();
+ entry.encode(out2);
+ }
+ byte[] plaintext = bout.toByteArray();
+ byte[] padding = pad.pad(plaintext, 0, plaintext.length);
+ payload = new byte[plaintext.length + padding.length];
+ byte[] lastBlock = new byte[mode.currentBlockSize()];
+ int l = mode.currentBlockSize() - padding.length;
+ System.arraycopy(plaintext, plaintext.length - l, lastBlock, 0, l);
+ System.arraycopy(padding, 0, lastBlock, l, padding.length);
+ int count = 0;
+ while (count + mode.currentBlockSize() < plaintext.length)
+ {
+ mode.update(plaintext, count, payload, count);
+ count += mode.currentBlockSize();
+ }
+ mode.update(lastBlock, 0, payload, count);
+ }
+
+ public void encode(DataOutputStream out, char[] password) throws IOException
+ {
+ encrypt(password);
+ encode(out);
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ if (payload == null)
+ {
+ throw new IllegalStateException("not encrypted");
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private IMode getMode(char[] password, int state)
+ {
+ String s = properties.get("salt");
+ if (s == null)
+ {
+ throw new IllegalArgumentException("no salt");
+ }
+ byte[] salt = Util.toBytesFromString(s);
+ IBlockCipher cipher = CipherFactory.getInstance(properties.get("cipher"));
+ if (cipher == null)
+ {
+ throw new IllegalArgumentException("no such cipher: "
+ + properties.get("cipher"));
+ }
+ int blockSize = cipher.defaultBlockSize();
+ if (properties.containsKey("block-size"))
+ {
+ try
+ {
+ blockSize = Integer.parseInt(properties.get("block-size"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new IllegalArgumentException("bad block size: "
+ + nfe.getMessage());
+ }
+ }
+ IMode mode = ModeFactory.getInstance(properties.get("mode"), cipher,
+ blockSize);
+ if (mode == null)
+ {
+ throw new IllegalArgumentException("no such mode: "
+ + properties.get("mode"));
+ }
+
+ HashMap pbAttr = new HashMap();
+ pbAttr.put(IPBE.PASSWORD, password);
+ pbAttr.put(IPBE.SALT, salt);
+ pbAttr.put(IPBE.ITERATION_COUNT, ITERATION_COUNT);
+ IRandom kdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA");
+ kdf.init(pbAttr);
+
+ int keylen = 0;
+ if (!properties.containsKey("keylen"))
+ {
+ throw new IllegalArgumentException("no key length");
+ }
+ try
+ {
+ keylen = Integer.parseInt(properties.get("keylen"));
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ byte[] dk = new byte[keylen];
+ byte[] iv = new byte[blockSize];
+ try
+ {
+ kdf.nextBytes(dk, 0, keylen);
+ kdf.nextBytes(iv, 0, blockSize);
+ }
+ catch (LimitReachedException shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen.toString());
+ }
+ HashMap modeAttr = new HashMap();
+ modeAttr.put(IMode.KEY_MATERIAL, dk);
+ modeAttr.put(IMode.STATE, new Integer(state));
+ modeAttr.put(IMode.IV, iv);
+ try
+ {
+ mode.init(modeAttr);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new IllegalArgumentException(ike.toString());
+ }
+ return mode;
+ }
+}
diff --git a/gnu/javax/crypto/keyring/PasswordProtectedEntry.java b/gnu/javax/crypto/keyring/PasswordProtectedEntry.java
new file mode 100644
index 000000000..0dcf73eb8
--- /dev/null
+++ b/gnu/javax/crypto/keyring/PasswordProtectedEntry.java
@@ -0,0 +1,66 @@
+/* PasswordProtectedEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public interface PasswordProtectedEntry
+{
+
+ // Constant.
+ // ------------------------------------------------------------------------
+
+ /**
+ * The iteration count for password-based KDFs.
+ */
+ Integer ITERATION_COUNT = new Integer(1000);
+
+ // Method.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Encodes this entry, protected by a password.
+ *
+ * @param out The output stream to encode to.
+ * @param password The password.
+ * @throws IOException If an I/O error occurs.
+ */
+ void encode(DataOutputStream out, char[] password) throws IOException;
+}
diff --git a/gnu/javax/crypto/keyring/PrimitiveEntry.java b/gnu/javax/crypto/keyring/PrimitiveEntry.java
new file mode 100644
index 000000000..4c9ff0ff1
--- /dev/null
+++ b/gnu/javax/crypto/keyring/PrimitiveEntry.java
@@ -0,0 +1,129 @@
+/* PrimitiveEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.util.Date;
+
+/**
+ * A primitive entry is an entry that contains a single cryptographic entity.
+ */
+public abstract class PrimitiveEntry extends Entry
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ /** The creation date. */
+ protected Date creationDate;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ protected PrimitiveEntry(int type, Date creationDate, Properties properties)
+ {
+ super(type, properties);
+ if (creationDate == null)
+ {
+ this.creationDate = new Date();
+ }
+ else
+ {
+ this.creationDate = (Date) creationDate.clone();
+ }
+ if (!this.properties.containsKey("alias")
+ || this.properties.get("alias").length() == 0)
+ {
+ throw new IllegalArgumentException(
+ "primitive entries MUST have an alias");
+ }
+ this.properties.put("creation-date", String.valueOf(creationDate.getTime()));
+ }
+
+ protected PrimitiveEntry(int type)
+ {
+ super(type);
+ }
+
+ // Instance method.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the alias of this primitive entry.
+ *
+ * @return The alias.
+ */
+ public String getAlias()
+ {
+ return properties.get("alias");
+ }
+
+ /**
+ * Returns the creation date of this primitive entry.
+ *
+ * @return The creation date.
+ */
+ public Date getCreationDate()
+ {
+ return (Date) creationDate.clone();
+ }
+
+ public boolean equals(Object object)
+ {
+ if (!getClass().equals(object.getClass()))
+ return false;
+ return getAlias().equals(((PrimitiveEntry) object).getAlias());
+ }
+
+ protected final void makeCreationDate() throws MalformedKeyringException
+ {
+ String s = properties.get("creation-date");
+ if (s == null)
+ {
+ throw new MalformedKeyringException("no creation date");
+ }
+ try
+ {
+ creationDate = new Date(Long.parseLong(s));
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new MalformedKeyringException("invalid creation date");
+ }
+ }
+}
diff --git a/gnu/javax/crypto/keyring/PrivateKeyEntry.java b/gnu/javax/crypto/keyring/PrivateKeyEntry.java
new file mode 100644
index 000000000..306349915
--- /dev/null
+++ b/gnu/javax/crypto/keyring/PrivateKeyEntry.java
@@ -0,0 +1,221 @@
+/* PrivateKeyEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.key.KeyPairCodecFactory;
+import gnu.java.security.key.dss.DSSPrivateKey;
+import gnu.java.security.key.rsa.GnuRSAPrivateKey;
+
+import gnu.javax.crypto.key.GnuSecretKey;
+import gnu.javax.crypto.key.dh.GnuDHPrivateKey;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Date;
+
+/**
+ * <p>An immutable class representing a private or secret key entry.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class PrivateKeyEntry extends PrimitiveEntry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int TYPE = 7;
+
+ /** The key. */
+ private Key key;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Creates a new key entry.</p>
+ *
+ * @param key The key.
+ * @param creationDate The entry creation date.
+ * @param properties The entry properties.
+ * @throws IllegalArgumentException If any parameter is null.
+ */
+ public PrivateKeyEntry(Key key, Date creationDate, Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+
+ if (key == null)
+ {
+ throw new IllegalArgumentException("no private key");
+ }
+ if (!(key instanceof PrivateKey) && !(key instanceof GnuSecretKey))
+ {
+ throw new IllegalArgumentException("not a private or secret key");
+ }
+ this.key = key;
+ }
+
+ private PrivateKeyEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static PrivateKeyEntry decode(DataInputStream in) throws IOException
+ {
+ PrivateKeyEntry entry = new PrivateKeyEntry();
+ entry.defaultDecode(in);
+ String type = entry.properties.get("type");
+ if (type == null)
+ {
+ throw new MalformedKeyringException("no key type");
+ }
+ if (type.equalsIgnoreCase("RAW-DSS"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
+ entry.key = coder.decodePrivateKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW-RSA"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("rsa");
+ entry.key = coder.decodePrivateKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW-DH"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dh");
+ entry.key = coder.decodePrivateKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW"))
+ {
+ entry.key = new GnuSecretKey(entry.payload, null);
+ }
+ else if (type.equalsIgnoreCase("PKCS8"))
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ entry.key = kf.generatePrivate(new PKCS8EncodedKeySpec(
+ entry.payload));
+ }
+ catch (Exception x)
+ {
+ }
+ if (entry.key == null)
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance("DSA");
+ entry.key = kf.generatePrivate(new PKCS8EncodedKeySpec(
+ entry.payload));
+ }
+ catch (Exception x)
+ {
+ }
+ if (entry.key == null)
+ {
+ throw new MalformedKeyringException(
+ "could not decode PKCS#8 key");
+ }
+ }
+ }
+ else
+ {
+ throw new MalformedKeyringException("unsupported key type " + type);
+ }
+ return entry;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns this entry's key.</p>
+ *
+ * @return The key.
+ */
+ public Key getKey()
+ {
+ return key;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ String format = key.getFormat();
+ if (key instanceof DSSPrivateKey)
+ {
+ properties.put("type", "RAW-DSS");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
+ payload = coder.encodePrivateKey((PrivateKey) key);
+ }
+ else if (key instanceof GnuRSAPrivateKey)
+ {
+ properties.put("type", "RAW-RSA");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("rsa");
+ payload = coder.encodePrivateKey((PrivateKey) key);
+ }
+ else if (key instanceof GnuDHPrivateKey)
+ {
+ properties.put("type", "RAW-DH");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dh");
+ payload = coder.encodePrivateKey((PrivateKey) key);
+ }
+ else if (key instanceof GnuSecretKey)
+ {
+ properties.put("type", "RAW");
+ payload = key.getEncoded();
+ }
+ else if (format != null && format.equals("PKCS#8"))
+ {
+ properties.put("type", "PKCS8");
+ payload = key.getEncoded();
+ }
+ else
+ {
+ throw new IllegalArgumentException("unsupported private key");
+ }
+ }
+}
diff --git a/gnu/javax/crypto/keyring/Properties.java b/gnu/javax/crypto/keyring/Properties.java
new file mode 100644
index 000000000..646b5711d
--- /dev/null
+++ b/gnu/javax/crypto/keyring/Properties.java
@@ -0,0 +1,227 @@
+/* Properties.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A set of <code>(name =&gt; value)</code> pairs used in keyring entries.
+ * Keys and values are simple strings, with the key never being empty and
+ * always treated case-insensitively.
+ */
+public class Properties implements Cloneable
+{
+
+ // Field.
+ // ------------------------------------------------------------------------
+
+ private HashMap props;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new properties object.
+ */
+ public Properties()
+ {
+ props = new HashMap();
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Removes all properties from this object.
+ */
+ public void clear()
+ {
+ props.clear();
+ }
+
+ /**
+ * Creates a copy of this properties object.
+ *
+ * @return The copy.
+ */
+ public Object clone()
+ {
+ Properties result = new Properties();
+ result.props.putAll(props);
+ return result;
+ }
+
+ /**
+ * Tests if this object contains a given property name.
+ *
+ * @param key The key to test.
+ * @return True if this object contains the given key.
+ */
+ public boolean containsKey(String key)
+ {
+ if (key == null || key.length() == 0)
+ {
+ return false;
+ }
+ return props.containsKey(canonicalize(key));
+ }
+
+ /**
+ * Tests if this object contains a given property value.
+ *
+ * @param value The value to test.
+ * @return True if this object contains the given value.
+ */
+ public boolean containsValue(String value)
+ {
+ if (value == null)
+ {
+ return false;
+ }
+ return props.containsValue(value);
+ }
+
+ /**
+ * Adds a new property to this object.
+ *
+ * @param key The key, which can neither be null nor empty.
+ * @param value The value, which cannot be null.
+ * @return The old value mapped by the key, if any.
+ * @throws IllegalArgumentException If either the key or value parameter
+
+ * is null, or if the key is empty.
+ */
+ public String put(String key, String value)
+ {
+ if (key == null || value == null || key.length() == 0)
+ {
+ throw new IllegalArgumentException("key nor value can be null");
+ }
+ return (String) props.put(canonicalize(key), value);
+ }
+
+ /**
+ * Returns the value mapped by the given key, or null if there is no
+ * such mapping.
+ *
+ * @param key
+ */
+ public String get(String key)
+ {
+ if (key == null || key.length() == 0)
+ {
+ return null;
+ }
+ return (String) props.get(canonicalize(key));
+ }
+
+ /**
+ * Removes a key and its value from this object.
+ *
+ * @param key The key of the property to remove.
+ * @return The old value mapped by the key, if any.
+ */
+ public String remove(String key)
+ {
+ if (key == null || key.length() == 0)
+ {
+ return null;
+ }
+ return (String) props.remove(canonicalize(key));
+ }
+
+ /**
+ * Decodes a set of properties from the given input stream.
+ *
+ * @param in The input stream.
+ * @throws IOException If an I/O error occurs.
+ */
+ public void decode(DataInputStream in) throws IOException
+ {
+ int len = in.readInt();
+ MeteredInputStream min = new MeteredInputStream(in, len);
+ DataInputStream in2 = new DataInputStream(min);
+ while (!min.limitReached())
+ {
+ String name = in2.readUTF();
+ String value = in2.readUTF();
+ put(name, value);
+ }
+ }
+
+ /**
+ * Encodes this set of properties to the given output stream.
+ *
+ * @param out The output stream to encode to.
+ * @throws IOException If an I/O error occurs.
+ */
+ public void encode(DataOutputStream out) throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ DataOutputStream out2 = new DataOutputStream(buf);
+ for (Iterator it = props.entrySet().iterator(); it.hasNext();)
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ out2.writeUTF((String) entry.getKey());
+ out2.writeUTF((String) entry.getValue());
+ }
+ out.writeInt(buf.size());
+ buf.writeTo(out);
+ }
+
+ public String toString()
+ {
+ return props.toString();
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private String canonicalize(String key)
+ {
+ return key.toLowerCase();
+ }
+}
diff --git a/gnu/javax/crypto/keyring/PublicKeyEntry.java b/gnu/javax/crypto/keyring/PublicKeyEntry.java
new file mode 100644
index 000000000..528e70cc6
--- /dev/null
+++ b/gnu/javax/crypto/keyring/PublicKeyEntry.java
@@ -0,0 +1,192 @@
+/* PublicKeyEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.keyring;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.PublicKey;
+import java.security.KeyFactory;
+import java.security.spec.X509EncodedKeySpec;
+
+import java.util.Date;
+
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.key.KeyPairCodecFactory;
+import gnu.java.security.key.dss.DSSPublicKey;
+import gnu.java.security.key.rsa.GnuRSAPublicKey;
+import gnu.javax.crypto.key.dh.GnuDHPublicKey;
+
+public final class PublicKeyEntry extends PrimitiveEntry
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ public static final int TYPE = 6;
+
+ private PublicKey key;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public PublicKeyEntry(PublicKey key, Date creationDate, Properties properties)
+ {
+ super(TYPE, creationDate, properties);
+
+ if (key == null)
+ {
+ throw new IllegalArgumentException("no key specified");
+ }
+ this.key = key;
+ }
+
+ private PublicKeyEntry()
+ {
+ super(TYPE);
+ }
+
+ // Class method.
+ // ------------------------------------------------------------------------
+
+ public static PublicKeyEntry decode(DataInputStream in) throws IOException
+ {
+ PublicKeyEntry entry = new PublicKeyEntry();
+ entry.defaultDecode(in);
+ String type = entry.properties.get("type");
+ if (type == null)
+ {
+ throw new MalformedKeyringException("no key type");
+ }
+ if (type.equalsIgnoreCase("RAW-DSS"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
+ entry.key = coder.decodePublicKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW-RSA"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("rsa");
+ entry.key = coder.decodePublicKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("RAW-DH"))
+ {
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dh");
+ entry.key = coder.decodePublicKey(entry.payload);
+ }
+ else if (type.equalsIgnoreCase("X.509"))
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ entry.key = kf.generatePublic(new X509EncodedKeySpec(entry.payload));
+ }
+ catch (Exception x)
+ {
+ }
+ if (entry.key == null)
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance("DSA");
+ entry.key = kf.generatePublic(new X509EncodedKeySpec(
+ entry.payload));
+ }
+ catch (Exception x)
+ {
+ }
+ if (entry.key == null)
+ {
+ throw new MalformedKeyringException(
+ "could not decode X.509 key");
+ }
+ }
+ }
+ else
+ {
+ throw new MalformedKeyringException("unsupported public key type: "
+ + type);
+ }
+ return entry;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the public key.
+ *
+ * @return The public key.
+ */
+ public PublicKey getKey()
+ {
+ return key;
+ }
+
+ protected void encodePayload() throws IOException
+ {
+ if (key instanceof DSSPublicKey)
+ {
+ properties.put("type", "RAW-DSS");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
+ payload = coder.encodePublicKey(key);
+ }
+ else if (key instanceof GnuRSAPublicKey)
+ {
+ properties.put("type", "RAW-RSA");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("rsa");
+ payload = coder.encodePublicKey(key);
+ }
+ else if (key instanceof GnuDHPublicKey)
+ {
+ properties.put("type", "RAW-DH");
+ IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dh");
+ payload = coder.encodePublicKey(key);
+ }
+ else if (key.getFormat() != null && key.getFormat().equals("X.509"))
+ {
+ properties.put("type", "X.509");
+ payload = key.getEncoded();
+ }
+ else
+ {
+ throw new IllegalArgumentException("cannot encode public key");
+ }
+ }
+}
diff --git a/gnu/javax/crypto/mac/BaseMac.java b/gnu/javax/crypto/mac/BaseMac.java
new file mode 100644
index 000000000..e5b47a937
--- /dev/null
+++ b/gnu/javax/crypto/mac/BaseMac.java
@@ -0,0 +1,144 @@
+/* BaseMac.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import gnu.java.security.hash.IMessageDigest;
+
+import java.util.Map;
+import java.security.InvalidKeyException;
+
+/**
+ * <p>A base abstract class to facilitate <i>MAC</i> (Message Authentication
+ * Code) implementations.</p>
+ */
+public abstract class BaseMac implements IMac
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of the <i>MAC</i>. */
+ protected String name;
+
+ /** Reference to the underlying hash algorithm instance. */
+ protected IMessageDigest underlyingHash;
+
+ /** The length of the truncated output in bytes. */
+ protected int truncatedSize;
+
+ /** The authentication key for this instance. */
+ // protected transient byte[] K;
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name of this instance.
+ */
+ protected BaseMac(String name)
+ {
+ super();
+
+ this.name = name;
+ }
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name of this instance.
+ * @param underlyingHash the underlying message digest algorithm instance.
+ */
+ protected BaseMac(String name, IMessageDigest underlyingHash)
+ {
+ this(name);
+
+ if (underlyingHash != null)
+ {
+ truncatedSize = underlyingHash.hashSize();
+ }
+ this.underlyingHash = underlyingHash;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.mac.IMac interface implementation ----------------------------
+
+ public String name()
+ {
+ return name;
+ }
+
+ public int macSize()
+ {
+ return truncatedSize;
+ }
+
+ public void update(byte b)
+ {
+ underlyingHash.update(b);
+ }
+
+ public void update(byte[] b, int offset, int len)
+ {
+ underlyingHash.update(b, offset, len);
+ }
+
+ public void reset()
+ {
+ underlyingHash.reset();
+ }
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+
+ // methods to be implemented by concrete subclasses ------------------------
+
+ public abstract void init(Map attributes) throws InvalidKeyException,
+ IllegalStateException;
+
+ public abstract byte[] digest();
+
+ public abstract boolean selfTest();
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/HMac.java b/gnu/javax/crypto/mac/HMac.java
new file mode 100644
index 000000000..f8f2e317d
--- /dev/null
+++ b/gnu/javax/crypto/mac/HMac.java
@@ -0,0 +1,313 @@
+/* HMac.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.hash.MD5;
+import gnu.java.security.util.Util;
+
+import java.security.InvalidKeyException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>The implementation of the <i>HMAC</i> (Keyed-Hash Message Authentication
+ * Code).</p>
+ *
+ * <p><i>HMAC</i> can be used in combination with any iterated cryptographic
+ * hash function. <i>HMAC</i> also uses a <i>secret key</i> for calculation and
+ * verification of the message authentication values. The main goals behind this
+ * construction are</p>
+ *
+ * <ul>
+ * <li>To use, without modifications, available hash functions. In
+ * particular, hash functions that perform well in software, and for which
+ * code is freely and widely available.</li>
+ *
+ * <li>To preserve the original performance of the hash function without
+ * incurring a significant degradation.</li>
+ *
+ * <li>To use and handle keys in a simple way.</li>
+ *
+ * <li>To have a well understood cryptographic analysis of the strength of
+ * the authentication mechanism based on reasonable assumptions on the
+ * underlying hash function.</li>
+ *
+ * <li>To allow for easy replaceability of the underlying hash function in
+ * case that faster or more secure hash functions are found or required.</li>
+ * </ul>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC:
+ * Keyed-Hashing for Message Authentication.<br>
+ * H. Krawczyk, M. Bellare, and R. Canetti.</li>
+ * </ol>
+ */
+public class HMac extends BaseMac implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String USE_WITH_PKCS5_V2 = "gnu.crypto.hmac.pkcs5";
+
+ private static final byte IPAD_BYTE = 0x36;
+
+ private static final byte OPAD_BYTE = 0x5C;
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ protected int macSize;
+
+ protected int blockSize;
+
+ protected IMessageDigest ipadHash;
+
+ protected IMessageDigest opadHash;
+
+ protected byte[] ipad;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param underlyingHash the underlying hash algorithm instance.
+ */
+ protected HMac(IMessageDigest underlyingHash)
+ {
+ super(Registry.HMAC_NAME_PREFIX + underlyingHash.name(), underlyingHash);
+
+ this.blockSize = underlyingHash.blockSize();
+ this.macSize = underlyingHash.hashSize();
+ ipadHash = opadHash = null;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // implementation of abstract methods in BaseMac ---------------------------
+
+ public void init(Map attributes) throws InvalidKeyException,
+ IllegalStateException
+ {
+ Integer ts = (Integer) attributes.get(TRUNCATED_SIZE);
+ truncatedSize = (ts == null ? macSize : ts.intValue());
+ if (truncatedSize < (macSize / 2))
+ {
+ throw new IllegalArgumentException("Truncated size too small");
+ }
+ else if (truncatedSize < 10)
+ {
+ throw new IllegalArgumentException("Truncated size less than 80 bits");
+ }
+
+ // we dont use/save the key outside this method
+ byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL);
+ if (K == null)
+ { // take it as an indication to re-use previous key if set
+ if (ipadHash == null)
+ {
+ throw new InvalidKeyException("Null key");
+ }
+ // we already went through the motions; ie. up to step #4. re-use
+ underlyingHash = (IMessageDigest) ipadHash.clone();
+ return;
+ }
+
+ // for HMACs used in key-derivation functions (e.g. PBKDF2) the key
+ // material need not be >= the (output) block size of the underlying
+ // algorithm
+ Boolean pkcs5 = (Boolean) attributes.get(USE_WITH_PKCS5_V2);
+ if (pkcs5 == null)
+ {
+ pkcs5 = Boolean.FALSE;
+ }
+ if (K.length < macSize && !pkcs5.booleanValue())
+ {
+ throw new InvalidKeyException("Key too short");
+ }
+
+ if (K.length > blockSize)
+ {
+ // (0) replace K with HASH(K) if K is larger than the hash's
+ // block size. Then pad with zeros until it is the correct
+ // size (the next `if').
+ underlyingHash.update(K, 0, K.length);
+ K = underlyingHash.digest();
+ }
+ if (K.length < blockSize)
+ {
+ // (1) append zeros to the end of K to create a B byte string
+ // (e.g., if K is of length 20 bytes and B=64, then K will be
+ // appended with 44 zero bytes 0x00)
+ int limit = (K.length > blockSize) ? blockSize : K.length;
+ byte[] newK = new byte[blockSize];
+ System.arraycopy(K, 0, newK, 0, limit);
+ K = newK;
+ }
+
+ underlyingHash.reset();
+ opadHash = (IMessageDigest) underlyingHash.clone();
+ if (ipad == null)
+ {
+ ipad = new byte[blockSize];
+ }
+ // (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+ // (1) with ipad
+ // (3) append the stream of data 'text' to the B byte string resulting
+ // from step (2)
+ // (4) apply H to the stream generated in step (3)
+ for (int i = 0; i < blockSize; i++)
+ {
+ // underlyingHash.update((byte)(K[i] ^ IPAD_BYTE));
+ ipad[i] = (byte) (K[i] ^ IPAD_BYTE);
+ }
+ for (int i = 0; i < blockSize; i++)
+ {
+ opadHash.update((byte) (K[i] ^ OPAD_BYTE));
+ }
+
+ underlyingHash.update(ipad, 0, blockSize);
+ ipadHash = (IMessageDigest) underlyingHash.clone();
+ K = null;
+ }
+
+ public void reset()
+ {
+ super.reset();
+ if (ipad != null)
+ {
+ underlyingHash.update(ipad, 0, blockSize);
+ ipadHash = (IMessageDigest) underlyingHash.clone();
+ }
+ }
+
+ public byte[] digest()
+ {
+ if (ipadHash == null)
+ {
+ throw new IllegalStateException("HMAC not initialised");
+ }
+
+ byte[] out = underlyingHash.digest();
+ // (5) XOR (bitwise exclusive-OR) the B byte string computed in
+ // step (1) with opad
+ underlyingHash = (IMessageDigest) opadHash.clone();
+ // (6) append the H result from step (4) to the B byte string
+ // resulting from step (5)
+ underlyingHash.update(out, 0, macSize);
+ // (7) apply H to the stream generated in step (6) and output
+ // the result
+ out = underlyingHash.digest(); // which also resets the underlying hash
+
+ // truncate and return
+ if (truncatedSize == macSize)
+ return out;
+
+ byte[] result = new byte[truncatedSize];
+ System.arraycopy(out, 0, result, 0, truncatedSize);
+
+ return result;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ try
+ {
+ IMac mac = new HMac(new MD5()); // use rfc-2104 test vectors
+ String tv1 = "9294727A3638BB1C13F48EF8158BFC9D";
+ String tv3 = "56BE34521D144C88DBB8C733F0E8B3F6";
+ byte[] k1 = new byte[] { 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
+ 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
+ 0x0B, 0x0B };
+ byte[] k3 = new byte[] { (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
+ (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
+ (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
+ (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
+ (byte) 0xAA, (byte) 0xAA, (byte) 0xAA,
+ (byte) 0xAA };
+ byte[] data = new byte[50];
+ for (int i = 0; i < 50;)
+ {
+ data[i++] = (byte) 0xDD;
+ }
+
+ HashMap map = new HashMap();
+
+ // test vector #1
+ map.put(MAC_KEY_MATERIAL, k1);
+ mac.init(map);
+ mac.update("Hi There".getBytes("ASCII"), 0, 8);
+ if (!tv1.equals(Util.toString(mac.digest())))
+ {
+ valid = Boolean.FALSE;
+ }
+
+ // test #2 is not used since it causes a "Key too short" exception
+
+ // test vector #3
+ map.put(MAC_KEY_MATERIAL, k3);
+ mac.init(map);
+ mac.update(data, 0, 50);
+ if (!tv3.equals(Util.toString(mac.digest())))
+ {
+ valid = Boolean.FALSE;
+ }
+ valid = Boolean.TRUE;
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace(System.err);
+ valid = Boolean.FALSE;
+ }
+ }
+ return valid.booleanValue();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/HMacFactory.java b/gnu/javax/crypto/mac/HMacFactory.java
new file mode 100644
index 000000000..156e6ced5
--- /dev/null
+++ b/gnu/javax/crypto/mac/HMacFactory.java
@@ -0,0 +1,128 @@
+/* HMacFactory.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <p>A <i>Factory</i> to instantiate Keyed-Hash Message Authentication Code
+ * (HMAC) algorithm instances.</p>
+ */
+public class HMacFactory implements Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce <i>Singleton</i> pattern. */
+ private HMacFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Return an instance of a <i>HMAC</i> algorithm given the name of its
+ * underlying hash function, prefixed with the literal defined in
+ * {@link Registry#HMAC_NAME_PREFIX}.</p>
+ *
+ * @param name the fully qualified name of the underlying algorithm: composed
+ * as the concatenation of a literal prefix (see {@link Registry#HMAC_NAME_PREFIX})
+ * and the name of the underlying hash algorithm.
+ * @return an instance of the <i>HMAC</i> algorithm, or <code>null</code> if
+ * none can be constructed.
+ * @exception InternalError if the implementation does not pass its self-test.
+ */
+ public static IMac getInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ name = name.toLowerCase();
+ if (!name.startsWith(HMAC_NAME_PREFIX))
+ {
+ return null;
+ }
+
+ // strip the prefix
+ name = name.substring(HMAC_NAME_PREFIX.length()).trim();
+ IMac result = new HMac(HashFactory.getInstance(name));
+ if (result != null && !result.selfTest())
+ {
+ throw new InternalError(result.name());
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link java.util.Set} of names of <i>HMAC</i> algorithms
+ * supported by this <i>Factory</i>.</p>
+ *
+ * @return a {@link java.util.Set} of HMAC algorithm names (Strings).
+ */
+ public static final Set getNames()
+ {
+ Set hashNames = HashFactory.getNames();
+ HashSet hs = new HashSet();
+ for (Iterator it = hashNames.iterator(); it.hasNext();)
+ {
+ hs.add(HMAC_NAME_PREFIX + ((String) it.next()));
+ }
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/IMac.java b/gnu/javax/crypto/mac/IMac.java
new file mode 100644
index 000000000..c4170c42c
--- /dev/null
+++ b/gnu/javax/crypto/mac/IMac.java
@@ -0,0 +1,197 @@
+/* IMac.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import java.util.Map;
+import java.security.InvalidKeyException;
+
+/**
+ * <p>The basic visible methods of any MAC (Message Authentication Code)
+ * algorithm.</p>
+ *
+ * <p>A <i>MAC</i> provides a way to check the integrity of information
+ * transmitted over, or stored in, an unreliable medium, based on a secret key.
+ * Typically, <i>MAC</i>s are used between two parties, that share a common
+ * secret key, in order to validate information transmitted between them.</p>
+ *
+ * <p>When a <i>MAC</i> algorithm is based on a cryptographic hash function, it
+ * is then called to a <i>HMAC</i> (Hashed Message Authentication Code) --see
+ * <a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC-2104</a>.</p>
+ *
+ * Another type of <i>MAC</i> algorithms exist: UMAC or <i>Universal Message
+ * Authentication Code</i>, described in
+ * <a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
+ * draft-krovetz-umac-01.txt</a>.</p>
+ *
+ * <p>With <i>UMAC</i>s, the sender and receiver share a common secret key (the
+ * <i>MAC</i> key) which determines:</p>
+ *
+ * <ul>
+ * <li>The key for a <i>universal hash function</i>. This hash function is
+ * <i>non-cryptographic</i>, in the sense that it does not need to have any
+ * cryptographic <i>hardness</i> property. Rather, it needs to satisfy some
+ * combinatorial property, which can be proven to hold without relying on
+ * unproven hardness assumptions.</li>
+ *
+ * <li>The key for a <i>pseudorandom function</i>. This is where one needs a
+ * cryptographic hardness assumption. The pseudorandom function may be
+ * obtained from a <i>block cipher</i> or a <i>cryptographic hash function</i>.
+ * </li>
+ * </ul>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc-2104.txt">RFC 2104</a>HMAC:
+ * Keyed-Hashing for Message Authentication.<br>
+ * H. Krawczyk, M. Bellare, and R. Canetti.</li>
+ *
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
+ * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
+ * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
+ * </ol>
+ */
+public interface IMac
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /**
+ * Property name of the user-supplied key material. The value associated to
+ * this property name is taken to be a byte array.
+ */
+ String MAC_KEY_MATERIAL = "gnu.crypto.mac.key.material";
+
+ /**
+ * <p>Property name of the desired truncated output size in bytes. The value
+ * associated to this property name is taken to be an integer. If no value
+ * is specified in the attributes map at initialisation time, then all bytes
+ * of the underlying hash algorithm's output are emitted.</p>
+ *
+ * <p>This implementation, follows the recommendation of the <i>RFC 2104</i>
+ * authors; specifically:</p>
+ *
+ * <pre>
+ * We recommend that the output length t be not less than half the
+ * length of the hash output (to match the birthday attack bound)
+ * and not less than 80 bits (a suitable lower bound on the number
+ * of bits that need to be predicted by an attacker).
+ * </pre>
+ */
+ String TRUNCATED_SIZE = "gnu.crypto.mac.truncated.size";
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of this algorithm.</p>
+ *
+ * @return the canonical name of this algorithm.
+ */
+ String name();
+
+ /**
+ * <p>Returns the output length in bytes of this <i>MAC</i> algorithm.</p>
+ *
+ * @return the output length in bytes of this <i>MAC</i> algorithm.
+ */
+ int macSize();
+
+ /**
+ * <p>Initialises the algorithm with designated attributes. Permissible names
+ * and values are described in the class documentation above.</p>
+ *
+ * @param attributes a set of name-value pairs that describe the desired
+ * future instance behaviour.
+ * @exception InvalidKeyException if the key data is invalid.
+ * @exception IllegalStateException if the instance is already initialised.
+ * @see #MAC_KEY_MATERIAL
+ */
+ void init(Map attributes) throws InvalidKeyException, IllegalStateException;
+
+ /**
+ * <p>Continues a <i>MAC</i> operation using the input byte.</p>
+ *
+ * @param b the input byte to digest.
+ */
+ void update(byte b);
+
+ /**
+ * <p>Continues a <i>MAC</i> operation, by filling the buffer, processing
+ * data in the algorithm's MAC_SIZE-bit block(s), updating the context and
+ * count, and buffering the remaining bytes in buffer for the next
+ * operation.</p>
+ *
+ * @param in the input block.
+ * @param offset start of meaningful bytes in input block.
+ * @param length number of bytes, in input block, to consider.
+ */
+ void update(byte[] in, int offset, int length);
+
+ /**
+ * <p>Completes the <i>MAC</i> by performing final operations such as
+ * padding and resetting the instance.</p>
+ *
+ * @return the array of bytes representing the <i>MAC</i> value.
+ */
+ byte[] digest();
+
+ /**
+ * <p>Resets the algorithm instance for re-initialisation and use with other
+ * characteristics. This method always succeeds.</p>
+ */
+ void reset();
+
+ /**
+ * <p>A basic test. Ensures that the MAC of a pre-determined message is equal
+ * to a known pre-computed value.</p>
+ *
+ * @return <code>true</code> if the implementation passes a basic self-test.
+ * Returns <code>false</code> otherwise.
+ */
+ boolean selfTest();
+
+ /**
+ * <p>Returns a clone copy of this instance.</p>
+ *
+ * @return a clone copy of this instance.
+ */
+ Object clone() throws CloneNotSupportedException;
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/MacFactory.java b/gnu/javax/crypto/mac/MacFactory.java
new file mode 100644
index 000000000..d8f8bcfce
--- /dev/null
+++ b/gnu/javax/crypto/mac/MacFactory.java
@@ -0,0 +1,164 @@
+/* MacFactory.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <p>A <i>Factory</i> that instantiates instances of every supported Message
+ * Authentication Code algorithms, including all <i>HMAC</i> algorithms.</p>
+ */
+public class MacFactory implements Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce <i>Singleton</i> pattern. */
+ private MacFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a <i>MAC</i> algorithm given its name.</p>
+ *
+ * @param name the name of the MAC algorithm.
+ * @return an instance of the <i>MAC</i> algorithm, or <code>null</code> if
+ * none can be constructed.
+ * @exception InternalError if the implementation does not pass its self-test.
+ */
+ public static IMac getInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ name = name.toLowerCase();
+ if (name.startsWith(HMAC_NAME_PREFIX))
+ {
+ return HMacFactory.getInstance(name);
+ }
+
+ if (name.startsWith(OMAC_PREFIX))
+ {
+ name = name.substring(OMAC_PREFIX.length());
+ IBlockCipher cipher = CipherFactory.getInstance(name);
+ if (cipher == null)
+ {
+ return null;
+ }
+ return new OMAC(cipher);
+ }
+
+ IMac result = null;
+ if (name.equalsIgnoreCase(UHASH32))
+ {
+ result = new UHash32();
+ }
+ else if (name.equalsIgnoreCase(UMAC32))
+ {
+ result = new UMac32();
+ }
+ else if (name.equalsIgnoreCase(TMMH16))
+ {
+ result = new TMMH16();
+ }
+ // else if (name.equalsIgnoreCase(TMMH32)) {
+ // result = new TMMH32();
+ // }
+
+ if (result != null && !result.selfTest())
+ {
+ throw new InternalError(result.name());
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link java.util.Set} of names of <i>MAC</i> algorithms
+ * supported by this <i>Factory</i>.</p>
+ *
+ * @return a {@link java.util.Set} of MAC names (Strings).
+ */
+ public static final Set getNames()
+ {
+ synchronized (MacFactory.class)
+ {
+ if (names == null)
+ {
+ HashSet hs = new HashSet();
+ hs.addAll(HMacFactory.getNames());
+ hs.add(UHASH32);
+ hs.add(UMAC32);
+ hs.add(TMMH16);
+ // hs.add(TMMH32);
+
+ for (Iterator it = CipherFactory.getNames().iterator(); it.hasNext();)
+ {
+ hs.add(OMAC_PREFIX + it.next());
+ }
+
+ names = Collections.unmodifiableSet(hs);
+ }
+ }
+ return names;
+ }
+
+ private static Set names;
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/MacInputStream.java b/gnu/javax/crypto/mac/MacInputStream.java
new file mode 100644
index 000000000..9acd18b19
--- /dev/null
+++ b/gnu/javax/crypto/mac/MacInputStream.java
@@ -0,0 +1,138 @@
+/* MacInputStream.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * A filtering input stream that computes a MAC (message authentication code)
+ * over all data read from the stream.
+ */
+public class MacInputStream extends FilterInputStream
+{
+
+ // Field.
+ // ------------------------------------------------------------------------
+
+ /**
+ * The digesting state. The MAC is updated only if this flag is true.
+ */
+ private boolean digesting;
+
+ /**
+ * The MAC being updated.
+ */
+ private IMac mac;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new MacInputStream. The stream is initially set to digest
+ * data written, the <i>mac</i> argument must have already been initialized,
+ * and the <i>mac</i> argument is <b>not</b> cloned.
+ *
+ * @param in The underlying input stream.
+ * @param mac The mac instance to use.
+ */
+ public MacInputStream(InputStream in, IMac mac)
+ {
+ super(in);
+ if (mac == null)
+ throw new NullPointerException();
+ this.mac = mac;
+ digesting = true;
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the MAC this stream is updating.
+ *
+ * @return The MAC.
+ */
+ public IMac getMac()
+ {
+ return mac;
+ }
+
+ /**
+ * Sets the MAC this stream is updating, which must have already been
+ * initialized. The argument is not cloned by this method.
+ *
+ * @param mac The new MAC.
+ * @throws NullPointerException If the argument is null.
+ */
+ public void setMac(IMac mac)
+ {
+ if (mac == null)
+ throw new NullPointerException();
+ this.mac = mac;
+ }
+
+ /**
+ * Turns the digesting state on or off. When off, the MAC will not be
+ * updated when data is written to the stream.
+ *
+ * @param flag The new digesting state.
+ */
+ public void on(boolean flag)
+ {
+ digesting = flag;
+ }
+
+ public int read() throws IOException
+ {
+ int i = in.read();
+ if (digesting && i != -1)
+ mac.update((byte) i);
+ return i;
+ }
+
+ public int read(byte[] buf, int off, int len) throws IOException
+ {
+ int i = in.read(buf, off, len);
+ if (digesting && i != -1)
+ mac.update(buf, off, i);
+ return i;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/MacOutputStream.java b/gnu/javax/crypto/mac/MacOutputStream.java
new file mode 100644
index 000000000..a48d25ba3
--- /dev/null
+++ b/gnu/javax/crypto/mac/MacOutputStream.java
@@ -0,0 +1,140 @@
+/* MacOutputStream.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * <p>A filtering output stream that computes a MAC (message authentication
+ * code) over all data written to the stream.</p>
+ */
+public class MacOutputStream extends FilterOutputStream
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The digesting state. The MAC is updated only if this flag is true. */
+ private boolean digesting;
+
+ /** The MAC being updated. */
+ private IMac mac;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Creates a new <code>MacOutputStream</code>. The stream is initially set
+ * to digest data written, the <code>mac</code> argument must have already
+ * been initialized, and the <code>mac</code> argument is <b>not</b> cloned.</p>
+ *
+ * @param out The underlying output stream.
+ * @param mac The mac instance to use.
+ */
+ public MacOutputStream(OutputStream out, IMac mac)
+ {
+ super(out);
+ if (mac == null)
+ {
+ throw new NullPointerException();
+ }
+ this.mac = mac;
+ digesting = true;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the MAC this stream is updating.</p>
+ *
+ * @return The MAC.
+ */
+ public IMac getMac()
+ {
+ return mac;
+ }
+
+ /**
+ * <p>Sets the MAC this stream is updating, which must have already been
+ * initialized. The argument is not cloned by this method.</p>
+ *
+ * @param mac The non-null new MAC.
+ * @throws NullPointerException If the argument is null.
+ */
+ public void setMac(IMac mac)
+ {
+ if (mac == null)
+ {
+ throw new NullPointerException();
+ }
+ this.mac = mac;
+ }
+
+ /**
+ * <p>Turns the digesting state on or off. When off, the MAC will not be
+ * updated when data is written to the stream.</p>
+ *
+ * @param flag The new digesting state.
+ */
+ public void on(boolean flag)
+ {
+ digesting = flag;
+ }
+
+ public void write(int b) throws IOException
+ {
+ if (digesting)
+ {
+ mac.update((byte) b);
+ }
+ out.write(b);
+ }
+
+ public void write(byte[] buf, int off, int len) throws IOException
+ {
+ if (digesting)
+ {
+ mac.update(buf, off, len);
+ }
+ out.write(buf, off, len);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/OMAC.java b/gnu/javax/crypto/mac/OMAC.java
new file mode 100644
index 000000000..c83320a1b
--- /dev/null
+++ b/gnu/javax/crypto/mac/OMAC.java
@@ -0,0 +1,402 @@
+/* OMAC.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+
+import java.security.InvalidKeyException;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>The One-Key CBC MAC, OMAC. This message authentication code is based on
+ * a block cipher in CBC mode.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li>Tetsu Iwata and Kaoru Kurosawa, <i><a
+ * href="http://crypt.cis.ibaraki.ac.jp/omac/docs/omac.pdf">OMAC: One-Key CBC
+ * MAC</a></i>.</li>
+ * </ol>
+ */
+public class OMAC implements IMac
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+
+ private static void debug(String msg)
+ {
+ System.out.print(">>> OMAC: ");
+ System.out.println(msg);
+ }
+
+ private static final byte C1 = (byte) 0x87;
+
+ private static final byte C2 = 0x1b;
+
+ // Test key for OMAC-AES-128
+ private static final byte[] KEY0 = Util.toBytesFromString("2b7e151628aed2a6abf7158809cf4f3c");
+
+ // Test MAC for zero-length input.
+ private static final byte[] DIGEST0 = Util.toBytesFromString("bb1d6929e95937287fa37d129b756746");
+
+ private static Boolean valid;
+
+ private final IBlockCipher cipher;
+
+ private final String name;
+
+ private IMode mode;
+
+ private int blockSize;
+
+ private int outputSize;
+
+ private byte[] Lu, Lu2;
+
+ private byte[] M;
+
+ private byte[] Y;
+
+ private boolean init;
+
+ private int index;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public OMAC(IBlockCipher cipher)
+ {
+ this.cipher = cipher;
+ this.name = "OMAC-" + cipher.name();
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new OMAC(cipher);
+ }
+
+ public String name()
+ {
+ return name;
+ }
+
+ public int macSize()
+ {
+ return outputSize;
+ }
+
+ public void init(Map attrib) throws InvalidKeyException
+ {
+ HashMap attrib2 = new HashMap();
+ attrib2.put(IBlockCipher.KEY_MATERIAL, attrib.get(MAC_KEY_MATERIAL));
+ cipher.reset();
+ cipher.init(attrib2);
+
+ blockSize = cipher.currentBlockSize();
+ Integer os = (Integer) attrib.get(TRUNCATED_SIZE);
+ if (os != null)
+ {
+ outputSize = os.intValue();
+ if (outputSize < 0 || outputSize > blockSize)
+ {
+ throw new IllegalArgumentException("truncated size out of range");
+ }
+ }
+ else
+ {
+ outputSize = blockSize;
+ }
+
+ byte[] L = new byte[blockSize];
+ cipher.encryptBlock(L, 0, L, 0);
+
+ if (DEBUG)
+ {
+ debug("L = " + Util.toString(L).toLowerCase());
+ }
+
+ if (Lu != null)
+ {
+ Arrays.fill(Lu, (byte) 0);
+ if (Lu.length != blockSize)
+ {
+ Lu = new byte[blockSize];
+ }
+ }
+ else
+ {
+ Lu = new byte[blockSize];
+ }
+ if (Lu2 != null)
+ {
+ Arrays.fill(Lu2, (byte) 0);
+ if (Lu2.length != blockSize)
+ {
+ Lu2 = new byte[blockSize];
+ }
+ }
+ else
+ {
+ Lu2 = new byte[blockSize];
+ }
+
+ boolean msb = (L[0] & 0x80) != 0;
+ for (int i = 0; i < blockSize; i++)
+ {
+ Lu[i] = (byte) (L[i] << 1 & 0xFF);
+ if (i + 1 < blockSize)
+ {
+ Lu[i] |= (byte) ((L[i + 1] & 0x80) >> 7);
+ }
+ }
+ if (msb)
+ {
+ if (blockSize == 16)
+ {
+ Lu[Lu.length - 1] ^= C1;
+ }
+ else if (blockSize == 8)
+ {
+ Lu[Lu.length - 1] ^= C2;
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "unsupported cipher block size: "
+ + blockSize);
+ }
+ }
+ if (DEBUG)
+ {
+ debug("Lu = " + Util.toString(Lu).toLowerCase());
+ }
+
+ msb = (Lu[0] & 0x80) != 0;
+ for (int i = 0; i < blockSize; i++)
+ {
+ Lu2[i] = (byte) (Lu[i] << 1 & 0xFF);
+ if (i + 1 < blockSize)
+ {
+ Lu2[i] |= (byte) ((Lu[i + 1] & 0x80) >> 7);
+ }
+ }
+ if (msb)
+ {
+ if (blockSize == 16)
+ {
+ Lu2[Lu2.length - 1] ^= C1;
+ }
+ else
+ {
+ Lu2[Lu2.length - 1] ^= C2;
+ }
+ }
+ if (DEBUG)
+ {
+ debug("Lu2 = " + Util.toString(Lu2).toLowerCase());
+ }
+
+ if (M != null)
+ {
+ Arrays.fill(M, (byte) 0);
+ if (M.length != blockSize)
+ {
+ M = new byte[blockSize];
+ }
+ }
+ else
+ {
+ M = new byte[blockSize];
+ }
+ if (Y != null)
+ {
+ Arrays.fill(Y, (byte) 0);
+ if (Y.length != blockSize)
+ {
+ Y = new byte[blockSize];
+ }
+ }
+ else
+ {
+ Y = new byte[blockSize];
+ }
+
+ index = 0;
+ init = true;
+ }
+
+ public void update(byte b)
+ {
+ if (!init)
+ {
+ throw new IllegalStateException("not initialized");
+ }
+ if (index == M.length)
+ {
+ process();
+ index = 0;
+ }
+ M[index++] = b;
+ }
+
+ public void update(byte[] buf, int off, int len)
+ {
+ if (!init)
+ {
+ throw new IllegalStateException("not initialized");
+ }
+ if (off < 0 || len < 0 || off + len > buf.length)
+ {
+ throw new IndexOutOfBoundsException("size=" + buf.length + "; off="
+ + off + "; len=" + len);
+ }
+ for (int i = 0; i < len;)
+ {
+ if (index == blockSize)
+ {
+ process();
+ index = 0;
+ }
+ int count = Math.min(blockSize - index, len - i);
+ System.arraycopy(buf, off + i, M, index, count);
+ index += count;
+ i += count;
+ }
+ }
+
+ public byte[] digest()
+ {
+ byte[] b = new byte[outputSize];
+ digest(b, 0);
+ return b;
+ }
+
+ public void digest(byte[] out, int off)
+ {
+ if (!init)
+ {
+ throw new IllegalStateException("not initialized");
+ }
+ if (off < 0 || off + outputSize > out.length)
+ {
+ throw new IndexOutOfBoundsException("size=" + out.length + "; off="
+ + off + "; len=" + outputSize);
+ }
+ byte[] T = new byte[blockSize];
+ byte[] L = Lu;
+ if (index < blockSize)
+ {
+ M[index++] = (byte) 0x80;
+ while (index < blockSize)
+ {
+ M[index++] = 0;
+ }
+ L = Lu2;
+ }
+ for (int i = 0; i < blockSize; i++)
+ {
+ T[i] = (byte) (M[i] ^ Y[i] ^ L[i]);
+ }
+ cipher.encryptBlock(T, 0, T, 0);
+ System.arraycopy(T, 0, out, off, outputSize);
+ reset();
+ }
+
+ public void reset()
+ {
+ index = 0;
+ if (Y != null)
+ {
+ Arrays.fill(Y, (byte) 0);
+ }
+ if (M != null)
+ {
+ Arrays.fill(M, (byte) 0);
+ }
+ }
+
+ public boolean selfTest()
+ {
+ OMAC mac = new OMAC(CipherFactory.getInstance(Registry.AES_CIPHER));
+ mac.reset();
+ Map attr = new HashMap();
+ attr.put(MAC_KEY_MATERIAL, KEY0);
+ byte[] digest = null;
+ try
+ {
+ mac.init(attr);
+ digest = mac.digest();
+ }
+ catch (Exception x)
+ {
+ return false;
+ }
+ if (digest == null)
+ {
+ return false;
+ }
+ return Arrays.equals(DIGEST0, digest);
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private void process()
+ {
+ for (int i = 0; i < blockSize; i++)
+ {
+ M[i] = (byte) (M[i] ^ Y[i]);
+ }
+ cipher.encryptBlock(M, 0, Y, 0);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/TMMH16.java b/gnu/javax/crypto/mac/TMMH16.java
new file mode 100644
index 000000000..82de3aac9
--- /dev/null
+++ b/gnu/javax/crypto/mac/TMMH16.java
@@ -0,0 +1,378 @@
+/* TMMH16.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+import java.security.InvalidKeyException;
+import java.util.Map;
+
+/**
+ * <p><i>TMMH</i> is a <i>universal</i> hash function suitable for message
+ * authentication in the Wegman-Carter paradigm, as in the Stream Cipher
+ * Security Transform. It is simple, quick, and especially appropriate for
+ * Digital Signal Processors and other processors with a fast multiply
+ * operation, though a straightforward implementation requires storage equal in
+ * length to the largest message to be hashed.</p>
+ *
+ * <p><i>TMMH</i> is a simple hash function which maps a key and a message to a
+ * hash value. There are two versions of TMMH: TMMH/16 and TMMH/32. <i>TMMH</i>
+ * can be used as a message authentication code, as described in Section 5 (see
+ * References).</p>
+ *
+ * <p>The key, message, and hash value are all octet strings, and the lengths of
+ * these quantities are denoted as <code>KEY_LENGTH</code>,
+ * <code>MESSAGE_LENGTH</code>, and <code>TAG_LENGTH</code>, respectively. The
+ * values of <code>KEY_LENGTH</code> and <code>TAG_LENGTH</code>
+ * <bold>MUST</bold> be fixed for any particular fixed value of the key, and
+ * must obey the alignment restrictions described below.</p>
+ *
+ * <p>The parameter <code>MAX_HASH_LENGTH</code>, which denotes the maximum
+ * value which <code>MESSAGE_LENGTH</code> may take, is equal to
+ * <code>KEY_LENGTH - TAG_LENGTH</code>.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a
+ href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-tmmh-01.txt">
+ * The Truncated Multi-Modular Hash Function (TMMH)</a>, David A. McGrew.</li>
+ * </ol>
+ */
+public class TMMH16 extends BaseMac implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String TAG_LENGTH = "gnu.crypto.mac.tmmh.tag.length";
+
+ public static final String KEYSTREAM = "gnu.crypto.mac.tmmh.keystream";
+
+ public static final String PREFIX = "gnu.crypto.mac.tmmh.prefix";
+
+ private static final int P = (1 << 16) + 1; // the TMMH/16 prime
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ private int tagWords = 0; // the tagLength expressed in words
+
+ private IRandom keystream = null; // the keystream generator
+
+ private byte[] prefix; // mask to use when operating as an authentication f.
+
+ private long keyWords; // key words counter
+
+ private long msgLength; // in bytes
+
+ private long msgWords; // should be = msgLength * WORD_LENGTH
+
+ private int[] context; // the tmmh running context; length == TAG_WORDS
+
+ private int[] K0; // the first TAG_WORDS words of the keystream
+
+ private int[] Ki; // the sliding TAG_WORDS words of the keystream
+
+ private int Mi; // current message word being constructed
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public TMMH16()
+ {
+ super(Registry.TMMH16);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.mac.IMac interface implementation ----------------------------
+
+ public int macSize()
+ {
+ return tagWords * 2;
+ }
+
+ public void init(Map attributes) throws InvalidKeyException,
+ IllegalStateException
+ {
+ int wantTagLength = 0;
+ Integer tagLength = (Integer) attributes.get(TAG_LENGTH); // get tag length
+ if (tagLength == null)
+ {
+ if (tagWords == 0)
+ { // was never set
+ throw new IllegalArgumentException(TAG_LENGTH);
+ } // else re-use
+ }
+ else
+ { // check if positive and is divisible by WORD_LENGTH
+ wantTagLength = tagLength.intValue();
+ if (wantTagLength < 2 || (wantTagLength % 2 != 0))
+ {
+ throw new IllegalArgumentException(TAG_LENGTH);
+ }
+ else if (wantTagLength > (512 / 8))
+ { // 512-bits is our maximum
+ throw new IllegalArgumentException(TAG_LENGTH);
+ }
+
+ tagWords = wantTagLength / 2; // init local vars
+ K0 = new int[tagWords];
+ Ki = new int[tagWords];
+ context = new int[tagWords];
+ }
+
+ prefix = (byte[]) attributes.get(PREFIX);
+ if (prefix == null)
+ { // default to all-zeroes
+ prefix = new byte[tagWords * 2];
+ }
+ else
+ { // ensure it's as long as it should
+ if (prefix.length != tagWords * 2)
+ {
+ throw new IllegalArgumentException(PREFIX);
+ }
+ }
+
+ IRandom prng = (IRandom) attributes.get(KEYSTREAM); // get keystream
+ if (prng == null)
+ {
+ if (keystream == null)
+ {
+ throw new IllegalArgumentException(KEYSTREAM);
+ } // else reuse
+ }
+ else
+ {
+ keystream = prng;
+ }
+
+ reset(); // reset context variables
+ for (int i = 0; i < tagWords; i++)
+ { // init starting key words
+ Ki[i] = K0[i] = getNextKeyWord(keystream);
+ }
+ }
+
+ // The words of the key are denoted as K[1], K[2], ..., K[KEY_WORDS], and the
+ // words of the message (after zero padding, if needed) are denoted as M[1],
+ // M[2], ..., M[MSG_WORDS], where MSG_WORDS is the smallest number such that
+ // 2 * MSG_WORDS is at least MESSAGE_LENGTH, and KEY_WORDS is KEY_LENGTH / 2.
+ //
+ // If MESSAGE_LENGTH is greater than MAX_HASH_LENGTH, then the value of
+ // TMMH/16 is undefined. Implementations MUST indicate an error if asked to
+ // hash a message with such a length. Otherwise, the hash value is defined
+ // to be the length TAG_WORDS sequence of words in which the j-th word in the
+ // sequence is defined as
+ //
+ // [ [ K[j] * MESSAGE_LENGTH +32 K[j+1] * M[1] +32 K[j+2] * M[2]
+ // +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16
+ //
+ // where j ranges from 1 to TAG_WORDS.
+ public void update(byte b)
+ {
+ this.update(b, keystream);
+ }
+
+ public void update(byte[] b, int offset, int len)
+ {
+ for (int i = 0; i < len; i++)
+ {
+ this.update(b[offset + i], keystream);
+ }
+ }
+
+ // For TMMH/16, KEY_LENGTH and TAG_LENGTH MUST be a multiple of two. The key,
+ // message, and hash value are treated as a sequence of unsigned sixteen bit
+ // integers in network byte order. (In this section, we call such an integer
+ // a word.) If MESSAGE_LENGTH is odd, then a zero byte is appended to the
+ // message to align it on a word boundary, though this process does not
+ // change the value of MESSAGE_LENGTH.
+ //
+ // ... Otherwise, the hash value is defined to be the length TAG_WORDS
+ // sequence of words in which the j-th word in the sequence is defined as
+ //
+ // [ [ K[j] * MESSAGE_LENGTH +32 K[j+1] * M[1] +32 K[j+2] * M[2]
+ // +32 ... K[j+MSG_WORDS] * M[MSG_WORDS] ] modulo p ] modulo 2^16
+ //
+ // where j ranges from 1 to TAG_WORDS.
+ //
+ // Here, TAG_WORDS is equal to TAG_LENGTH / 2, and p is equal to 2^16 + 1.
+ // The symbol * denotes multiplication and the symbol +32 denotes addition
+ // modulo 2^32.
+ public byte[] digest()
+ {
+ return this.digest(keystream);
+ }
+
+ public void reset()
+ {
+ msgLength = msgWords = keyWords = 0L;
+ Mi = 0;
+ for (int i = 0; i < tagWords; i++)
+ {
+ context[i] = 0;
+ }
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ // TODO: compute and test equality with one known vector
+
+ valid = Boolean.TRUE;
+ }
+ return valid.booleanValue();
+ }
+
+ // own methods -------------------------------------------------------------
+
+ /**
+ * <p>Similar to the same method with one argument, but uses the designated
+ * random number generator to compute needed keying material.</p>
+ *
+ * @param b the byte to process.
+ * @param prng the source of randomness to use.
+ */
+ public void update(byte b, IRandom prng)
+ {
+ Mi <<= 8; // update message buffer
+ Mi |= b & 0xFF;
+ msgLength++; // update message length (bytes)
+ if (msgLength % 2 == 0)
+ { // got a full word
+ msgWords++; // update message words counter
+ System.arraycopy(Ki, 1, Ki, 0, tagWords - 1); // 1. shift Ki up by 1
+ Ki[tagWords - 1] = getNextKeyWord(prng); // 2. fill last box of Ki
+ long t; // temp var to allow working in modulo 2^32
+ for (int i = 0; i < tagWords; i++)
+ { // 3. update context
+ t = context[i] & 0xFFFFFFFFL;
+ t += Ki[i] * Mi;
+ context[i] = (int) t;
+ }
+ Mi = 0; // reset message buffer
+ }
+ }
+
+ /**
+ * <p>Similar to the same method with three arguments, but uses the
+ * designated random number generator to compute needed keying material.</p>
+ *
+ * @param b the byte array to process.
+ * @param offset the starting offset in <code>b</code> to start considering
+ * the bytes to process.
+ * @param len the number of bytes in <code>b</code> starting from
+ * <code>offset</code> to process.
+ * @param prng the source of randomness to use.
+ */
+ public void update(byte[] b, int offset, int len, IRandom prng)
+ {
+ for (int i = 0; i < len; i++)
+ {
+ this.update(b[offset + i], prng);
+ }
+ }
+
+ /**
+ * <p>Similar to the same method with no arguments, but uses the designated
+ * random number generator to compute needed keying material.</p>
+ *
+ * @param prng the source of randomness to use.
+ * @return the final result of the algorithm.
+ */
+ public byte[] digest(IRandom prng)
+ {
+ doFinalRound(prng);
+ byte[] result = new byte[tagWords * 2];
+ for (int i = 0, j = 0; i < tagWords; i++)
+ {
+ result[j] = (byte) ((context[i] >>> 8) ^ prefix[j]);
+ j++;
+ result[j] = (byte) (context[i] ^ prefix[j]);
+ j++;
+ }
+
+ reset();
+ return result;
+ }
+
+ private int getNextKeyWord(IRandom prng)
+ {
+ int result = 0;
+ try
+ {
+ result = (prng.nextByte() & 0xFF) << 8 | (prng.nextByte() & 0xFF);
+ }
+ catch (LimitReachedException x)
+ {
+ throw new RuntimeException(String.valueOf(x));
+ }
+
+ keyWords++; // update key words counter
+ return result;
+ }
+
+ private void doFinalRound(IRandom prng)
+ {
+ long limit = msgLength; // formula works on real message length
+ while (msgLength % 2 != 0)
+ {
+ update((byte) 0x00, prng);
+ }
+ long t;
+ for (int i = 0; i < tagWords; i++)
+ {
+ t = context[i] & 0xFFFFFFFFL;
+ t += K0[i] * limit;
+ t %= P;
+ context[i] = (int) t;
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/UHash32.java b/gnu/javax/crypto/mac/UHash32.java
new file mode 100644
index 000000000..8abb0255e
--- /dev/null
+++ b/gnu/javax/crypto/mac/UHash32.java
@@ -0,0 +1,957 @@
+/* UHash32.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.prng.UMacGenerator;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p><i>UHASH</i> is a keyed hash function, which takes as input a string of
+ * arbitrary length, and produces as output a string of fixed length (such as 8
+ * bytes). The actual output length depends on the parameter UMAC-OUTPUT-LEN.</p>
+ *
+ * <p><i>UHASH</i> has been shown to be <i>epsilon-ASU</i> ("Almost Strongly
+ * Universal"), where epsilon is a small (parameter-dependent) real number.
+ * Informally, saying that a keyed hash function is <i>epsilon-ASU</i> means
+ * that for any two distinct fixed input strings, the two outputs of the hash
+ * function with a random key "look almost like a pair of random strings". The
+ * number epsilon measures how non-random the output strings may be.</p>
+ *
+ * <i>UHASH</i> has been designed to be fast by exploiting several architectural
+ * features of modern commodity processors. It was specifically designed for use
+ * in <i>UMAC</i>. But <i>UHASH</i> is useful beyond that domain, and can be
+ * easily adopted for other purposes.</p>
+ *
+ * <i>UHASH</i> does its work in three layers. First, a hash function called
+ * <code>NH</code> is used to compress input messages into strings which are
+ * typically many times smaller than the input message. Second, the compressed
+ * message is hashed with an optimized <i>polynomial hash function</i> into a
+ * fixed-length 16-byte string. Finally, the 16-byte string is hashed using an
+ * <i>inner-product hash</i> into a string of length WORD-LEN bytes. These three
+ * layers are repeated (with a modified key) until the outputs total
+ * UMAC-OUTPUT-LEN bytes.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
+ * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
+ * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
+ * </ol>
+ */
+public class UHash32 extends BaseMac
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // UMAC prime values
+ private static final BigInteger PRIME_19 = BigInteger.valueOf(0x7FFFFL);
+
+ private static final BigInteger PRIME_32 = BigInteger.valueOf(0xFFFFFFFBL);
+
+ private static final BigInteger PRIME_36 = BigInteger.valueOf(0xFFFFFFFFBL);
+
+ private static final BigInteger PRIME_64 = new BigInteger(
+ 1,
+ new byte[] {
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xC5 });
+
+ private static final BigInteger PRIME_128 = new BigInteger(
+ 1,
+ new byte[] {
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0x61 });
+
+ static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ static final long BOUNDARY = TWO.shiftLeft(17).longValue();
+
+ // 2**64 - 2**32
+ static final BigInteger LOWER_RANGE = TWO.pow(64).subtract(TWO.pow(32));
+
+ // 2**128 - 2**96
+ static final BigInteger UPPER_RANGE = TWO.pow(128).subtract(TWO.pow(96));
+
+ static final byte[] ALL_ZEROES = new byte[32];
+
+ int streams;
+
+ L1Hash32[] l1hash;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public UHash32()
+ {
+ super("uhash32");
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param that the instance to clone.
+ */
+ private UHash32(UHash32 that)
+ {
+ this();
+
+ this.streams = that.streams;
+ if (that.l1hash != null)
+ {
+ // this.l1hash = new L1Hash32[that.l1hash.length];
+ this.l1hash = new L1Hash32[that.streams];
+ // for (int i = 0; i < that.l1hash.length; i++) {
+ for (int i = 0; i < that.streams; i++)
+ {
+ if (that.l1hash[i] != null)
+ {
+ this.l1hash[i] = (L1Hash32) that.l1hash[i].clone();
+ }
+ }
+ }
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>The prime numbers used in UMAC are:</p>
+ * <pre>
+ * +-----+--------------------+---------------------------------------+
+ * | x | prime(x) [Decimal] | prime(x) [Hexadecimal] |
+ * +-----+--------------------+---------------------------------------+
+ * | 19 | 2^19 - 1 | 0x0007FFFF |
+ * | 32 | 2^32 - 5 | 0xFFFFFFFB |
+ * | 36 | 2^36 - 5 | 0x0000000F FFFFFFFB |
+ * | 64 | 2^64 - 59 | 0xFFFFFFFF FFFFFFC5 |
+ * | 128 | 2^128 - 159 | 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFF61 |
+ * +-----+--------------------+---------------------------------------+
+ *</pre>
+ *
+ * @param n a number of bits.
+ * @return the largest prime number less than 2**n.
+ */
+ static final BigInteger prime(int n)
+ {
+ switch (n)
+ {
+ case 19:
+ return PRIME_19;
+ case 32:
+ return PRIME_32;
+ case 36:
+ return PRIME_36;
+ case 64:
+ return PRIME_64;
+ case 128:
+ return PRIME_128;
+ default:
+ throw new IllegalArgumentException("Undefined prime("
+ + String.valueOf(n) + ")");
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new UHash32(this);
+ }
+
+ // gnu.crypto.mac.IMac interface implementation ----------------------------
+
+ public int macSize()
+ {
+ return UMac32.OUTPUT_LEN;
+ }
+
+ public void init(Map attributes) throws InvalidKeyException,
+ IllegalStateException
+ {
+ byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL);
+ if (K == null)
+ {
+ throw new InvalidKeyException("Null Key");
+ }
+ if (K.length != UMac32.KEY_LEN)
+ {
+ throw new InvalidKeyException("Invalid Key length: "
+ + String.valueOf(K.length));
+ }
+
+ // Calculate iterations needed to make UMAC-OUTPUT-LEN bytes
+ streams = (UMac32.OUTPUT_LEN + 3) / 4;
+
+ // Define total key needed for all iterations using UMacGenerator.
+ // L1Key and L3Key1 both reuse most key between iterations.
+ IRandom kdf1 = new UMacGenerator();
+ IRandom kdf2 = new UMacGenerator();
+ IRandom kdf3 = new UMacGenerator();
+ IRandom kdf4 = new UMacGenerator();
+ Map map = new HashMap();
+ map.put(IBlockCipher.KEY_MATERIAL, K);
+ map.put(UMacGenerator.INDEX, new Integer(0));
+ kdf1.init(map);
+ map.put(UMacGenerator.INDEX, new Integer(1));
+ kdf2.init(map);
+ map.put(UMacGenerator.INDEX, new Integer(2));
+ kdf3.init(map);
+ map.put(UMacGenerator.INDEX, new Integer(3));
+ kdf4.init(map);
+
+ // need to generate all bytes for use later in a Toepliz construction
+ byte[] L1Key = new byte[UMac32.L1_KEY_LEN + (streams - 1) * 16];
+ try
+ {
+ kdf1.nextBytes(L1Key, 0, L1Key.length);
+ }
+ catch (LimitReachedException x)
+ {
+ x.printStackTrace(System.err);
+ throw new RuntimeException("KDF for L1Key reached limit");
+ }
+
+ l1hash = new L1Hash32[streams];
+ for (int i = 0; i < streams; i++)
+ {
+ byte[] k1 = new byte[UMac32.L1_KEY_LEN];
+ System.arraycopy(L1Key, i * 16, k1, 0, UMac32.L1_KEY_LEN);
+ byte[] k2 = new byte[24];
+ try
+ {
+ kdf2.nextBytes(k2, 0, 24);
+ }
+ catch (LimitReachedException x)
+ {
+ x.printStackTrace(System.err);
+ throw new RuntimeException("KDF for L2Key reached limit");
+ }
+
+ byte[] k31 = new byte[64];
+ try
+ {
+ kdf3.nextBytes(k31, 0, 64);
+ }
+ catch (LimitReachedException x)
+ {
+ x.printStackTrace(System.err);
+ throw new RuntimeException("KDF for L3Key1 reached limit");
+ }
+
+ byte[] k32 = new byte[4];
+ try
+ {
+ kdf4.nextBytes(k32, 0, 4);
+ }
+ catch (LimitReachedException x)
+ {
+ x.printStackTrace(System.err);
+ throw new RuntimeException("KDF for L3Key2 reached limit");
+ }
+
+ L1Hash32 mac = new L1Hash32();
+ mac.init(k1, k2, k31, k32);
+ l1hash[i] = mac;
+ }
+ }
+
+ public void update(byte b)
+ {
+ for (int i = 0; i < streams; i++)
+ {
+ l1hash[i].update(b);
+ }
+ }
+
+ public void update(byte[] b, int offset, int len)
+ {
+ for (int i = 0; i < len; i++)
+ {
+ this.update(b[offset + i]);
+ }
+ }
+
+ public byte[] digest()
+ {
+ byte[] result = new byte[UMac32.OUTPUT_LEN];
+ for (int i = 0; i < streams; i++)
+ {
+ byte[] partialResult = l1hash[i].digest();
+ System.arraycopy(partialResult, 0, result, 4 * i, 4);
+ }
+ reset();
+ return result;
+ }
+
+ public void reset()
+ {
+ for (int i = 0; i < streams; i++)
+ {
+ l1hash[i].reset();
+ }
+ }
+
+ public boolean selfTest()
+ {
+ return true;
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ // Inner classes
+ // =========================================================================
+
+ /**
+ * First hash stage of the UHash32 algorithm.
+ */
+ class L1Hash32 implements Cloneable
+ {
+
+ // Constants and variables
+ // ----------------------------------------------------------------------
+
+ private int[] key; // key material as an array of 32-bit ints
+
+ private byte[] buffer; // work buffer L1_KEY_LEN long
+
+ private int count; // meaningful bytes in buffer
+
+ private ByteArrayOutputStream Y;
+
+ // private byte[] y;
+ private long totalCount;
+
+ private L2Hash32 l2hash;
+
+ private L3Hash32 l3hash;
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ L1Hash32()
+ {
+ super();
+
+ key = new int[UMac32.L1_KEY_LEN / 4];
+ buffer = new byte[UMac32.L1_KEY_LEN];
+ count = 0;
+ Y = new ByteArrayOutputStream();
+ totalCount = 0L;
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param that the instance to clone.
+ */
+ private L1Hash32(L1Hash32 that)
+ {
+ this();
+
+ System.arraycopy(that.key, 0, this.key, 0, that.key.length);
+ System.arraycopy(that.buffer, 0, this.buffer, 0, that.count);
+ this.count = that.count;
+ byte[] otherY = that.Y.toByteArray();
+ this.Y.write(otherY, 0, otherY.length);
+ this.totalCount = that.totalCount;
+ if (that.l2hash != null)
+ {
+ this.l2hash = (L2Hash32) that.l2hash.clone();
+ }
+ if (that.l3hash != null)
+ {
+ this.l3hash = (L3Hash32) that.l3hash.clone();
+ }
+ }
+
+ // Class methods
+ // ----------------------------------------------------------------------
+
+ // Instance methods
+ // ----------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation -------------------------
+
+ public Object clone()
+ {
+ return new L1Hash32(this);
+ }
+
+ // other instance methods -----------------------------------------------
+
+ public void init(byte[] k1, byte[] k2, byte[] k31, byte[] k32)
+ {
+ for (int i = 0, j = 0; i < (UMac32.L1_KEY_LEN / 4); i++)
+ {
+ key[i] = k1[j++] << 24 | (k1[j++] & 0xFF) << 16
+ | (k1[j++] & 0xFF) << 8 | (k1[j++] & 0xFF);
+ }
+
+ l2hash = new L2Hash32(k2);
+ l3hash = new L3Hash32(k31, k32);
+ }
+
+ public void update(byte b)
+ {
+ // Break M into L1_KEY_LEN byte chunks (final chunk may be shorter)
+
+ // Let M_1, M_2, ..., M_t be strings so that M = M_1 || M_2 || .. ||
+ // M_t, and length(M_i) = L1_KEY_LEN for all 0 < i < t.
+
+ // For each chunk, except the last: endian-adjust, NH hash
+ // and add bit-length. Use results to build Y.
+ buffer[count] = b;
+ count++;
+ totalCount++;
+ if (count >= UMac32.L1_KEY_LEN)
+ {
+ byte[] y = nh32(UMac32.L1_KEY_LEN);
+ Y.write(y, 0, 8);
+
+ count = 0;
+
+ // For each iteration, extract key and three-layer hash.
+ // If length(M) <= L1_KEY_LEN, then skip L2-HASH.
+ if (Y.size() == 16)
+ { // we already hashed twice L1_KEY_LEN
+ byte[] A = Y.toByteArray();
+ Y.reset();
+ l2hash.update(A, 0, 16);
+ }
+ }
+ }
+
+ public byte[] digest()
+ {
+ // For the last chunk: pad to 32-byte boundary, endian-adjust,
+ // NH hash and add bit-length. Concatenate the result to Y.
+ if (count != 0)
+ {
+ if (count % 32 != 0)
+ {
+ int limit = 32 * ((count + 31) / 32);
+ System.arraycopy(ALL_ZEROES, 0, buffer, count, limit - count);
+ count += limit - count;
+ }
+ byte[] y = nh32(count);
+ Y.write(y, 0, 8);
+ }
+
+ byte[] A = Y.toByteArray();
+ Y.reset();
+ byte[] B;
+ if (totalCount <= UMac32.L1_KEY_LEN)
+ {
+ // we might have 'update'd the bytes already. check
+ if (A.length == 0)
+ { // we did
+ B = l2hash.digest();
+ }
+ else
+ { // did not
+ B = new byte[16];
+ System.arraycopy(A, 0, B, 8, 8);
+ }
+ }
+ else
+ {
+ if (A.length != 0)
+ {
+ l2hash.update(A, 0, A.length);
+ }
+ B = l2hash.digest();
+ }
+
+ byte[] result = l3hash.digest(B);
+ reset();
+ return result;
+ }
+
+ public void reset()
+ {
+ count = 0;
+ Y.reset();
+ totalCount = 0L;
+ if (l2hash != null)
+ {
+ l2hash.reset();
+ }
+ }
+
+ // helper methods -------------------------------------------------------
+
+ /**
+ * 5.1 NH-32: NH hashing with a 32-bit word size.
+ *
+ * @param len count of bytes, divisible by 32, in buffer to process
+ * @return Y, string of length 8 bytes.
+ */
+ private byte[] nh32(int len)
+ {
+ // Break M and K into 4-byte chunks
+ int t = len / 4;
+
+ // Let M_1, M_2, ..., M_t be 4-byte strings
+ // so that M = M_1 || M_2 || .. || M_t.
+ // Let K_1, K_2, ..., K_t be 4-byte strings
+ // so that K_1 || K_2 || .. || K_t is a prefix of K.
+ int[] m = new int[t];
+
+ int i;
+ int j = 0;
+ for (i = 0, j = 0; i < t; i++)
+ {
+ m[i] = buffer[j++] << 24 | (buffer[j++] & 0xFF) << 16
+ | (buffer[j++] & 0xFF) << 8 | (buffer[j++] & 0xFF);
+ }
+
+ // Perform NH hash on the chunks, pairing words for multiplication
+ // which are 4 apart to accommodate vector-parallelism.
+ long result = len * 8L;
+ for (i = 0; i < t; i += 8)
+ {
+ result += ((m[i + 0] + key[i + 0]) & 0xFFFFFFFFL)
+ * ((m[i + 4] + key[i + 4]) & 0xFFFFFFFFL);
+ result += ((m[i + 1] + key[i + 1]) & 0xFFFFFFFFL)
+ * ((m[i + 5] + key[i + 5]) & 0xFFFFFFFFL);
+ result += ((m[i + 2] + key[i + 2]) & 0xFFFFFFFFL)
+ * ((m[i + 6] + key[i + 6]) & 0xFFFFFFFFL);
+ result += ((m[i + 3] + key[i + 3]) & 0xFFFFFFFFL)
+ * ((m[i + 7] + key[i + 7]) & 0xFFFFFFFFL);
+ }
+
+ return new byte[] { (byte) (result >>> 56), (byte) (result >>> 48),
+ (byte) (result >>> 40), (byte) (result >>> 32),
+ (byte) (result >>> 24), (byte) (result >>> 16),
+ (byte) (result >>> 8), (byte) result };
+ }
+ }
+
+ // =========================================================================
+
+ /**
+ * <p>Second hash stage of the UHash32 algorithm.</p>
+ *
+ * 5.4 L2-HASH-32: Second-layer hash.<p>
+ * <ul>
+ * <li>Input:<br>
+ * K string of length 24 bytes.<br>
+ * M string of length less than 2^64 bytes.</li>
+ * <li>Returns:<br>
+ * Y, string of length 16 bytes.</li>
+ * </ul>
+ */
+ class L2Hash32 implements Cloneable
+ {
+
+ // Constants and variables
+ // ----------------------------------------------------------------------
+
+ private BigInteger k64, k128;
+
+ private BigInteger y;
+
+ private boolean highBound;
+
+ private long bytesSoFar;
+
+ private ByteArrayOutputStream buffer;
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ L2Hash32(byte[] K)
+ {
+ super();
+
+ if (K.length != 24)
+ {
+ throw new ExceptionInInitializerError("K length is not 24");
+ }
+
+ // Extract keys and restrict to special key-sets
+ // Mask64 = uint2str(0x01FFFFFF01FFFFFF, 8);
+ // Mask128 = uint2str(0x01FFFFFF01FFFFFF01FFFFFF01FFFFFF, 16);
+ // k64 = str2uint(K[1..8] and Mask64);
+ // k128 = str2uint(K[9..24] and Mask128);
+ int i = 0;
+ k64 = new BigInteger(1, new byte[] { (byte) (K[i++] & 0x01),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0x01),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF) });
+ k128 = new BigInteger(1, new byte[] { (byte) (K[i++] & 0x01),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0x01),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0x01),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0x01),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF),
+ (byte) (K[i++] & 0xFF) });
+
+ y = BigInteger.ONE;
+ highBound = false;
+ bytesSoFar = 0L;
+ }
+
+ private L2Hash32(L2Hash32 that)
+ {
+ super();
+
+ this.k64 = that.k64;
+ this.k128 = that.k128;
+ this.y = that.y;
+ this.highBound = that.highBound;
+ this.bytesSoFar = that.bytesSoFar;
+ if (that.buffer != null)
+ {
+ byte[] thatbuffer = that.buffer.toByteArray();
+ this.buffer = new ByteArrayOutputStream();
+ this.buffer.write(thatbuffer, 0, thatbuffer.length);
+ }
+ }
+
+ // Class methods
+ // ----------------------------------------------------------------------
+
+ // Instance methods
+ // ----------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation -------------------------
+
+ public Object clone()
+ {
+ return new L2Hash32(this);
+ }
+
+ // other instance methods -----------------------------------------------
+
+ // this is called with either 8-bytes or 16-bytes
+ void update(byte[] b, int offset, int len)
+ {
+ if (len == 0)
+ {
+ return;
+ }
+
+ if (!highBound)
+ { // do the first (only?) 8-bytes
+ poly(64, LOWER_RANGE, k64, b, offset, 8);
+ bytesSoFar += 8L;
+ highBound = (bytesSoFar > BOUNDARY);
+ if (highBound)
+ { // if we just crossed the limit then process y
+ poly(128, UPPER_RANGE, k128, yTo16bytes(), 0, 16);
+ buffer = new ByteArrayOutputStream();
+ }
+ // do the rest if any
+ update(b, offset + 8, len - 8);
+ }
+ else
+ { // we're already beyond the 2**17 bytes size limit
+ // process in chuncks of 16
+ buffer.write(b, offset, len);
+ if (buffer.size() > 16)
+ {
+ byte[] bb = buffer.toByteArray();
+ poly(128, UPPER_RANGE, k128, bb, 0, 16);
+ if (bb.length > 16)
+ {
+ buffer.write(bb, 16, bb.length - 16);
+ }
+ }
+ }
+ }
+
+ byte[] digest()
+ {
+ // If M no more than 2^17 bytes, hash under 64-bit prime,
+ // otherwise, hash first 2^17 bytes under 64-bit prime and
+ // remainder under 128-bit prime.
+ if (!highBound)
+ { // y is up-to-date
+ // do nothing
+ }
+ else
+ { // we may have some bytes in buffer
+ byte[] bb = buffer.toByteArray();
+ byte[] lastBlock = new byte[16];
+ System.arraycopy(bb, 0, lastBlock, 0, bb.length);
+ lastBlock[bb.length] = (byte) 0x80;
+ poly(128, UPPER_RANGE, k128, lastBlock, 0, 16);
+ }
+
+ byte[] result = yTo16bytes();
+ reset();
+ return result;
+ }
+
+ void reset()
+ {
+ y = BigInteger.ONE;
+ highBound = false;
+ bytesSoFar = 0L;
+ if (buffer != null)
+ {
+ buffer.reset();
+ }
+ }
+
+ // helper methods -------------------------------------------------------
+
+ private byte[] yTo16bytes()
+ {
+ byte[] yy = y.toByteArray();
+ byte[] result = new byte[16];
+ if (yy.length > 16)
+ {
+ System.arraycopy(yy, yy.length - 16, result, 0, 16);
+ }
+ else
+ {
+ System.arraycopy(yy, 0, result, 16 - yy.length, yy.length);
+ }
+
+ return result;
+ }
+
+ /**
+ * 5.3 POLY: Polynomial hash
+ * Function Name: POLY
+ *
+ * @param wordbits positive integer divisible by 8: called with 64 or 128.
+ * @param maxwordrange positive integer less than 2**wordbits.
+ * @param k integer in the range 0 .. prime(wordbits) - 1.
+ * @param M string with length divisible by (wordbits / 8) bytes.
+ * return y, integer in the range 0 .. prime(wordbits) - 1.
+ */
+ private void poly(int wordbits, BigInteger maxwordrange, BigInteger k,
+ byte[] M, int off, int len)
+ {
+ byte[] mag = new byte[len];
+ System.arraycopy(M, off, mag, 0, len);
+ // Define constants used for fixing out-of-range words
+ // int wordbytes = wordbits / 8;
+
+ BigInteger p = prime(wordbits);
+ BigInteger offset = TWO.pow(wordbits).subtract(p); // 2^wordbits - p;
+ BigInteger marker = p.subtract(BigInteger.ONE);
+
+ // Break M into chunks of length wordbytes bytes
+ // long n = M.length / wordbytes;
+ // Let M_1, M_2, ..., M_n be strings of length wordbytes bytes
+ // so that M = M_1 || M_2 || .. || M_n
+
+ // For each input word, compare it with maxwordrange. If larger
+ // then hash the words 'marker' and (m - offset), both in range.
+ // for (int i = 0; i < n; i++) {
+ BigInteger m = new BigInteger(1, mag);
+ if (m.compareTo(maxwordrange) >= 0)
+ { // m >= maxwordrange
+ y = y.multiply(k).add(marker).mod(p); // (k * y + marker) % p;
+ y = y.multiply(k).add(m.subtract(offset)).mod(p); // (k * y + (m - offset)) % p;
+ }
+ else
+ {
+ y = y.multiply(k).add(m).mod(p); // (k * y + m) % p;
+ }
+ // }
+
+ // return y;
+ }
+ }
+
+ // =========================================================================
+
+ /**
+ * Third hash stage of the UHash32 algorithm.
+ *
+ * Input:
+ * K1 string of length 64 bytes.
+ * K2 string of length 4 bytes.
+ * M string of length 16 bytes.
+ * Returns:
+ * Y, string of length 4 bytes.
+ */
+ class L3Hash32 implements Cloneable
+ {
+
+ // Constants and variables
+ // ----------------------------------------------------------------------
+
+ private static final long PRIME_36 = 0x0000000FFFFFFFFBL;
+
+ private int[] k = new int[9];
+
+ // Constructor(s)
+ // ----------------------------------------------------------------------
+
+ /**
+ *
+ * @param K1 string of length 64 bytes.
+ * @param K2 string of length 4 bytes.
+ */
+ L3Hash32(byte[] K1, byte[] K2)
+ {
+ super();
+
+ // pre-conditions
+ if (K1.length != 64)
+ {
+ throw new ExceptionInInitializerError("K1 length is not 64");
+ }
+ if (K2.length != 4)
+ {
+ throw new ExceptionInInitializerError("K2 length is not 4");
+ }
+
+ // Break K1 into 8 chunks and convert to integers
+ // int i = 0;
+ // for (int j = 0; i < 8; ) {
+ for (int i = 0, j = 0; i < 8; i++)
+ {
+ long kk = (K1[j++] & 0xFFL) << 56 | (K1[j++] & 0xFFL) << 48
+ | (K1[j++] & 0xFFL) << 40 | (K1[j++] & 0xFFL) << 32
+ | (K1[j++] & 0xFFL) << 24 | (K1[j++] & 0xFFL) << 16
+ | (K1[j++] & 0xFFL) << 8 | (K1[j++] & 0xFFL);
+ // k[i++] = (int)(kk % PRIME_36);
+ k[i] = (int) (kk % PRIME_36);
+ }
+ // k[i] = K2[0] << 24 | (K2[1] & 0xFF) << 16 | (K2[2] & 0xFF) << 8 | (K2[3] & 0xFF);
+ k[8] = K2[0] << 24 | (K2[1] & 0xFF) << 16 | (K2[2] & 0xFF) << 8
+ | (K2[3] & 0xFF);
+ }
+
+ private L3Hash32(int[] k)
+ {
+ super();
+
+ this.k = k;
+ }
+
+ // Class methods
+ // ----------------------------------------------------------------------
+
+ // Instance methods
+ // ----------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation -------------------------
+
+ public Object clone()
+ {
+ return new L3Hash32((int[]) k.clone());
+ }
+
+ // other instance methods -----------------------------------------------
+
+ /**
+ * @param M string of length 16 bytes.
+ * @return Y, string of length 4 bytes.
+ */
+ byte[] digest(byte[] M)
+ {
+ if (M.length != 16)
+ {
+ throw new IllegalArgumentException("M length is not 16");
+ }
+
+ long m, y = 0L;
+ for (int i = 0, j = 0; i < 8; i++)
+ {
+ // Break M into 8 chunks and convert to integers
+ m = (M[j++] & 0xFFL) << 8 | (M[j++] & 0xFFL);
+
+ // Inner-product hash, extract last 32 bits and affine-translate
+ // y = (m_1 * k_1 + ... + m_8 * k_8) mod prime(36);
+ // y = y mod 2^32;
+ y += (m * (k[i] & 0xFFFFFFFFL)) % PRIME_36;
+ }
+ int Y = ((int) y) ^ k[8];
+ return new byte[] { (byte) (Y >>> 24), (byte) (Y >>> 16),
+ (byte) (Y >>> 8), (byte) Y };
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mac/UMac32.java b/gnu/javax/crypto/mac/UMac32.java
new file mode 100644
index 000000000..d20d4f4a9
--- /dev/null
+++ b/gnu/javax/crypto/mac/UMac32.java
@@ -0,0 +1,491 @@
+/* UMac32.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mac;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.prng.UMacGenerator;
+
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>The implementation of the <i>UMAC</i> (Universal Message Authentication
+ * Code).</p>
+ *
+ * <p>The <i>UMAC</i> algorithms described are <i>parameterized</i>. This means
+ * that various low-level choices, like the endian convention and the underlying
+ * cryptographic primitive, have not been fixed. One must choose values for
+ * these parameters before the authentication tag generated by <i>UMAC</i> (for
+ * a given message, key, and nonce) becomes fully-defined. In this document
+ * we provide two collections of parameter settings, and have named the sets
+ * <i>UMAC16</i> and <i>UMAC32</i>. The parameter sets have been chosen based on
+ * experimentation and provide good performance on a wide variety of processors.
+ * <i>UMAC16</i> is designed to excel on processors which provide small-scale
+ * SIMD parallelism of the type found in Intel's MMX and Motorola's AltiVec
+ * instruction sets, while <i>UMAC32</i> is designed to do well on processors
+ * with good 32- and 64- bit support. <i>UMAC32</i> may take advantage of SIMD
+ * parallelism in future processors.</p>
+ *
+ * <p><i>UMAC</i> has been designed to allow implementations which accommodate
+ * <i>on-line</i> authentication. This means that pieces of the message may
+ * be presented to <i>UMAC</i> at different times (but in correct order) and an
+ * on-line implementation will be able to process the message correctly without
+ * the need to buffer more than a few dozen bytes of the message. For
+ * simplicity, the algorithms in this specification are presented as if the
+ * entire message being authenticated were available at once.</p>
+ *
+ * <p>To authenticate a message, <code>Msg</code>, one first applies the
+ * universal hash function, resulting in a string which is typically much
+ * shorter than the original message. The pseudorandom function is applied to a
+ * nonce, and the result is used in the manner of a Vernam cipher: the
+ * authentication tag is the xor of the output from the hash function and the
+ * output from the pseudorandom function. Thus, an authentication tag is
+ * generated as</p>
+ *
+ * <pre>
+ * AuthTag = f(Nonce) xor h(Msg)
+ * </pre>
+ *
+ * <p>Here <code>f</code> is the pseudorandom function shared between the sender
+ * and the receiver, and h is a universal hash function shared by the sender and
+ * the receiver. In <i>UMAC</i>, a shared key is used to key the pseudorandom
+ * function <code>f</code>, and then <code>f</code> is used for both tag
+ * generation and internally to generate all of the bits needed by the universal
+ * hash function.</p>
+ *
+ * <p>The universal hash function that we use is called <code>UHASH</code>. It
+ * combines several software-optimized algorithms into a multi-layered
+ * structure. The algorithm is moderately complex. Some of this complexity comes
+ * from extensive speed optimizations.</p>
+ *
+ * <p>For the pseudorandom function we use the block cipher of the <i>Advanced
+ * Encryption Standard</i> (AES).</p>
+ *
+ * <p>The UMAC32 parameters, considered in this implementation are:</p>
+ * <pre>
+ * UMAC32
+ * ------
+ * WORD-LEN 4
+ * UMAC-OUTPUT-LEN 8
+ * L1-KEY-LEN 1024
+ * UMAC-KEY-LEN 16
+ * ENDIAN-FAVORITE BIG *
+ * L1-OPERATIONS-SIGN UNSIGNED
+ * </pre>
+ *
+ * <p>Please note that this UMAC32 differs from the one described in the paper
+ * by the <i>ENDIAN-FAVORITE</i> value.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
+ * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
+ * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
+ * </ol>
+ */
+public class UMac32 extends BaseMac
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * Property name of the user-supplied <i>Nonce</i>. The value associated to
+ * this property name is taken to be a byte array.
+ */
+ public static final String NONCE_MATERIAL = "gnu.crypto.umac.nonce.material";
+
+ /** Known test vector. */
+ // private static final String TV1 = "3E5A0E09198B0F94";
+ // private static final String TV1 = "5FD764A6D3A9FD9D";
+ // private static final String TV1 = "48658DE1D9A70304";
+ private static final String TV1 = "455ED214A6909F20";
+
+ private static final BigInteger MAX_NONCE_ITERATIONS = BigInteger.ONE.shiftLeft(16 * 8);
+
+ // UMAC32 parameters
+ static final int OUTPUT_LEN = 8;
+
+ static final int L1_KEY_LEN = 1024;
+
+ static final int KEY_LEN = 16;
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ private byte[] nonce;
+
+ private UHash32 uhash32;
+
+ private BigInteger nonceReuseCount;
+
+ /** The authentication key for this instance. */
+ private transient byte[] K;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public UMac32()
+ {
+ super("umac32");
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param that the instance to clone.
+ */
+ private UMac32(UMac32 that)
+ {
+ this();
+
+ if (that.K != null)
+ {
+ this.K = (byte[]) that.K.clone();
+ }
+ if (that.nonce != null)
+ {
+ this.nonce = (byte[]) that.nonce.clone();
+ }
+ if (that.uhash32 != null)
+ {
+ this.uhash32 = (UHash32) that.uhash32.clone();
+ }
+ this.nonceReuseCount = that.nonceReuseCount;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new UMac32(this);
+ }
+
+ // gnu.crypto.mac.IMac interface implementation ----------------------------
+
+ public int macSize()
+ {
+ return OUTPUT_LEN;
+ }
+
+ /**
+ * <p>Initialising a <i>UMAC</i> instance consists of defining values for
+ * the following parameters:</p>
+ *
+ * <ol>
+ * <li>Key Material: as the value of the attribute entry keyed by
+ * {@link #MAC_KEY_MATERIAL}. The value is taken to be a byte array
+ * containing the user-specified key material. The length of this array,
+ * if/when defined SHOULD be exactly equal to {@link #KEY_LEN}.</li>
+ *
+ * <li>Nonce Material: as the value of the attribute entry keyed by
+ * {@link #NONCE_MATERIAL}. The value is taken to be a byte array
+ * containing the user-specified nonce material. The length of this array,
+ * if/when defined SHOULD be (a) greater than zero, and (b) less or equal
+ * to 16 (the size of the AES block).</li>
+ * </ol>
+ *
+ * <p>For convenience, this implementation accepts that not both parameters
+ * be always specified.</p>
+ *
+ * <ul>
+ * <li>If the <i>Key Material</i> is specified, but the <i>Nonce Material</i>
+ * is not, then this implementation, re-uses the previously set <i>Nonce
+ * Material</i> after (a) converting the bytes to an unsigned integer,
+ * (b) incrementing the number by one, and (c) converting it back to 16
+ * bytes.</li>
+ *
+ * <li>If the <i>Nonce Material</i> is specified, but the <i>Key Material</i>
+ * is not, then this implementation re-uses the previously set <i>Key
+ * Material</i>.</li>
+ * </ul>
+ *
+ * <p>This method throws an exception if no <i>Key Material</i> is specified
+ * in the input map, and there is no previously set/defined <i>Key Material</i>
+ * (from an earlier invocation of this method). If a <i>Key Material</i> can
+ * be used, but no <i>Nonce Material</i> is defined or previously set/defined,
+ * then a default value of all-zeroes shall be used.</p>
+ *
+ * @param attributes one or both of required parameters.
+ * @throws InvalidKeyException the key material specified is not of the
+ * correct length.
+ */
+ public void init(Map attributes) throws InvalidKeyException,
+ IllegalStateException
+ {
+ byte[] key = (byte[]) attributes.get(MAC_KEY_MATERIAL);
+ byte[] n = (byte[]) attributes.get(NONCE_MATERIAL);
+
+ boolean newKey = (key != null);
+ boolean newNonce = (n != null);
+
+ if (newKey)
+ {
+ if (key.length != KEY_LEN)
+ {
+ throw new InvalidKeyException("Key length: "
+ + String.valueOf(key.length));
+ }
+ K = key;
+ }
+ else
+ {
+ if (K == null)
+ {
+ throw new InvalidKeyException("Null Key");
+ }
+ }
+
+ if (newNonce)
+ {
+ if (n.length < 1 || n.length > 16)
+ {
+ throw new IllegalArgumentException("Invalid Nonce length: "
+ + String.valueOf(n.length));
+ }
+
+ if (n.length < 16)
+ { // pad with zeroes
+ byte[] newN = new byte[16];
+ System.arraycopy(n, 0, newN, 0, n.length);
+ nonce = newN;
+ }
+ else
+ {
+ nonce = n;
+ }
+
+ nonceReuseCount = BigInteger.ZERO;
+ }
+ else if (nonce == null)
+ { // use all-0 nonce if 1st time
+ nonce = new byte[16];
+ nonceReuseCount = BigInteger.ZERO;
+ }
+ else if (!newKey)
+ { // increment nonce if still below max count
+ nonceReuseCount = nonceReuseCount.add(BigInteger.ONE);
+ if (nonceReuseCount.compareTo(MAX_NONCE_ITERATIONS) >= 0)
+ {
+ // limit reached. we SHOULD have a key
+ throw new InvalidKeyException("Null Key and unusable old Nonce");
+ }
+ BigInteger N = new BigInteger(1, nonce);
+ N = N.add(BigInteger.ONE).mod(MAX_NONCE_ITERATIONS);
+ n = N.toByteArray();
+ if (n.length == 16)
+ {
+ nonce = n;
+ }
+ else if (n.length < 16)
+ {
+ nonce = new byte[16];
+ System.arraycopy(n, 0, nonce, 16 - n.length, n.length);
+ }
+ else
+ {
+ nonce = new byte[16];
+ System.arraycopy(n, n.length - 16, nonce, 0, 16);
+ }
+ }
+ else
+ { // do nothing, re-use old nonce value
+ nonceReuseCount = BigInteger.ZERO;
+ }
+
+ if (uhash32 == null)
+ {
+ uhash32 = new UHash32();
+ }
+
+ Map map = new HashMap();
+ map.put(MAC_KEY_MATERIAL, K);
+ uhash32.init(map);
+ }
+
+ public void update(byte b)
+ {
+ uhash32.update(b);
+ }
+
+ public void update(byte[] b, int offset, int len)
+ {
+ uhash32.update(b, offset, len);
+ }
+
+ public byte[] digest()
+ {
+ byte[] result = uhash32.digest();
+ byte[] pad = pdf(); // pdf(K, nonce);
+ for (int i = 0; i < OUTPUT_LEN; i++)
+ {
+ result[i] = (byte) (result[i] ^ pad[i]);
+ }
+
+ return result;
+ }
+
+ public void reset()
+ {
+ if (uhash32 != null)
+ {
+ uhash32.reset();
+ }
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ byte[] key;
+ try
+ {
+ key = "abcdefghijklmnop".getBytes("ASCII");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new RuntimeException("ASCII not supported");
+ }
+ byte[] nonce = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
+ UMac32 mac = new UMac32();
+ Map attributes = new HashMap();
+ attributes.put(MAC_KEY_MATERIAL, key);
+ attributes.put(NONCE_MATERIAL, nonce);
+ try
+ {
+ mac.init(attributes);
+ }
+ catch (InvalidKeyException x)
+ {
+ x.printStackTrace(System.err);
+ return false;
+ }
+
+ byte[] data = new byte[128];
+ data[0] = (byte) 0x80;
+
+ mac.update(data, 0, 128);
+ byte[] result = mac.digest();
+ // System.out.println("UMAC test vector: "+Util.toString(result));
+ valid = new Boolean(TV1.equals(Util.toString(result)));
+ }
+ return valid.booleanValue();
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ *
+ * @return byte array of length 8 (or OUTPUT_LEN) bytes.
+ */
+ private byte[] pdf()
+ {
+ // Make Nonce 16 bytes by prepending zeroes. done (see init())
+
+ // one AES invocation is enough for more than one PDF invocation
+ // number of index bits needed = 1
+
+ // Extract index bits and zero low bits of Nonce
+ BigInteger Nonce = new BigInteger(1, nonce);
+ int nlowbitsnum = Nonce.testBit(0) ? 1 : 0;
+ Nonce = Nonce.clearBit(0);
+
+ // Generate subkey, AES and extract indexed substring
+ IRandom kdf = new UMacGenerator();
+ Map map = new HashMap();
+ map.put(IBlockCipher.KEY_MATERIAL, K);
+ // map.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(128/8));
+ map.put(UMacGenerator.INDEX, new Integer(128));
+ // map.put(UMacGenerator.CIPHER, Registry.AES_CIPHER);
+ kdf.init(map);
+ byte[] Kp = new byte[KEY_LEN];
+ try
+ {
+ kdf.nextBytes(Kp, 0, KEY_LEN);
+ }
+ catch (IllegalStateException x)
+ {
+ x.printStackTrace(System.err);
+ throw new RuntimeException(String.valueOf(x));
+ }
+ catch (LimitReachedException x)
+ {
+ x.printStackTrace(System.err);
+ throw new RuntimeException(String.valueOf(x));
+ }
+ IBlockCipher aes = CipherFactory.getInstance(Registry.AES_CIPHER);
+ map.put(IBlockCipher.KEY_MATERIAL, Kp);
+ try
+ {
+ aes.init(map);
+ }
+ catch (InvalidKeyException x)
+ {
+ x.printStackTrace(System.err);
+ throw new RuntimeException(String.valueOf(x));
+ }
+ catch (IllegalStateException x)
+ {
+ x.printStackTrace(System.err);
+ throw new RuntimeException(String.valueOf(x));
+ }
+ byte[] T = new byte[16];
+ aes.encryptBlock(nonce, 0, T, 0);
+ byte[] result = new byte[OUTPUT_LEN];
+ System.arraycopy(T, nlowbitsnum, result, 0, OUTPUT_LEN);
+
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/BaseMode.java b/gnu/javax/crypto/mode/BaseMode.java
new file mode 100644
index 000000000..0a9ab2dab
--- /dev/null
+++ b/gnu/javax/crypto/mode/BaseMode.java
@@ -0,0 +1,352 @@
+/* BaseMode.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.security.InvalidKeyException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * <p>A basic abstract class to facilitate implementing block cipher modes of
+ * operations.</p>
+ */
+public abstract class BaseMode implements IMode
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of this mode. */
+ protected String name;
+
+ /** The state indicator of this instance. */
+ protected int state;
+
+ /** The underlying block cipher implementation. */
+ protected IBlockCipher cipher;
+
+ /** The block size, in bytes, to operate the underlying block cipher in. */
+ protected int cipherBlockSize;
+
+ /** The block size, in bytes, in which to operate the mode instance. */
+ protected int modeBlockSize;
+
+ /** The initialisation vector value. */
+ protected byte[] iv;
+
+ /** The instance lock. */
+ protected Object lock = new Object();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name prefix of this mode.
+ * @param underlyingCipher the implementation of the underlying cipher.
+ * @param cipherBlockSize the block size, in bytes, in which to operate the
+ * underlying cipher.
+ */
+ protected BaseMode(String name, IBlockCipher underlyingCipher,
+ int cipherBlockSize)
+ {
+ super();
+
+ this.name = name;
+ this.cipher = underlyingCipher;
+ this.cipherBlockSize = cipherBlockSize;
+ state = -1;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IMode interface implementation ------------------------------------------
+
+ public void update(byte[] in, int inOffset, byte[] out, int outOffset)
+ throws IllegalStateException
+ {
+ synchronized (lock)
+ {
+ switch (state)
+ {
+ case ENCRYPTION:
+ encryptBlock(in, inOffset, out, outOffset);
+ break;
+ case DECRYPTION:
+ decryptBlock(in, inOffset, out, outOffset);
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ // IBlockCipher interface implementation -----------------------------------
+
+ public String name()
+ {
+ return new StringBuffer().append(name).append('(').append(cipher.name()).append(
+ ')').toString();
+ }
+
+ /**
+ * <p>Returns the default value, in bytes, of the mode's block size. This
+ * value is part of the construction arguments passed to the Factory methods
+ * in {@link ModeFactory}. Unless changed by an invocation of any of the
+ * <code>init()</code> methods, a <i>Mode</i> instance would operate with
+ * the same block size as its underlying block cipher. As mentioned earlier,
+ * the block size of the underlying block cipher itself is specified in one
+ * of the method(s) available in the factory class.</p>
+ *
+ * @return the default value, in bytes, of the mode's block size.
+ * @see gnu.crypto.mode.ModeFactory
+ */
+ public int defaultBlockSize()
+ {
+ return cipherBlockSize;
+ }
+
+ /**
+ * <p>Returns the default value, in bytes, of the underlying block cipher
+ * key size.</p>
+ *
+ * @return the default value, in bytes, of the underlying cipher's key size.
+ */
+ public int defaultKeySize()
+ {
+ return cipher.defaultKeySize();
+ }
+
+ /**
+ * <p>Returns an {@link Iterator} over the supported block sizes. Each
+ * element returned by this object is an {@link Integer}.</p>
+ *
+ * <p>The default behaviour is to return an iterator with just one value,
+ * which is that currently configured for the underlying block cipher.
+ * Concrete implementations may override this behaviour to signal their
+ * ability to support other values.</p>
+ *
+ * @return an {@link Iterator} over the supported block sizes.
+ */
+ public Iterator blockSizes()
+ {
+ ArrayList al = new ArrayList();
+ al.add(new Integer(cipherBlockSize));
+
+ return Collections.unmodifiableList(al).iterator();
+ }
+
+ /**
+ * <p>Returns an {@link Iterator} over the supported underlying block cipher
+ * key sizes. Each element returned by this object is an instance of
+ * {@link Integer}.</p>
+ *
+ * @return an {@link Iterator} over the supported key sizes.
+ */
+ public Iterator keySizes()
+ {
+ return cipher.keySizes();
+ }
+
+ public void init(Map attributes) throws InvalidKeyException,
+ IllegalStateException
+ {
+ synchronized (lock)
+ {
+ if (state != -1)
+ {
+ throw new IllegalStateException();
+ }
+
+ Integer want = (Integer) attributes.get(STATE);
+ if (want != null)
+ {
+ switch (want.intValue())
+ {
+ case ENCRYPTION:
+ state = ENCRYPTION;
+ break;
+ case DECRYPTION:
+ state = DECRYPTION;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ Integer bs = (Integer) attributes.get(MODE_BLOCK_SIZE);
+ modeBlockSize = (bs == null ? cipherBlockSize : bs.intValue());
+
+ byte[] iv = (byte[]) attributes.get(IV);
+ if (iv != null)
+ {
+ this.iv = (byte[]) iv.clone();
+ }
+ else
+ {
+ this.iv = new byte[modeBlockSize];
+ }
+
+ cipher.init(attributes);
+ setup();
+ }
+ }
+
+ public int currentBlockSize()
+ {
+ if (state == -1)
+ {
+ throw new IllegalStateException();
+ }
+ return modeBlockSize;
+ }
+
+ public void reset()
+ {
+ synchronized (lock)
+ {
+ state = -1;
+ iv = null;
+ cipher.reset();
+
+ teardown();
+ }
+ }
+
+ public boolean selfTest()
+ {
+ int ks;
+ Iterator bit;
+ for (Iterator kit = keySizes(); kit.hasNext();)
+ {
+ ks = ((Integer) kit.next()).intValue();
+ for (bit = blockSizes(); bit.hasNext();)
+ {
+ if (!testSymmetry(ks, ((Integer) bit.next()).intValue()))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // methods to be implemented by concrete subclasses ------------------------
+
+ public abstract Object clone();
+
+ /** The initialisation phase of the concrete mode implementation. */
+ public abstract void setup();
+
+ /** The termination phase of the concrete mode implementation. */
+ public abstract void teardown();
+
+ public abstract void encryptBlock(byte[] in, int i, byte[] out, int o);
+
+ public abstract void decryptBlock(byte[] in, int i, byte[] out, int o);
+
+ // own methods -------------------------------------------------------------
+
+ private boolean testSymmetry(int ks, int bs)
+ {
+ try
+ {
+ IMode mode = (IMode) this.clone();
+ byte[] iv = new byte[cipherBlockSize]; // all zeroes
+ byte[] k = new byte[ks];
+ int i;
+ for (i = 0; i < ks; i++)
+ {
+ k[i] = (byte) i;
+ }
+
+ int blockCount = 5;
+ int limit = blockCount * bs;
+ byte[] pt = new byte[limit];
+ for (i = 0; i < limit; i++)
+ {
+ pt[i] = (byte) i;
+ }
+ byte[] ct = new byte[limit];
+ byte[] cpt = new byte[limit];
+
+ Map map = new HashMap();
+ map.put(KEY_MATERIAL, k);
+ map.put(CIPHER_BLOCK_SIZE, new Integer(cipherBlockSize));
+ map.put(STATE, new Integer(ENCRYPTION));
+ map.put(IV, iv);
+ map.put(MODE_BLOCK_SIZE, new Integer(bs));
+
+ mode.reset();
+ mode.init(map);
+ for (i = 0; i < blockCount; i++)
+ {
+ mode.update(pt, i * bs, ct, i * bs);
+ }
+
+ mode.reset();
+ map.put(STATE, new Integer(DECRYPTION));
+ mode.init(map);
+ for (i = 0; i < blockCount; i++)
+ {
+ mode.update(ct, i * bs, cpt, i * bs);
+ }
+
+ return Arrays.equals(pt, cpt);
+
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace(System.err);
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/CBC.java b/gnu/javax/crypto/mode/CBC.java
new file mode 100644
index 000000000..10578a6ef
--- /dev/null
+++ b/gnu/javax/crypto/mode/CBC.java
@@ -0,0 +1,143 @@
+/* CBC.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+/**
+ * The Cipher Block Chaining mode. This mode introduces feedback into
+ * the cipher by XORing the previous ciphertext block with the plaintext
+ * block before encipherment. That is, encrypting looks like this:</p>
+ *
+ * <blockquote><p>C<sub>i</sub> = E<sub>K</sub>(P<sub>i</sub> ^
+ * C<sub>i-1</sub></p></blockquote>
+ *
+ * <p>Similarly, decrypting is:</p>
+ *
+ * <blockquote><p>P<sub>i</sub> = C<sub>i-1</sub> ^
+ * D<sub>K</sub>(C<sub>i</sub>)</p></blockquote>
+ */
+public class CBC extends BaseMode implements Cloneable
+{
+
+ // Constants and Variables
+ //------------------------------------------------------------------
+
+ /** The last (de|en)crypted block */
+ private byte[] lastBlock;
+
+ /** An intermediate buffer. */
+ private byte[] scratch;
+
+ // Constructors
+ // -----------------------------------------------------------------
+
+ /**
+ * Package-private constructor for the factory class.
+ *
+ * @param underlyingCipher The cipher implementation.
+ * @param cipherBlockSize The cipher's block size.
+ */
+ CBC(IBlockCipher underlyingCipher, int cipherBlockSize)
+ {
+ super(Registry.CBC_MODE, underlyingCipher, cipherBlockSize);
+ }
+
+ /** Our constructor for cloning. */
+ private CBC(CBC that)
+ {
+ this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
+ }
+
+ // Cloneable interface implementation
+ // -----------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new CBC(this);
+ }
+
+ // Implementation of abstract methods in BaseMode
+ // -----------------------------------------------------------------
+
+ public void setup()
+ {
+ if (modeBlockSize != cipherBlockSize)
+ {
+ throw new IllegalArgumentException();
+ }
+ scratch = new byte[cipherBlockSize];
+ lastBlock = new byte[cipherBlockSize];
+
+ // lastBlock gets initialized to the initialization vector.
+ for (int i = 0; i < lastBlock.length && i < iv.length; i++)
+ {
+ lastBlock[i] = iv[i];
+ }
+ }
+
+ public void teardown()
+ {
+ lastBlock = null;
+ scratch = null;
+ }
+
+ public void encryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ for (int k = 0; k < scratch.length; k++)
+ {
+ scratch[k] = (byte) (lastBlock[k] ^ in[k + i]);
+ }
+ cipher.encryptBlock(scratch, 0, out, o);
+ System.arraycopy(out, o, lastBlock, 0, cipherBlockSize);
+ }
+
+ public void decryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ byte[] buf = new byte[cipherBlockSize];
+ System.arraycopy(in, i, buf, 0, cipherBlockSize);
+ cipher.decryptBlock(in, i, scratch, 0);
+ for (int k = 0; k < scratch.length; k++)
+ {
+ out[o + k] = (byte) (lastBlock[k] ^ scratch[k]);
+ }
+ System.arraycopy(buf, 0, lastBlock, 0, cipherBlockSize);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/CFB.java b/gnu/javax/crypto/mode/CFB.java
new file mode 100644
index 000000000..fef2b634c
--- /dev/null
+++ b/gnu/javax/crypto/mode/CFB.java
@@ -0,0 +1,175 @@
+/* CFB.java --
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+/**
+ * The cipher feedback mode. CFB mode is a stream mode that operates on
+ * <i>s</i> bit blocks, where 1 &lt;= <i>s</i> &lt;= <i>b</i>, if
+ * <i>b</i> is the underlying cipher's block size. Encryption is:
+ *
+ <pre>
+ I[1] = IV
+ I[j] = LSB(b-s, I[j-1]) | C[j-1] for j = 2...n
+ O[j] = CIPH(K, I[j]) for j = 1,2...n
+ C[j] = P[j] ^ MSB(s, O[j]) for j = 1,2...n
+ </pre>
+ *
+ * <p>And decryption is:</p>
+ *
+ <pre>
+ I[1] = IV
+ I[j] = LSB(b-s, I[j-1]) | C[j-1] for j = 2...n
+ O[j] = CIPH(K, I[j]) for j = 1,2...n
+ P[j] = C[j] ^ MSB(s, O[j]) for j = 1,2...n
+ </pre>
+ *
+ * <p>CFB mode requires an initialization vector, which need not be kept
+ * secret.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms,
+ * and Source Code in C, Second Edition</i>. (1996 John Wiley and Sons)
+ * ISBN 0-471-11709-9.</li>
+ *
+ * <li><a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
+ * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
+ * Morris Dworkin.</li>
+ * </ol>
+ */
+public class CFB extends BaseMode
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ /** The shift register, the input block to the block cipher. */
+ private byte[] shiftRegister;
+
+ /** The output block from the block cipher. */
+ private byte[] scratch;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Package-private constructor for the factory class.
+ *
+ * @param underlyingCipher The cipher implementation.
+ * @param cipherBlockSize The cipher's block size.
+ */
+ CFB(IBlockCipher underlyingCipher, int cipherBlockSize)
+ {
+ super(Registry.CFB_MODE, underlyingCipher, cipherBlockSize);
+ }
+
+ /**
+ * Cloneing constructor.
+ *
+ * @param that The instance being cloned.
+ */
+ private CFB(CFB that)
+ {
+ this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
+ }
+
+ // Instance methods implementing BaseMode.
+ // -----------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new CFB(this);
+ }
+
+ public void setup()
+ {
+ if (modeBlockSize > cipherBlockSize)
+ {
+ throw new IllegalArgumentException(
+ "CFB block size cannot be larger than the cipher block size");
+ }
+ shiftRegister = new byte[cipherBlockSize];
+ scratch = new byte[cipherBlockSize];
+ System.arraycopy(iv, 0, shiftRegister, 0, Math.min(iv.length,
+ cipherBlockSize));
+ }
+
+ public void teardown()
+ {
+ if (shiftRegister != null)
+ {
+ for (int i = 0; i < shiftRegister.length; i++)
+ {
+ shiftRegister[i] = 0;
+ }
+ }
+ shiftRegister = null;
+ }
+
+ public void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ cipher.encryptBlock(shiftRegister, 0, scratch, 0);
+ for (int i = 0; i < modeBlockSize; i++)
+ {
+ out[outOffset + i] = (byte) (in[inOffset + i] ^ scratch[i]);
+ }
+ System.arraycopy(shiftRegister, modeBlockSize, shiftRegister, 0,
+ cipherBlockSize - modeBlockSize);
+ System.arraycopy(out, outOffset, shiftRegister, cipherBlockSize
+ - modeBlockSize,
+ modeBlockSize);
+ }
+
+ public void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ cipher.encryptBlock(shiftRegister, 0, scratch, 0);
+ for (int i = 0; i < modeBlockSize; i++)
+ {
+ out[outOffset + i] = (byte) (in[inOffset + i] ^ scratch[i]);
+ }
+ System.arraycopy(shiftRegister, modeBlockSize, shiftRegister, 0,
+ cipherBlockSize - modeBlockSize);
+ System.arraycopy(in, inOffset, shiftRegister, cipherBlockSize
+ - modeBlockSize,
+ modeBlockSize);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/CTR.java b/gnu/javax/crypto/mode/CTR.java
new file mode 100644
index 000000000..49f4b9f3c
--- /dev/null
+++ b/gnu/javax/crypto/mode/CTR.java
@@ -0,0 +1,221 @@
+/* CTR.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Sequence;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * <p>The implementation of the Counter Mode.</p>
+ *
+ * <p>The algorithm steps are formally described as follows:</p>
+ *
+ * <pre>
+ * CTR Encryption: O[j] = E(K)(T[j]); for j = 1, 2...n;
+ * C[j] = P[j] ^ O[j]; for j = 1, 2...n.
+ * CTR Decryption: O[j] = E(K)(T[j]); for j = 1, 2...n;
+ * P[j] = C[j] ^ O[j]; for j = 1, 2...n.
+ * </pre>
+ *
+ * <p>where <code>P</code> is the plaintext, <code>C</code> is the ciphertext,
+ * <code>E(K)</code> is the underlying block cipher encryption function
+ * parametrised with the session key <code>K</code>, and <code>T</code> is the
+ * <i>Counter</i>.</p>
+ *
+ * <p>This implementation, uses a standard incrementing function with a step of
+ * 1, and an initial value similar to that described in the NIST document.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
+ * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
+ * Morris Dworkin.</li>
+ * </ol>
+ */
+public class CTR extends BaseMode implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The current counter. */
+ // private BigInteger T;
+ private int off;
+
+ private byte[] counter, enc;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial package-private constructor for use by the Factory class.</p>
+ *
+ * @param underlyingCipher the underlying cipher implementation.
+ * @param cipherBlockSize the underlying cipher block size to use.
+ */
+ CTR(IBlockCipher underlyingCipher, int cipherBlockSize)
+ {
+ super(Registry.CTR_MODE, underlyingCipher, cipherBlockSize);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param that the instance to clone.
+ */
+ private CTR(CTR that)
+ {
+ this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Cloneable interface implementation
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new CTR(this);
+ }
+
+ // Implementation of abstract methods in BaseMode
+ // -------------------------------------------------------------------------
+
+ public void setup()
+ {
+ if (modeBlockSize > cipherBlockSize)
+ {
+ throw new IllegalArgumentException(
+ "mode size exceeds cipher block size");
+ }
+ off = 0;
+ counter = new byte[cipherBlockSize];
+ int i = cipherBlockSize - 1;
+ int j = iv.length - 1;
+ while (i >= 0 && j >= 0)
+ {
+ counter[i--] = iv[j--];
+ }
+ enc = new byte[cipherBlockSize];
+ cipher.encryptBlock(counter, 0, enc, 0);
+ // if (modeBlockSize != cipherBlockSize) {
+ // throw new IllegalArgumentException();
+ // }
+
+ // byte[] tBytes = new byte[modeBlockSize+1];
+ // tBytes[0] = (byte) 0x80;
+ // for (int i = 0; i < modeBlockSize; i++) {
+ // tBytes[i+1] = (byte)(256 - modeBlockSize + i);
+ // }
+
+ // T = new BigInteger(1, tBytes);
+ }
+
+ public void teardown()
+ {
+ if (counter != null)
+ {
+ Arrays.fill(counter, (byte) 0);
+ }
+ if (enc != null)
+ {
+ Arrays.fill(enc, (byte) 0);
+ }
+ // T = null;
+ }
+
+ public void encryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ ctr(in, i, out, o);
+ }
+
+ public void decryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ ctr(in, i, out, o);
+ }
+
+ public Iterator blockSizes()
+ {
+ return new Sequence(1, cipherBlockSize).iterator();
+ }
+
+ // own methods
+ // -------------------------------------------------------------------------
+
+ private void ctr(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ // T = T.add(BigInteger.ONE);
+ // byte[] O = T.toByteArray();
+ // int ndx = O.length - modeBlockSize;
+ // cipher.encryptBlock(O, ndx, O, ndx);
+ // for (int i = 0; i < modeBlockSize; i++) {
+ // out[outOffset++] = (byte)(in[inOffset++] ^ O[ndx++]);
+ // }
+ for (int i = 0; i < modeBlockSize; i++)
+ {
+ out[outOffset++] = (byte) (in[inOffset++] ^ enc[off++]);
+ if (off == cipherBlockSize)
+ {
+ int j;
+ for (j = cipherBlockSize - 1; j >= 0; j--)
+ {
+ counter[j]++;
+ if ((counter[j] & 0xFF) != 0)
+ {
+ break;
+ }
+ }
+ if (j == 0)
+ {
+ counter[cipherBlockSize - 1]++;
+ }
+ off = 0;
+ cipher.encryptBlock(counter, 0, enc, 0);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/EAX.java b/gnu/javax/crypto/mode/EAX.java
new file mode 100644
index 000000000..bf2609898
--- /dev/null
+++ b/gnu/javax/crypto/mode/EAX.java
@@ -0,0 +1,352 @@
+/* EAX.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.java.security.Registry;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+
+import java.security.InvalidKeyException;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * <p>A conventional two-pass authenticated-encrypted mode, EAX. EAX is a
+ * <i>Authenticated Encryption with Additional Data</i> (<b>AEAD</b>) scheme,
+ * which provides protection and authentication for the message, and provides
+ * authentication of an (optional) header. EAX is composed of the counter mode
+ * (CTR) and the one-key CBC MAC (OMAC).
+ *
+ * <p>This class makes full use of the {@link IAuthenticatedMode} interface,
+ * that is, all methods of both {@link IMode} and {@link IMac} can be used
+ * as specified in the {@link IAuthenticatedMode} interface.
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li>M. Bellare, P. Rogaway, and D. Wagner; <a
+ * href="http://www.cs.berkeley.edu/~daw/papers/eprint-short-ae.pdf">A
+ * Conventional Authenticated-Encryption Mode</a>.</li>
+ * </ol>
+ */
+public class EAX implements IAuthenticatedMode
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ /** The tag size, in bytes. */
+ private int tagSize;
+
+ /** The nonce OMAC instance. */
+ private IMac nonceOmac;
+
+ /** The header OMAC instance. */
+ private IMac headerOmac;
+
+ /** The message OMAC instance. */
+ private IMac msgOmac;
+
+ /** The CTR instance. */
+ private IMode ctr;
+
+ /** The direction state (encrypting or decrypting). */
+ private int state;
+
+ /** Whether we're initialized or not. */
+ private boolean init;
+
+ /** The cipher block size. */
+ private int cipherBlockSize;
+
+ /** The cipher. */
+ private IBlockCipher cipher;
+
+ /** The [t]_n array. */
+ private byte[] t_n;
+
+ private static boolean valid = false;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ public EAX(IBlockCipher cipher, int cipherBlockSize)
+ {
+ this.cipher = cipher;
+ this.cipherBlockSize = cipherBlockSize;
+ String name = cipher.name();
+ int i = name.indexOf('-');
+ if (i >= 0)
+ {
+ name = name.substring(0, i);
+ }
+ String omacname = Registry.OMAC_PREFIX + name;
+ nonceOmac = MacFactory.getInstance(omacname);
+ headerOmac = MacFactory.getInstance(omacname);
+ msgOmac = MacFactory.getInstance(omacname);
+ ctr = ModeFactory.getInstance(Registry.CTR_MODE, cipher, cipherBlockSize);
+ t_n = new byte[cipherBlockSize];
+ init = false;
+ }
+
+ // IMode instance methods.
+ // ------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new EAX((IBlockCipher) cipher.clone(), cipherBlockSize);
+ }
+
+ public String name()
+ {
+ return Registry.EAX_MODE + "(" + cipher.name() + ")";
+ }
+
+ public int defaultBlockSize()
+ {
+ return ctr.defaultBlockSize();
+ }
+
+ public int defaultKeySize()
+ {
+ return ctr.defaultKeySize();
+ }
+
+ public Iterator blockSizes()
+ {
+ return ctr.blockSizes();
+ }
+
+ public Iterator keySizes()
+ {
+ return ctr.keySizes();
+ }
+
+ public void init(Map attrib) throws InvalidKeyException
+ {
+ byte[] nonce = (byte[]) attrib.get(IV);
+ if (nonce == null)
+ {
+ throw new IllegalArgumentException("no nonce provided");
+ }
+ byte[] key = (byte[]) attrib.get(KEY_MATERIAL);
+ if (key == null)
+ {
+ throw new IllegalArgumentException("no key provided");
+ }
+
+ Arrays.fill(t_n, (byte) 0);
+
+ nonceOmac.reset();
+ nonceOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
+ nonceOmac.update(t_n, 0, t_n.length);
+ nonceOmac.update(nonce, 0, nonce.length);
+ byte[] N = nonceOmac.digest();
+ nonceOmac.reset();
+ nonceOmac.update(t_n, 0, t_n.length);
+ nonceOmac.update(nonce, 0, nonce.length);
+
+ t_n[t_n.length - 1] = 1;
+ headerOmac.reset();
+ headerOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
+ headerOmac.update(t_n, 0, t_n.length);
+
+ t_n[t_n.length - 1] = 2;
+ msgOmac.reset();
+ msgOmac.init(Collections.singletonMap(MAC_KEY_MATERIAL, key));
+ msgOmac.update(t_n, 0, t_n.length);
+
+ Integer modeSize = (Integer) attrib.get(MODE_BLOCK_SIZE);
+ if (modeSize == null)
+ {
+ modeSize = new Integer(cipherBlockSize);
+ }
+ HashMap ctrAttr = new HashMap();
+ ctrAttr.put(KEY_MATERIAL, key);
+ ctrAttr.put(IV, N);
+ ctrAttr.put(STATE, new Integer(ENCRYPTION));
+ ctrAttr.put(MODE_BLOCK_SIZE, modeSize);
+ ctr.reset();
+ ctr.init(ctrAttr);
+
+ Integer st = (Integer) attrib.get(STATE);
+ if (st != null)
+ {
+ state = st.intValue();
+ if (state != ENCRYPTION && state != DECRYPTION)
+ {
+ throw new IllegalArgumentException("invalid state");
+ }
+ }
+ else
+ {
+ state = ENCRYPTION;
+ }
+
+ Integer ts = (Integer) attrib.get(TRUNCATED_SIZE);
+ if (ts != null)
+ {
+ tagSize = ts.intValue();
+ }
+ else
+ {
+ tagSize = cipherBlockSize;
+ }
+ if (tagSize < 0 || tagSize > cipherBlockSize)
+ {
+ throw new IllegalArgumentException("tag size out of range");
+ }
+ init = true;
+ }
+
+ public int currentBlockSize()
+ {
+ return ctr.currentBlockSize();
+ }
+
+ public void encryptBlock(byte[] in, int inOff, byte[] out, int outOff)
+ {
+ if (!init)
+ {
+ throw new IllegalStateException("not initialized");
+ }
+ if (state != ENCRYPTION)
+ {
+ throw new IllegalStateException("not encrypting");
+ }
+ ctr.update(in, inOff, out, outOff);
+ msgOmac.update(out, outOff, ctr.currentBlockSize());
+ }
+
+ public void decryptBlock(byte[] in, int inOff, byte[] out, int outOff)
+ {
+ if (!init)
+ {
+ throw new IllegalStateException("not initialized");
+ }
+ if (state != DECRYPTION)
+ {
+ throw new IllegalStateException("not decrypting");
+ }
+ msgOmac.update(in, inOff, ctr.currentBlockSize());
+ ctr.update(in, inOff, out, outOff);
+ }
+
+ public void update(byte[] in, int inOff, byte[] out, int outOff)
+ {
+ switch (state)
+ {
+ case ENCRYPTION:
+ encryptBlock(in, inOff, out, outOff);
+ break;
+ case DECRYPTION:
+ decryptBlock(in, inOff, out, outOff);
+ break;
+ default:
+ throw new IllegalStateException("impossible state " + state);
+ }
+ }
+
+ public void reset()
+ {
+ nonceOmac.reset();
+ headerOmac.reset();
+ msgOmac.reset();
+ ctr.reset();
+ }
+
+ public boolean selfTest()
+ {
+ return true; // XXX
+ }
+
+ // IMac instance methods.
+ // ------------------------------------------------------------------------
+
+ public int macSize()
+ {
+ return tagSize;
+ }
+
+ public byte[] digest()
+ {
+ byte[] tag = new byte[tagSize];
+ digest(tag, 0);
+ return tag;
+ }
+
+ public void digest(byte[] out, int outOffset)
+ {
+ if (outOffset < 0 || outOffset + tagSize > out.length)
+ {
+ throw new IndexOutOfBoundsException();
+ }
+ byte[] N = nonceOmac.digest();
+ byte[] H = headerOmac.digest();
+ byte[] M = msgOmac.digest();
+ for (int i = 0; i < tagSize; i++)
+ {
+ out[outOffset + i] = (byte) (N[i] ^ H[i] ^ M[i]);
+ }
+ reset();
+ }
+
+ public void update(byte b)
+ {
+ if (!init)
+ {
+ throw new IllegalStateException("not initialized");
+ }
+ headerOmac.update(b);
+ }
+
+ public void update(byte[] buf, int off, int len)
+ {
+ if (!init)
+ {
+ throw new IllegalStateException("not initialized");
+ }
+ headerOmac.update(buf, off, len);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/ECB.java b/gnu/javax/crypto/mode/ECB.java
new file mode 100644
index 000000000..3b33a1848
--- /dev/null
+++ b/gnu/javax/crypto/mode/ECB.java
@@ -0,0 +1,137 @@
+/* ECB.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+/**
+ * <p>The implementation of the Electronic Codebook mode.</p>
+ *
+ * <p>The Electronic Codebook (ECB) mode is a confidentiality mode that is
+ * defined as follows:</p>
+ *
+ * <ul>
+ * <li>ECB Encryption: C<sub>j</sub> = CIPH<sub>K</sub>(P<sub>j</sub>) for j = 1...n</li>
+ * <li>ECB Decryption: P<sub>j</sub> = CIPH<sup>-1</sup><sub>K</sub>(C<sub>j</sub>) for j = 1...n</li>
+ * </ul>
+ *
+ * <p>In ECB encryption, the forward cipher function is applied directly, and
+ * independently, to each block of the plaintext. The resulting sequence of
+ * output blocks is the ciphertext.</p>
+ *
+ * <p>In ECB decryption, the inverse cipher function is applied directly, and
+ * independently, to each block of the ciphertext. The resulting sequence of
+ * output blocks is the plaintext.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
+ * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
+ * Morris Dworkin.</li>
+ * </ol>
+ */
+public class ECB extends BaseMode implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial package-private constructor for use by the Factory class.</p>
+ *
+ * @param underlyingCipher the underlying cipher implementation.
+ * @param cipherBlockSize the underlying cipher block size to use.
+ */
+ ECB(IBlockCipher underlyingCipher, int cipherBlockSize)
+ {
+ super(Registry.ECB_MODE, underlyingCipher, cipherBlockSize);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param that the mode to clone.
+ */
+ private ECB(ECB that)
+ {
+ this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new ECB(this);
+ }
+
+ // Implementation of abstract methods in BaseMode --------------------------
+
+ public void setup()
+ {
+ if (modeBlockSize != cipherBlockSize)
+ {
+ throw new IllegalArgumentException(IMode.MODE_BLOCK_SIZE);
+ }
+ }
+
+ public void teardown()
+ {
+ }
+
+ public void encryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ cipher.encryptBlock(in, i, out, o);
+ }
+
+ public void decryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ cipher.decryptBlock(in, i, out, o);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/IAuthenticatedMode.java b/gnu/javax/crypto/mode/IAuthenticatedMode.java
new file mode 100644
index 000000000..d89c0016d
--- /dev/null
+++ b/gnu/javax/crypto/mode/IAuthenticatedMode.java
@@ -0,0 +1,60 @@
+/* IAuthenticatedMode.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.javax.crypto.mac.IMac;
+
+/**
+ * The interface for encryption modes that also produce a message authentication
+ * tag.
+ *
+ * <p>This interface is merely the conjuction of the {@link IMode} and
+ * {@link IMac} interfaces. Encryption and decryption is done via the
+ * {@link IMode#update(byte[],int,byte[],int)} method, tag generation
+ * is done via the {@link IMac#digest()} method, and header updating
+ * (if supported by the mode) is done via the {@link
+ * IMac#update(byte[],int,int)} method.
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface IAuthenticatedMode extends IMode, IMac
+{
+
+ // Trivial conjunction of IMode and IMac.
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/ICM.java b/gnu/javax/crypto/mode/ICM.java
new file mode 100644
index 000000000..d37908b5d
--- /dev/null
+++ b/gnu/javax/crypto/mode/ICM.java
@@ -0,0 +1,228 @@
+/* ICM.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.math.BigInteger;
+
+/**
+ * <p>An implementation of <i>David McGrew</i> Integer Counter Mode (ICM) as an
+ * {@link IMode}.</p>
+ *
+ * <p>ICM is a way to define a pseudorandom keystream generator using a block
+ * cipher. The keystream can be used for additive encryption, key derivation,
+ * or any other application requiring pseudorandom data. In the case of this
+ * class, it is used as additive encryption, XOR-ing the keystream with the
+ * input text --for both encryption and decryption.</p>
+ *
+ * <p>In ICM, the keystream is logically broken into segments. Each segment is
+ * identified with a segment index, and the segments have equal lengths. This
+ * segmentation makes ICM especially appropriate for securing packet-based
+ * protocols. ICM also allows a variety of configurations based, among other
+ * things, on two parameters: the <i>block index length</i> and the
+ * <i>segment index length</i>. A constraint on those two values exists: The sum
+ * of <i>segment index length</i> and <i>block index length</i> <b>must not</b>
+ * half the <i>block size</i> of the underlying cipher. This requirement protects
+ * the ICM keystream generator from potentially failing to be pseudorandom.</p>
+ *
+ * <p>For simplicity, this implementation, fixes these two values to the
+ * following:</p>
+ *
+ * <ul>
+ * <li>block index length: is half the underlying cipher block size, and</li>
+ * <li>segment index length: is zero.</li>
+ * </ul>
+ *
+ * <p>For a 128-bit block cipher, the above values imply a maximum keystream
+ * length of 295,147,905,179,352,825,856 octets, since in ICM, each segment must
+ * not exceed the value <code>(256 ^ <i>block index length</i>) * <i>block length</i></code>
+ * octets.</p>
+ *
+ * <p>Finally, for this implementation of the ICM, the IV placeholder will be
+ * used to pass the value of the <i>Offset</i> in the keystream segment.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-icm-00.txt">
+ * Integer Counter Mode</a>, David A. McGrew.</li>
+ * </ol>
+ */
+public class ICM extends BaseMode implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The integer value 256 as a BigInteger. */
+ private static final BigInteger TWO_FIFTY_SIX = new BigInteger("256");
+
+ /** Maximum number of blocks per segment. */
+ private BigInteger maxBlocksPerSegment;
+
+ /** A work constant. */
+ private BigInteger counterRange;
+
+ /** The initial counter for a given keystream segment. */
+ private BigInteger C0;
+
+ /** The index of the next block for a given keystream segment. */
+ private BigInteger blockNdx;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial package-private constructor for use by the Factory class.</p>
+ *
+ * @param underlyingCipher the underlying cipher implementation.
+ * @param cipherBlockSize the underlying cipher block size to use.
+ */
+ ICM(IBlockCipher underlyingCipher, int cipherBlockSize)
+ {
+ super(Registry.ICM_MODE, underlyingCipher, cipherBlockSize);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.<p>
+ *
+ * @param that the instance to clone.
+ */
+ private ICM(ICM that)
+ {
+ this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Cloneable interface implementation
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new ICM(this);
+ }
+
+ // Implementation of abstract methods in BaseMode
+ // -------------------------------------------------------------------------
+
+ public void setup()
+ {
+ if (modeBlockSize != cipherBlockSize)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ counterRange = TWO_FIFTY_SIX.pow(cipherBlockSize);
+ maxBlocksPerSegment = TWO_FIFTY_SIX.pow(cipherBlockSize / 2);
+ BigInteger r = new BigInteger(1, iv);
+ C0 = maxBlocksPerSegment.add(r).modPow(BigInteger.ONE, counterRange);
+ blockNdx = BigInteger.ZERO;
+ }
+
+ public void teardown()
+ {
+ counterRange = null;
+ maxBlocksPerSegment = null;
+ C0 = null;
+ blockNdx = null;
+ }
+
+ public void encryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ icm(in, i, out, o);
+ }
+
+ public void decryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ icm(in, i, out, o);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ private void icm(byte[] in, int inOffset, byte[] out, int outOffset)
+ {
+ if (blockNdx.compareTo(maxBlocksPerSegment) >= 0)
+ throw new RuntimeException("Maximum blocks for segment reached");
+
+ // encrypt the counter for the current blockNdx
+ // C[i] = (C[0] + i) modulo (256^BLOCK_LENGTH).
+
+ BigInteger Ci = C0.add(blockNdx).modPow(BigInteger.ONE, counterRange);
+ byte[] result = Ci.toByteArray();
+ int limit = result.length;
+ // if (limit < cipherBlockSize) {
+ // byte[] data = new byte[cipherBlockSize];
+ // System.arraycopy(result, 0, data, cipherBlockSize-limit, limit);
+ // result = data;
+ // } else if (limit > cipherBlockSize) {
+ // byte[] data = new byte[cipherBlockSize];
+ // System.arraycopy(result, limit-cipherBlockSize, data, 0, cipherBlockSize);
+ // result = data;
+ // }
+ //
+ // cipher.encryptBlock(result, 0, result, 0);
+ // blockNdx = blockNdx.add(BigInteger.ONE); // increment blockNdx
+ // for (int i = 0; i < modeBlockSize; ) { // xor result with input block
+ // out[outOffset++] = (byte)(in[inOffset++] ^ result[i++]);
+ // }
+ int ndx = 0;
+ if (limit < cipherBlockSize)
+ {
+ byte[] data = new byte[cipherBlockSize];
+ System.arraycopy(result, 0, data, cipherBlockSize - limit, limit);
+ result = data;
+ }
+ else if (limit > cipherBlockSize)
+ {
+ ndx = limit - cipherBlockSize;
+ }
+
+ cipher.encryptBlock(result, ndx, result, ndx);
+ blockNdx = blockNdx.add(BigInteger.ONE); // increment blockNdx
+ for (int i = 0; i < modeBlockSize; i++)
+ { // xor result with input block
+ out[outOffset++] = (byte) (in[inOffset++] ^ result[ndx++]);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/IMode.java b/gnu/javax/crypto/mode/IMode.java
new file mode 100644
index 000000000..4cb6ca64b
--- /dev/null
+++ b/gnu/javax/crypto/mode/IMode.java
@@ -0,0 +1,145 @@
+/* IMode.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+/**
+ * <p>The basic visible methods of any block cipher mode.</p>
+ *
+ * <p>Block ciphers encrypt plaintext in fixed size n-bit blocks. For messages
+ * larger than n bits, the simplest approach is to segment the message into
+ * n-bit blocks and process (encrypt and/or decrypt) each one separately
+ * (Electronic Codebook or ECB mode). But this approach has disadvantages in
+ * most applications. The block cipher modes of operations are one way of
+ * working around those disadvantages.</p>
+ *
+ * <p>A <i>Mode</i> always employs an underlying block cipher for processing its
+ * input. For all intents and purposes, a <i>Mode</i> appears to behave as any
+ * other block cipher with the following differences:</p>
+ *
+ * <ul>
+ * <li>Depending on the specifications of the mode, the block size may be
+ * different that that of the underlying cipher.</li>
+ *
+ * <li>While some modes of operations allow operations on block sizes that
+ * can be 1-bit long, this library will only deal with sizes that are
+ * multiple of 8 bits. This is because the <tt>byte</tt> is the smallest,
+ * easy to handle, primitive type in Java.</li>
+ *
+ * <li>Some modes need an <i>Initialisation Vector</i> (IV) to be properly
+ * initialised.</li>
+ * </ul>
+ *
+ * <p>Possible additional initialisation values for an instance of that type
+ * are:</p>
+ *
+ * <ul>
+ * <li>The block size in which to operate this mode instance. This
+ * value is <b>optional</b>, if unspecified, the underlying block cipher's
+ * configured block size shall be used.</li>
+ *
+ * <li>Whether this mode will be used for encryption or decryption. This
+ * value is <b>mandatory</b> and should be included in the initialisation
+ * parameters. If it isn't, a {@link java.lang.IllegalStateException} will
+ * be thrown if any method, other than <code>reset()</code> is invoked on the
+ * instance.</li>
+ *
+ * <li>The byte array containing the <i>initialisation vector</i>, if
+ * required by this type of mode.</li>
+ * </ul>
+ */
+public interface IMode extends IBlockCipher
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Property name of the state in which to operate this mode. The value
+ * associated to this property name is taken to be an {@link Integer} which
+ * value is either <code>ENCRYPTION</code> or <code>DECRYPTION</code>.</p>
+ */
+ String STATE = "gnu.crypto.mode.state";
+
+ /**
+ * <p>Property name of the block size in which to operate this mode. The
+ * value associated with this property name is taken to be an {@link Integer}.
+ * If it is not specified, the value of the block size of the underlying
+ * block cipher, used to construct the mode instance, shall be used.</p>
+ */
+ String MODE_BLOCK_SIZE = "gnu.crypto.mode.block.size";
+
+ /**
+ * <p>Property name of the initialisation vector to use, if required, with
+ * this instance. The value associated with this property name is taken to
+ * be a byte array. If the concrete instance needs such a parameter, and it
+ * has not been specified as part of the initialissation parameters, an
+ * all-zero byte array of the appropriate size shall be used.</p>
+ */
+ String IV = "gnu.crypto.mode.iv";
+
+ /**
+ * <p>Constant indicating the instance is being used for <i>encryption</i>.</p>
+ */
+ int ENCRYPTION = 1;
+
+ /**
+ * <p>Constant indicating the instance is being used for <i>decryption</i>.</p>
+ */
+ int DECRYPTION = 2;
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A convenience method. Effectively invokes the <code>encryptBlock()</code>
+ * or <code>decryptBlock()</code> method depending on the operational state
+ * of the instance.</p>
+ *
+ * @param in the plaintext.
+ * @param inOffset index of <code>in</code> from which to start considering
+ * data.
+ * @param out the ciphertext.
+ * @param outOffset index of <code>out</code> from which to store result.
+ * @exception IllegalStateException if the instance is not initialised.
+ */
+ void update(byte[] in, int inOffset, byte[] out, int outOffset)
+ throws IllegalStateException;
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/ModeFactory.java b/gnu/javax/crypto/mode/ModeFactory.java
new file mode 100644
index 000000000..0e949ed9e
--- /dev/null
+++ b/gnu/javax/crypto/mode/ModeFactory.java
@@ -0,0 +1,192 @@
+/* ModeFactory.java --
+ Copyright (C) 2001, 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.java.security.Registry;
+
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <p>A <i>Factory</i> to instantiate block cipher modes of operations.</p>
+ */
+public class ModeFactory implements Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private ModeFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a block cipher mode of operations given its name
+ * and characteristics of the underlying block cipher.</p>
+ *
+ * @param mode the case-insensitive name of the mode of operations.
+ * @param cipher the case-insensitive name of the block cipher.
+ * @param cipherBlockSize the block size, in bytes, of the underlying cipher.
+ * @return an instance of the block cipher algorithm, operating in a given
+ * mode of operations, or <code>null</code> if none found.
+ * @exception InternalError if either the mode or the underlying block cipher
+ * implementation does not pass its self-test.
+ */
+ public static IMode getInstance(String mode, String cipher,
+ int cipherBlockSize)
+ {
+ if (mode == null || cipher == null)
+ {
+ return null;
+ }
+
+ mode = mode.trim();
+ cipher = cipher.trim();
+
+ IBlockCipher cipherImpl = CipherFactory.getInstance(cipher);
+ if (cipherImpl == null)
+ {
+ return null;
+ }
+
+ return getInstance(mode, cipherImpl, cipherBlockSize);
+ }
+
+ public static IMode getInstance(String mode, IBlockCipher cipher,
+ int cipherBlockSize)
+ {
+ // ensure that cipherBlockSize is valid for the chosen underlying cipher
+ boolean ok = false;
+ for (Iterator it = cipher.blockSizes(); it.hasNext();)
+ {
+ ok = (cipherBlockSize == ((Integer) it.next()).intValue());
+ if (ok)
+ {
+ break;
+ }
+ }
+
+ if (!ok)
+ {
+ throw new IllegalArgumentException("cipherBlockSize");
+ }
+
+ IMode result = null;
+ if (mode.equalsIgnoreCase(ECB_MODE))
+ {
+ result = new ECB(cipher, cipherBlockSize);
+ }
+ else if (mode.equalsIgnoreCase(CTR_MODE))
+ {
+ result = new CTR(cipher, cipherBlockSize);
+ }
+ else if (mode.equalsIgnoreCase(ICM_MODE))
+ {
+ result = new ICM(cipher, cipherBlockSize);
+ }
+ else if (mode.equalsIgnoreCase(OFB_MODE))
+ {
+ result = new OFB(cipher, cipherBlockSize);
+ }
+ else if (mode.equalsIgnoreCase(CBC_MODE))
+ {
+ result = new CBC(cipher, cipherBlockSize);
+ }
+ else if (mode.equalsIgnoreCase(CFB_MODE))
+ {
+ result = new CFB(cipher, cipherBlockSize);
+ }
+ else if (mode.equalsIgnoreCase(EAX_MODE))
+ {
+ result = new EAX(cipher, cipherBlockSize);
+ }
+
+ if (result != null && !result.selfTest())
+ {
+ throw new InternalError(result.name());
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link java.util.Set} of names of mode supported by this
+ * <i>Factory</i>.</p>
+ *
+ * @return a {@link java.util.Set} of mode names (Strings).
+ */
+ public static final Set getNames()
+ {
+ synchronized (ModeFactory.class)
+ {
+ if (names == null)
+ {
+ HashSet hs = new HashSet();
+ hs.add(ECB_MODE);
+ hs.add(CTR_MODE);
+ hs.add(ICM_MODE);
+ hs.add(OFB_MODE);
+ hs.add(CBC_MODE);
+ hs.add(CFB_MODE);
+ hs.add(EAX_MODE);
+
+ names = Collections.unmodifiableSet(hs);
+ }
+ }
+ return names;
+ }
+
+ private static Set names;
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/mode/OFB.java b/gnu/javax/crypto/mode/OFB.java
new file mode 100644
index 000000000..68065d10b
--- /dev/null
+++ b/gnu/javax/crypto/mode/OFB.java
@@ -0,0 +1,194 @@
+/* OFB.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.mode;
+
+import gnu.java.security.Registry;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+/**
+ * <p>The Output Feedback (OFB) mode is a confidentiality mode that requires a
+ * unique <code>IV</code> for every message that is ever encrypted under the
+ * given key. The OFB mode is defined as follows:</p>
+ *
+ * <ul>
+ * <li>OFB Encryption:
+ * <ul>
+ * <li>I<sub>1</sub> = IV;</li>
+ * <li>I<sub>j</sub> = O<sub>j -1</sub> for j = 2...n;</li>
+ * <li>O<sub>j</sub> = CIPH<sub>K</sub>(I<sub>j</sub>) for j = 1, 2...n;</li>
+ * <li>C<sub>j</sub> = P<sub>j</sub> XOR O<sub>j</sub> for j = 1, 2...n.</li>
+ * </ul></li>
+ * <li>OFB Decryption:
+ * <ul>
+ * <li>I<sub>1</sub> = IV;</li>
+ * <li>I<sub>j</sub> = O<sub>j -1</sub> for j = 2...n;</li>
+ * <li>O<sub>j</sub> = CIPH<sub>K</sub>(I<sub>j</sub>) for j = 1, 2...n;</li>
+ * <li>P<sub>j</sub> = C<sub>j</sub> XOR O<sub>j</sub> for j = 1, 2...n.</li>
+ * </ul></li>
+ * </ul>
+ *
+ * <p>In OFB encryption, the <code>IV</code> is transformed by the forward
+ * cipher function to produce the first output block. The first output block is
+ * exclusive-ORed with the first plaintext block to produce the first ciphertext
+ * block. The first output block is then transformed by the forward cipher
+ * function to produce the second output block. The second output block is
+ * exclusive-ORed with the second plaintext block to produce the second
+ * ciphertext block, and the second output block is transformed by the forward
+ * cipher function to produce the third output block. Thus, the successive
+ * output blocks are produced from enciphering the previous output blocks, and
+ * the output blocks are exclusive-ORed with the corresponding plaintext blocks
+ * to produce the ciphertext blocks.</p>
+ *
+ * <p>In OFB decryption, the <code>IV</code> is transformed by the forward cipher
+ * function to produce the first output block. The first output block is
+ * exclusive-ORed with the first ciphertext block to recover the first plaintext
+ * block. The first output block is then transformed by the forward cipher
+ * function to produce the second output block. The second output block is
+ * exclusive-ORed with the second ciphertext block to produce the second
+ * plaintext block, and the second output block is also transformed by the
+ * forward cipher function to produce the third output block. Thus, the
+ * successive output blocks are produced from enciphering the previous output
+ * blocks, and the output blocks are exclusive-ORed with the corresponding
+ * ciphertext blocks to recover the plaintext blocks.</p>
+ *
+ * <p>In both OFB encryption and OFB decryption, each forward cipher function
+ * (except the first) depends on the results of the previous forward cipher
+ * function; therefore, multiple forward cipher functions cannot be performed
+ * in parallel. However, if the <code>IV</code> is known, the output blocks can
+ * be generated prior to the availability of the plaintext or ciphertext data.</p>
+ *
+ * <p>The OFB mode requires a unique <code>IV</code> for every message that is
+ * ever encrypted under the given key. If, contrary to this requirement, the
+ * same <code>IV</code> is used for the encryption of more than one message,
+ * then the confidentiality of those messages may be compromised. In particular,
+ * if a plaintext block of any of these messages is known, say, the j<sup>th</sup>
+ * plaintext block, then the j<sup>th</sup> output of the forward cipher
+ * function can be determined easily from the j<sup>th</sup> ciphertext block of
+ * the message. This information allows the j<sup>th</sup> plaintext block of
+ * any other message that is encrypted using the same <code>IV</code> to be
+ * easily recovered from the jth ciphertext block of that message.</p>
+ *
+ * <p>Confidentiality may similarly be compromised if any of the input blocks to
+ * the forward cipher function for the encryption of a message is used as the
+ * <code>IV</code> for the encryption of another message under the given key.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
+ * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
+ * Morris Dworkin.</li>
+ * </ol>
+ */
+public class OFB extends BaseMode implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private byte[] outputBlock;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial package-private constructor for use by the Factory class.</p>
+ *
+ * @param underlyingCipher the underlying cipher implementation.
+ * @param cipherBlockSize the underlying cipher block size to use.
+ */
+ OFB(IBlockCipher underlyingCipher, int cipherBlockSize)
+ {
+ super(Registry.OFB_MODE, underlyingCipher, cipherBlockSize);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param that the mode to clone.
+ */
+ private OFB(OFB that)
+ {
+ this((IBlockCipher) that.cipher.clone(), that.cipherBlockSize);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new OFB(this);
+ }
+
+ // Implementation of abstract methods in BaseMode --------------------------
+
+ public void setup()
+ {
+ if (modeBlockSize != cipherBlockSize)
+ {
+ throw new IllegalArgumentException(IMode.MODE_BLOCK_SIZE);
+ }
+
+ outputBlock = (byte[]) iv.clone();
+ }
+
+ public void teardown()
+ {
+ }
+
+ public void encryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ cipher.encryptBlock(outputBlock, 0, outputBlock, 0);
+ for (int j = 0; j < cipherBlockSize;)
+ {
+ out[o++] = (byte) (in[i++] ^ outputBlock[j++]);
+ }
+ }
+
+ public void decryptBlock(byte[] in, int i, byte[] out, int o)
+ {
+ this.encryptBlock(in, i, out, o);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/BasePad.java b/gnu/javax/crypto/pad/BasePad.java
new file mode 100644
index 000000000..49c5d050a
--- /dev/null
+++ b/gnu/javax/crypto/pad/BasePad.java
@@ -0,0 +1,153 @@
+/* BasePad.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+/**
+ * <p>An abstract class to facilitate implementing padding algorithms.</p>
+ */
+public abstract class BasePad implements IPad
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of the padding algorithm. */
+ protected String name;
+
+ /** The block size, in bytes, for this instance. */
+ protected int blockSize;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor for use by concrete subclasses. */
+ protected BasePad(final String name)
+ {
+ super();
+
+ this.name = name;
+ blockSize = -1;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IPad interface implementation -------------------------------------------
+
+ public String name()
+ {
+ final StringBuffer sb = new StringBuffer(name);
+ if (blockSize != -1)
+ {
+ sb.append('-').append(String.valueOf(8 * blockSize));
+ }
+ return sb.toString();
+ }
+
+ public void init(final int bs) throws IllegalStateException
+ {
+ if (blockSize != -1)
+ {
+ throw new IllegalStateException();
+ }
+ blockSize = bs;
+ setup();
+ }
+
+ public void reset()
+ {
+ blockSize = -1;
+ }
+
+ public boolean selfTest()
+ {
+ byte[] padBytes;
+ final int offset = 5;
+ final int limit = 1024;
+ final byte[] in = new byte[limit];
+ for (int bs = 2; bs < 256; bs++)
+ {
+ this.init(bs);
+ for (int i = 0; i < limit - offset - blockSize; i++)
+ {
+ padBytes = pad(in, offset, i);
+ if (((i + padBytes.length) % blockSize) != 0)
+ {
+ new RuntimeException(name()).printStackTrace(System.err);
+ return false;
+ }
+
+ System.arraycopy(padBytes, 0, in, offset + i, padBytes.length);
+ try
+ {
+ if (padBytes.length != unpad(in, offset, i + padBytes.length))
+ {
+ new RuntimeException(name()).printStackTrace(System.err);
+ return false;
+ }
+ }
+ catch (WrongPaddingException x)
+ {
+ x.printStackTrace(System.err);
+ return false;
+ }
+ }
+ this.reset();
+ }
+
+ return true;
+ }
+
+ // abstract methods to implement by subclasses -----------------------------
+
+ /**
+ * <p>If any additional checks or resource setup must be done by the
+ * subclass, then this is the hook for it. This method will be called before
+ * the {@link #init(int)} method returns.</p>
+ */
+ public abstract void setup();
+
+ public abstract byte[] pad(byte[] in, int off, int len);
+
+ public abstract int unpad(byte[] in, int off, int len)
+ throws WrongPaddingException;
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/IPad.java b/gnu/javax/crypto/pad/IPad.java
new file mode 100644
index 000000000..4b4c925e6
--- /dev/null
+++ b/gnu/javax/crypto/pad/IPad.java
@@ -0,0 +1,110 @@
+/* IPad.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+/**
+ * <p>The basic visible methods of any padding algorithm.</p>
+ *
+ * <p>Padding algorithms serve to <i>pad</i> and <i>unpad</i> byte arrays usually
+ * as the last step in an <i>encryption</i> or respectively a <i>decryption</i>
+ * operation. Their input buffers are usually those processed by instances of
+ * {@link gnu.crypto.mode.IMode} and/or {@link gnu.crypto.cipher.IBlockCipher}.</p>
+ */
+public interface IPad
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /** @return the canonical name of this instance. */
+ String name();
+
+ /**
+ * Initialises the padding scheme with a designated block size.
+ *
+ * @param bs the designated block size.
+ * @exception IllegalStateException if the instance is already initialised.
+ * @exception IllegalArgumentException if the block size value is invalid.
+ */
+ void init(int bs) throws IllegalStateException;
+
+ /**
+ * Returns the byte sequence that should be appended to the designated input.
+ *
+ * @param in the input buffer containing the bytes to pad.
+ * @param offset the starting index of meaningful data in <i>in</i>.
+ * @param length the number of meaningful bytes in <i>in</i>.
+ * @return the possibly 0-byte long sequence to be appended to the designated
+ * input.
+ */
+ byte[] pad(byte[] in, int offset, int length);
+
+ /**
+ * Returns the number of bytes to discard from a designated input buffer.
+ *
+ * @param in the input buffer containing the bytes to unpad.
+ * @param offset the starting index of meaningful data in <i>in</i>.
+ * @param length the number of meaningful bytes in <i>in</i>.
+ * @return the number of bytes to discard, to the left of index position
+ * <tt>offset + length</tt> in <i>in</i>. In other words, if the return
+ * value of a successful invocation of this method is <tt>result</tt>, then
+ * the unpadded byte sequence will be <tt>offset + length - result</tt> bytes
+ * in <i>in</i>, starting from index position <tt>offset</tt>.
+ * @exception WrongPaddingException if the data is not terminated with the
+ * expected padding bytes.
+ */
+ int unpad(byte[] in, int offset, int length) throws WrongPaddingException;
+
+ /**
+ * Resets the scheme instance for re-initialisation and use with other
+ * characteristics. This method always succeeds.
+ */
+ void reset();
+
+ /**
+ * A basic symmetric pad/unpad test.
+ *
+ * @return <tt>true</tt> if the implementation passes a basic symmetric
+ * self-test. Returns <tt>false</tt> otherwise.
+ */
+ boolean selfTest();
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/PKCS1_V1_5.java b/gnu/javax/crypto/pad/PKCS1_V1_5.java
new file mode 100644
index 000000000..5b4f7b850
--- /dev/null
+++ b/gnu/javax/crypto/pad/PKCS1_V1_5.java
@@ -0,0 +1,184 @@
+/* PKCS1_V1_5.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.EME_PKCS1_V1_5;
+import gnu.java.security.util.Util;
+
+import java.io.PrintWriter;
+import java.util.Random;
+
+/**
+ * <p>A padding algorithm implementation of the EME-PKCS1-V1.5 encoding/decoding
+ * algorithm as described in section 7.2 of RFC-3447. This is effectively an
+ * <i>Adapter</i> over an instance of {@link EME_PKCS1_V1_5} initialised with
+ * the RSA public shared modulus length (in bytes).</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @see EME_PKCS1_V1_5
+ */
+public class PKCS1_V1_5 extends BasePad
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = Registry.EME_PKCS1_V1_5_PAD;
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 9;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(final String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private EME_PKCS1_V1_5 codec;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial package-private constructor for use by the <i>Factory</i> class.
+ * </p>
+ *
+ * @see gnu.crypto.pad.PadFactory
+ */
+ PKCS1_V1_5()
+ {
+ super(Registry.EME_PKCS1_V1_5_PAD);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in BasePad
+ // -------------------------------------------------------------------------
+
+ public void setup()
+ {
+ codec = EME_PKCS1_V1_5.getInstance(blockSize);
+ }
+
+ public byte[] pad(final byte[] in, final int offset, final int length)
+ {
+ final byte[] M = new byte[length];
+ System.arraycopy(in, offset, M, 0, length);
+ final byte[] EM = codec.encode(M);
+ final byte[] result = new byte[blockSize - length];
+ System.arraycopy(EM, 0, result, 0, result.length);
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("padding: 0x" + Util.toString(result));
+ }
+ return result;
+ }
+
+ public int unpad(final byte[] in, final int offset, final int length)
+ throws WrongPaddingException
+ {
+ final byte[] EM = new byte[length];
+ System.arraycopy(in, offset, EM, 0, length);
+ final int result = length - codec.decode(EM).length;
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("padding length: " + String.valueOf(result));
+ }
+ return result;
+ }
+
+ // overloaded methods ------------------------------------------------------
+
+ public boolean selfTest()
+ {
+ final int[] mLen = new int[] { 16, 20, 32, 48, 64 };
+ final byte[] M = new byte[mLen[mLen.length - 1]];
+ new Random ().nextBytes(M);
+ final byte[] EM = new byte[1024];
+ byte[] p;
+ int bs, i, j;
+ for (bs = 256; bs < 1025; bs += 256)
+ {
+ init(bs);
+ for (i = 0; i < mLen.length; i++)
+ {
+ j = mLen[i];
+ p = pad(M, 0, j);
+ if (j + p.length != blockSize)
+ {
+ new RuntimeException(name()).printStackTrace(System.err);
+ return false;
+ }
+
+ System.arraycopy(p, 0, EM, 0, p.length);
+ System.arraycopy(M, 0, EM, p.length, j);
+ try
+ {
+ if (p.length != unpad(EM, 0, blockSize))
+ {
+ new RuntimeException(name()).printStackTrace(System.err);
+ return false;
+ }
+ }
+ catch (WrongPaddingException x)
+ {
+ x.printStackTrace(System.err);
+ return false;
+ }
+ }
+ reset();
+ }
+
+ return true;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/PKCS7.java b/gnu/javax/crypto/pad/PKCS7.java
new file mode 100644
index 000000000..5697aff27
--- /dev/null
+++ b/gnu/javax/crypto/pad/PKCS7.java
@@ -0,0 +1,149 @@
+/* PKCS7.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import java.io.PrintWriter;
+
+/**
+ * <p>The implementation of the PKCS7 padding algorithm.</p>
+ *
+ * <p>This algorithm is described for 8-byte blocks in [RFC-1423] and extended to
+ * block sizes of up to 256 bytes in [PKCS-7].</p>
+ *
+ * References:<br>
+ * <a href="http://www.ietf.org/rfc/rfc1423.txt">RFC-1423</a>: Privacy
+ * Enhancement for Internet Electronic Mail: Part III: Algorithms, Modes, and
+ * Identifiers.<br>
+ * <a href="http://www.ietf.org/">IETF</a>.
+ * <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-7/">[PKCS-7]</a>PKCS #7:
+ * Cryptographic Message Syntax Standard - An RSA Laboratories Technical Note.<br>
+ * <a href="http://www.rsasecurity.com/">RSA Security</a>.<p>
+ */
+public final class PKCS7 extends BasePad
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "pkcs7";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 9;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial package-private constructor for use by the <i>Factory</i> class.<p>
+ *
+ * @see gnu.crypto.pad.PadFactory
+ */
+ PKCS7()
+ {
+ super(Registry.PKCS7_PAD);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in BasePad
+ // -------------------------------------------------------------------------
+
+ public void setup()
+ {
+ if (blockSize < 2 || blockSize > 256)
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public byte[] pad(byte[] in, int offset, int length)
+ {
+ int padLength = blockSize;
+ if (length % blockSize != 0)
+ {
+ padLength = blockSize - length % blockSize;
+ }
+ byte[] result = new byte[padLength];
+ for (int i = 0; i < padLength;)
+ {
+ result[i++] = (byte) padLength;
+ }
+
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("padding: 0x" + Util.toString(result));
+ }
+ return result;
+ }
+
+ public int unpad(byte[] in, int offset, int length)
+ throws WrongPaddingException
+ {
+ int limit = offset + length;
+ int result = in[limit - 1] & 0xFF;
+ for (int i = 0; i < result; i++)
+ {
+ if (result != (in[--limit] & 0xFF))
+ {
+ throw new WrongPaddingException();
+ }
+ }
+
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("padding length: " + String.valueOf(result));
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/PadFactory.java b/gnu/javax/crypto/pad/PadFactory.java
new file mode 100644
index 000000000..e122719b6
--- /dev/null
+++ b/gnu/javax/crypto/pad/PadFactory.java
@@ -0,0 +1,136 @@
+/* PadFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+import gnu.java.security.Registry;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>A Factory to instantiate padding schemes.</p>
+ */
+public class PadFactory implements Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private PadFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a padding algorithm given its name.</p>
+ *
+ * @param pad the case-insensitive name of the padding algorithm.
+ * @return an instance of the padding algorithm, operating with a given
+ * block size, or <code>null</code> if none found.
+ * @throws InternalError if the implementation does not pass its self-test.
+ */
+ public static final IPad getInstance(String pad)
+ {
+ if (pad == null)
+ {
+ return null;
+ }
+
+ pad = pad.trim().toLowerCase();
+ if (pad.endsWith("padding"))
+ pad = pad.substring(0, pad.length() - "padding".length());
+ IPad result = null;
+ if (pad.equals(PKCS7_PAD))
+ {
+ result = new PKCS7();
+ }
+ else if (pad.equals(TBC_PAD))
+ {
+ result = new TBC();
+ }
+ else if (pad.equals(EME_PKCS1_V1_5_PAD))
+ {
+ result = new PKCS1_V1_5();
+ }
+ else if (pad.equals(SSL3_PAD))
+ {
+ result = new SSL3();
+ }
+ else if (pad.equals(TLS1_PAD))
+ {
+ result = new TLS1();
+ }
+
+ if (result != null && !result.selfTest())
+ {
+ throw new InternalError(result.name());
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link java.util.Set} of names of padding algorithms
+ * supported by this <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of padding algorithm names (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(PKCS7_PAD);
+ hs.add(TBC_PAD);
+ hs.add(EME_PKCS1_V1_5_PAD);
+ hs.add(SSL3_PAD);
+ hs.add(TLS1_PAD);
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/SSL3.java b/gnu/javax/crypto/pad/SSL3.java
new file mode 100644
index 000000000..25aeefa13
--- /dev/null
+++ b/gnu/javax/crypto/pad/SSL3.java
@@ -0,0 +1,98 @@
+/* SSL3.java -- SSLv3 padding scheme.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+/**
+ * The padding scheme used by the Secure Sockets Layer, version 3. This
+ * padding scheme is used in the block-ciphered struct, e.g.:
+ *
+ * <pre>
+ * block-ciphered struct {
+ * opaque content[SSLCompressed.length];
+ * opaque MAC[CipherSpec.hash_size];
+ * uint8 padding[GenericBlockCipher.padding_length];
+ * uint8 padding_length;
+ * } GenericBlockCipher;
+ * </pre>
+ *
+ * <p>Where <i>padding_length</i> is <i>cipher_block_size</i> -
+ * ((<i>SSLCompressed.length</i> + <i>CipherSpec.hash_size</i>)
+ * % <i>cipher_block_size</i>) - 1. That is, the padding is enough bytes
+ * to make the plaintext a multiple of the block size minus one, plus one
+ * additional byte for the padding length. The padding can be any arbitrary
+ * data.</p>
+ */
+public class SSL3 extends BasePad
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public SSL3()
+ {
+ super("ssl3");
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void setup()
+ {
+ if (blockSize <= 0 || blockSize > 255)
+ throw new IllegalArgumentException("invalid block size: " + blockSize);
+ }
+
+ public byte[] pad(final byte[] in, final int off, final int len)
+ {
+ int padlen = blockSize - (len % blockSize);
+ byte[] pad = new byte[padlen];
+ for (int i = 0; i < padlen; i++)
+ pad[i] = (byte) (padlen - 1);
+ return pad;
+ }
+
+ public int unpad(final byte[] in, final int off, final int len)
+ throws WrongPaddingException
+ {
+ int padlen = in[off + len - 1] & 0xFF;
+ if (padlen >= blockSize)
+ throw new WrongPaddingException();
+ return padlen + 1;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/TBC.java b/gnu/javax/crypto/pad/TBC.java
new file mode 100644
index 000000000..25c3e4286
--- /dev/null
+++ b/gnu/javax/crypto/pad/TBC.java
@@ -0,0 +1,156 @@
+/* TBC.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import java.io.PrintWriter;
+
+/**
+ * <p>The implementation of the Trailing Bit Complement (TBC) padding algorithm.</p>
+ *
+ * <p>In this mode, "...the data string is padded at the trailing end with the
+ * complement of the trailing bit of the unpadded message: if the trailing bit
+ * is <tt>1</tt>, then <tt>0</tt> bits are appended, and if the trailing bit is
+ * <tt>0</tt>, then <tt>1</tt> bits are appended. As few bits are added as are
+ * necessary to meet the formatting size requirement."</p>
+ *
+ * References:<br>
+ * <a href="http://csrc.nist.gov/encryption/modes/Recommendation/Modes01.pdf">
+ * Recommendation for Block Cipher Modes of Operation Methods and Techniques</a>,
+ * Morris Dworkin.<p>
+ */
+public final class TBC extends BasePad
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "tbc";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 9;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial package-private constructor for use by the <i>Factory</i> class.<p>
+ *
+ * @see gnu.crypto.pad.PadFactory
+ */
+ TBC()
+ {
+ super(Registry.TBC_PAD);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in BasePad
+ // -------------------------------------------------------------------------
+
+ public void setup()
+ {
+ if (blockSize < 1 || blockSize > 256)
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public byte[] pad(byte[] in, int offset, int length)
+ {
+ int padLength = blockSize;
+ if (length % blockSize != 0)
+ {
+ padLength = blockSize - length % blockSize;
+ }
+ byte[] result = new byte[padLength];
+ int lastBit = in[offset + length - 1] & 0x01;
+ if (lastBit == 0)
+ {
+ for (int i = 0; i < padLength;)
+ {
+ result[i++] = 0x01;
+ }
+ } // else it's already set to zeroes by virtue of initialisation
+
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("padding: 0x" + Util.toString(result));
+ }
+ return result;
+ }
+
+ public int unpad(byte[] in, int offset, int length)
+ throws WrongPaddingException
+ {
+ int limit = offset + length - 1;
+ int lastBit = in[limit] & 0xFF;
+ int result = 0;
+ while (lastBit == (in[limit] & 0xFF))
+ {
+ result++;
+ limit--;
+ }
+
+ if (result > length)
+ {
+ throw new WrongPaddingException();
+ }
+
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("padding length: " + String.valueOf(result));
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/TLS1.java b/gnu/javax/crypto/pad/TLS1.java
new file mode 100644
index 000000000..00a538f88
--- /dev/null
+++ b/gnu/javax/crypto/pad/TLS1.java
@@ -0,0 +1,105 @@
+/* TLS1.java -- TLSv1 padding scheme.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+import gnu.java.security.util.Util;
+
+/**
+ * The padding scheme used by the Transport Layer Security protocol,
+ * version 1. This padding scheme is used in the block-ciphered struct,
+ * e.g.:
+ *
+ * <pre>
+ * block-ciphered struct {
+ * opaque content[TLSCompressed.length];
+ * opaque MAC[CipherSpec.hash_size];
+ * uint8 padding[GenericBlockCipher.padding_length];
+ * uint8 padding_length;
+ * } GenericBlockCipher;
+ * </pre>
+ *
+ * <p>Where <i>padding_length</i> is any multiple of <i>cipher_block_size</i> -
+ * ((<i>SSLCompressed.length</i> + <i>CipherSpec.hash_size</i>)
+ * % <i>cipher_block_size</i>) - 1 that is less than 255. Every byte of the
+ * padding must be equal to <i>padding_length</i>. That is, the end of the
+ * plaintext is <i>n</i> + 1 copies of the unsigned byte <i>n</i>.</p>
+ */
+public class TLS1 extends BasePad
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public TLS1()
+ {
+ super("tls1");
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void setup()
+ {
+ if (blockSize <= 0 || blockSize > 255)
+ throw new IllegalArgumentException("invalid block size: " + blockSize);
+ }
+
+ public byte[] pad(final byte[] in, final int off, final int len)
+ {
+ int padlen = blockSize - (len % blockSize);
+ byte[] pad = new byte[padlen];
+ for (int i = 0; i < padlen; i++)
+ {
+ pad[i] = (byte) (padlen - 1);
+ }
+ return pad;
+ }
+
+ public int unpad(final byte[] in, final int off, final int len)
+ throws WrongPaddingException
+ {
+ int padlen = in[off + len - 1] & 0xFF;
+ for (int i = off + (len - padlen - 1); i < off + len - 1; i++)
+ {
+ if ((in[i] & 0xFF) != padlen)
+ throw new WrongPaddingException();
+ }
+ return padlen + 1;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/pad/WrongPaddingException.java b/gnu/javax/crypto/pad/WrongPaddingException.java
new file mode 100644
index 000000000..cc74dfb26
--- /dev/null
+++ b/gnu/javax/crypto/pad/WrongPaddingException.java
@@ -0,0 +1,63 @@
+/* WrongPaddingException.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.pad;
+
+/**
+ * <p>A checked exception that indicates that a padding algorithm did not find the
+ * expected padding bytes when unpadding some data.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class WrongPaddingException extends Exception
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instant methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/prng/ARCFour.java b/gnu/javax/crypto/prng/ARCFour.java
new file mode 100644
index 000000000..22316ec8b
--- /dev/null
+++ b/gnu/javax/crypto/prng/ARCFour.java
@@ -0,0 +1,161 @@
+/* ARCFour.java --
+ Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.prng;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.BasePRNG;
+import gnu.java.security.prng.LimitReachedException;
+
+import java.util.Map;
+
+/**
+ * RC4 is a stream cipher developed by Ron Rivest. Until 1994 RC4 was a
+ * trade secret of RSA Data Security, Inc., when it was released
+ * anonymously to a mailing list. This version is a descendent of that
+ * code, and since there is no proof that the leaked version was in fact
+ * RC4 and because "RC4" is a trademark, it is called "ARCFOUR", short for
+ * "Allegedly RC4".
+ *
+ * <p>This class only implements the <i>keystream</i> of ARCFOUR. To use
+ * this as a stream cipher, one would say:</p>
+ *
+ * <pre> out = in ^ arcfour.nextByte();</pre>
+ *
+ * <p>This operation works for encryption and decryption.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>Schneier, Bruce: <i>Applied Cryptography: Protocols, Algorithms,
+ * and Source Code in C, Second Edition.</i> (1996 John Wiley and Sons),
+ * pp. 397--398. ISBN 0-471-11709-9</li>
+ * <li>K. Kaukonen and R. Thayer, "A Stream Cipher Encryption Algorithm
+ * 'Arcfour'", Internet Draft (expired), <a
+ * href="http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt">draft-kaukonen-cipher-arcfour-03.txt</a></li>
+ * </ol>
+ */
+public class ARCFour extends BasePRNG implements Cloneable
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ /** The attributes property name for the key bytes. */
+ public static final String ARCFOUR_KEY_MATERIAL = "gnu.crypto.prng.arcfour.key-material";
+
+ /** The size of the internal S-box. */
+ public static final int ARCFOUR_SBOX_SIZE = 256;
+
+ /** The S-box. */
+ private byte[] s;
+
+ private byte m, n;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ /** Default 0-arguments constructor. */
+ public ARCFour()
+ {
+ super(Registry.ARCFOUR_PRNG);
+ }
+
+ // Methods implementing BasePRNG.
+ // -----------------------------------------------------------------------
+
+ public void setup(Map attributes)
+ {
+ byte[] kb = (byte[]) attributes.get(ARCFOUR_KEY_MATERIAL);
+
+ if (kb == null)
+ {
+ throw new IllegalArgumentException("ARCFOUR needs a key");
+ }
+
+ s = new byte[ARCFOUR_SBOX_SIZE];
+ m = n = 0;
+ byte[] k = new byte[ARCFOUR_SBOX_SIZE];
+
+ for (int i = 0; i < ARCFOUR_SBOX_SIZE; i++)
+ {
+ s[i] = (byte) i;
+ }
+
+ if (kb.length > 0)
+ {
+ for (int i = 0, j = 0; i < ARCFOUR_SBOX_SIZE; i++)
+ {
+ k[i] = kb[j++];
+ if (j >= kb.length)
+ j = 0;
+ }
+ }
+
+ for (int i = 0, j = 0; i < ARCFOUR_SBOX_SIZE; i++)
+ {
+ j = j + s[i] + k[i];
+ byte temp = s[i];
+ s[i] = s[j & 0xff];
+ s[j & 0xff] = temp;
+ }
+
+ buffer = new byte[ARCFOUR_SBOX_SIZE];
+ try
+ {
+ fillBlock();
+ }
+ catch (LimitReachedException wontHappen)
+ {
+ }
+ }
+
+ public void fillBlock() throws LimitReachedException
+ {
+ for (int i = 0; i < buffer.length; i++)
+ {
+ m++;
+ n = (byte) (n + s[m & 0xff]);
+ byte temp = s[m & 0xff];
+ s[m & 0xff] = s[n & 0xff];
+ s[n & 0xff] = temp;
+ temp = (byte) (s[m & 0xff] + s[n & 0xff]);
+ buffer[i] = s[temp & 0xff];
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/prng/CSPRNG.java b/gnu/javax/crypto/prng/CSPRNG.java
new file mode 100644
index 000000000..197009232
--- /dev/null
+++ b/gnu/javax/crypto/prng/CSPRNG.java
@@ -0,0 +1,1268 @@
+/* CSPRNG.java -- continuously-seeded pseudo-random number generator.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.prng;
+
+import gnu.java.security.Properties;
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.prng.BasePRNG;
+import gnu.java.security.prng.EntropySource;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.SimpleList;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import java.security.AccessController;
+import java.security.InvalidKeyException;
+import java.security.PrivilegedAction;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * <p>An entropy pool-based pseudo-random number generator based on the PRNG
+ * in Peter Gutmann's cryptlib (<a
+ * href="http://www.cs.auckland.ac.nz/~pgut001/cryptlib/">http://www.cs.auckland.ac.nz/~pgut001/cryptlib/</a>).</p>
+ *
+ * <p>The basic properties of this generator are:</p>
+ *
+ * <ol>
+ * <li>The internal state cannot be determined by knowledge of the input.</li>
+ * <li>It is resistant to bias introduced by specific inputs.</li>
+ * <li>The output does not reveal the state of the generator.</li>
+ * </ol>
+ */
+public class CSPRNG extends BasePRNG
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+
+ private static void debug(String msg)
+ {
+ System.err.print(">>> CSPRNG: ");
+ System.err.println(msg);
+ }
+
+ /**
+ * Property name for the list of files to read for random values. The
+ * mapped value is a list with the following values:
+ *
+ * <ol>
+ * <li>A {@link Double}, indicating the suggested <i>quality</i> of this
+ * source. This value must be between 0 and 100.</li>
+ * <li>An {@link Integer}, indicating the number of bytes to skip in the file
+ * before reading bytes. This can be any nonnegative value.</li>
+ * <li>An {@link Integer}, indicating the number of bytes to read.</li>
+ * <li>A {@link String}, indicating the path to the file.</li>
+ * </ol>
+ *
+ * @see gnu.crypto.util.SimpleList
+ */
+ public static final String FILE_SOURCES = "gnu.crypto.prng.pool.files";
+
+ /**
+ * Property name for the list of URLs to poll for random values. The
+ * mapped value is a list formatted similarly as in {@link #FILE_SOURCES},
+ * but the fourth member is a {@link URL}.
+ */
+ public static final String URL_SOURCES = "gnu.crypto.prng.pool.urls";
+
+ /**
+ * Property name for the list of programs to execute, and use the output
+ * as new random bytes. The mapped property is formatted similarly an in
+ * {@link #FILE_SOURCES} and {@link #URL_SOURCES}, except the fourth
+ * member is a {@link String} of the program to execute.
+ */
+ public static final String PROGRAM_SOURCES = "gnu.crypto.prng.pool.programs";
+
+ /**
+ * Property name for a list of other sources of entropy. The mapped
+ * value must be a list of {@link EntropySource} objects.
+ */
+ public static final String OTHER_SOURCES = "gnu.crypto.prng.pool.other";
+
+ /**
+ * Property name for whether or not to wait for the slow poll to
+ * complete, passed as a {@link Boolean}. The default value is true.
+ */
+ public static final String BLOCKING = "gnu.crypto.prng.pool.blocking";
+
+ private static final String FILES = "gnu.crypto.csprng.file.";
+
+ private static final String URLS = "gnu.crypto.csprng.url.";
+
+ private static final String PROGS = "gnu.crypto.csprng.program.";
+
+ private static final String OTHER = "gnu.crypto.csprng.other.";
+
+ private static final String BLOCK = "gnu.crypto.csprng.blocking";
+
+ private static final int POOL_SIZE = 256;
+
+ private static final int ALLOC_SIZE = 260;
+
+ private static final int OUTPUT_SIZE = POOL_SIZE / 2;
+
+ private static final int X917_POOL_SIZE = 16;
+
+ private static final String HASH_FUNCTION = Registry.SHA160_HASH;
+
+ private static final String CIPHER = Registry.AES_CIPHER;
+
+ private static final int MIX_COUNT = 10;
+
+ private static final int X917_LIFETIME = 8192;
+
+ // FIXME this should be configurable.
+ private static final int SPINNER_COUNT = 8;
+
+ /**
+ * The spinner group singleton. We use this to add a small amount of
+ * randomness (in addition to the current time and the amount of
+ * free memory) based on the randomness (if any) present due to
+ * system load and thread scheduling.
+ */
+ private static final Spinner[] SPINNERS = new Spinner[SPINNER_COUNT];
+
+ private static final Thread[] SPINNER_THREADS = new Thread[SPINNER_COUNT];
+ static
+ {
+ for (int i = 0; i < SPINNER_COUNT; i++)
+ {
+ SPINNER_THREADS[i] = new Thread(SPINNERS[i] = new Spinner(),
+ "spinner-" + i);
+ SPINNER_THREADS[i].setDaemon(true);
+ SPINNER_THREADS[i].setPriority(Thread.MIN_PRIORITY);
+ SPINNER_THREADS[i].start();
+ }
+ }
+
+ /**
+ * The message digest (SHA-1) used in the mixing function.
+ */
+ private final IMessageDigest hash;
+
+ /**
+ * The cipher (AES) used in the output masking function.
+ */
+ private final IBlockCipher cipher;
+
+ /**
+ * The number of times the pool has been mixed.
+ */
+ private int mixCount;
+
+ /**
+ * The entropy pool.
+ */
+ private final byte[] pool;
+
+ /**
+ * The quality of the random pool (percentage).
+ */
+ private double quality;
+
+ /**
+ * The index of the next byte in the entropy pool.
+ */
+ private int index;
+
+ /**
+ * The pool for the X9.17-like generator.
+ */
+ private byte[] x917pool;
+
+ /**
+ * The number of iterations of the X9.17-like generators.
+ */
+ private int x917count;
+
+ /**
+ * Whether or not the X9.17-like generator is initialized.
+ */
+ private boolean x917init;
+
+ /**
+ * The list of file soures.
+ */
+ private final List files;
+
+ /**
+ * The list of URL sources.
+ */
+ private final List urls;
+
+ /**
+ * The list of program sources.
+ */
+ private final List progs;
+
+ /**
+ * The list of other sources.
+ */
+ private final List other;
+
+ /**
+ * Whether or not to wait for the slow poll to complete.
+ */
+ private boolean blocking;
+
+ /**
+ * The thread that polls for random data.
+ */
+ private Poller poller;
+
+ private Thread pollerThread;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public CSPRNG()
+ {
+ super("CSPRNG");
+ pool = new byte[ALLOC_SIZE];
+ x917pool = new byte[X917_POOL_SIZE];
+ x917count = 0;
+ x917init = false;
+ quality = 0.0;
+ hash = HashFactory.getInstance(HASH_FUNCTION);
+ cipher = CipherFactory.getInstance(CIPHER);
+ buffer = new byte[OUTPUT_SIZE];
+ ndx = 0;
+ initialised = false;
+ files = new LinkedList();
+ urls = new LinkedList();
+ progs = new LinkedList();
+ other = new LinkedList();
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Create and initialize a CSPRNG instance with the "system" parameters;
+ * the files, URLs, programs, and {@link EntropySource} sources used by
+ * the instance are derived from properties set in the system {@link
+ * Properties}.</p>
+ *
+ * <p>All properties are of the from <i>name</i>.</i>N</i>, where <i>name</i>
+ * is the name of the source, and <i>N</i> is an integer (staring at 1) that
+ * indicates the preference number for that source.</p>
+ *
+ * <p>The following vales for <i>name</i> are used here:</p>
+ *
+ * <dl>
+ * <dt>gnu.crypto.csprng.file</dt>
+ * <dd><p>These properties are file sources, passed as the {@link #FILE_SOURCES}
+ * parameter of the instance. The property value is a 4-tuple formatted as:</p>
+ *
+ * <blockquote><i>quality</i> ; <i>offset</i> ; <i>count</i> ; <i>path</i></blockquote>
+ *
+ * <p>The parameters are mapped to the parameters defined for {@link
+ * #FILE_SOURCES}. Leading or trailing spaces on any item are trimmed
+ * off.</p></dd>
+ *
+ * <dt>gnu.crypto.csprng.url</dt>
+ * <dd><p>These properties are URL sources, passed as the {@link #URL_SOURCES}
+ * parameter of the instance. The property is formatted the same way as file
+ * sources, but the <i>path</i> argument must be a valid URL.</p></dd>
+ *
+ * <dt>gnu.crypto.csprng.program</dt>
+ * <dd><p>These properties are program sources, passed as the {@link
+ * #PROGRAM_SOURCES} parameter of the instance. This property is formatted
+ * the same way as file and URL sources, but the last argument is a program
+ * and its arguments.</p></dd>
+ *
+ * <dt>gnu.crypto.cspring.other</dt>
+ * <dd><p>These properties are other sources, passed as the {@link OTHER_SOURCES}
+ * parameter of the instance. The property value must be the full name
+ * of a class that implements the {@link EntropySource} interface and has a
+ * public no-argument constructor.</p></dd>
+ * </dl>
+ *
+ * <p>Finally, a boolean property "gnu.crypto.csprng.blocking" can be set to
+ * the desired value of {@link #BLOCKING}.</p>
+ *
+ * <p>An example of valid properties would be:</p>
+ *
+ * <pre>
+ * gnu.crypto.csprng.blocking=true
+ *
+ * gnu.crypto.csprng.file.1=75.0;0;256;/dev/random
+ * gnu.crypto.csprng.file.2=10.0;0;100;/home/user/file
+ *
+ * gnu.crypto.csprng.url.1=5.0;0;256;http://www.random.org/cgi-bin/randbyte?nbytes=256
+ * gnu.crypto.csprng.url.2=0;256;256;http://slashdot.org/
+ *
+ * gnu.crypto.csprng.program.1=0.5;0;10;last -n 50
+ * gnu.crypto.csprng.program.2=0.5;0;10;tcpdump -c 5
+ *
+ * gnu.crypto.csprng.other.1=foo.bar.MyEntropySource
+ * gnu.crypto.csprng.other.2=com.company.OtherEntropySource
+ * </pre>
+ */
+ public static IRandom getSystemInstance() throws ClassNotFoundException,
+ MalformedURLException, NumberFormatException
+ {
+ CSPRNG instance = new CSPRNG();
+ HashMap attrib = new HashMap();
+ attrib.put(BLOCKING, new Boolean(getProperty(BLOCK)));
+ String s = null;
+
+ // Get each file source "gnu.crypto.csprng.file.N".
+ List l = new LinkedList();
+ for (int i = 0; (s = getProperty(FILES + i)) != null; i++)
+ {
+ try
+ {
+ l.add(parseString(s.trim()));
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ }
+ attrib.put(FILE_SOURCES, l);
+
+ l = new LinkedList();
+ for (int i = 0; (s = getProperty(URLS + i)) != null; i++)
+ {
+ try
+ {
+ l.add(parseURL(s.trim()));
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ catch (MalformedURLException mue)
+ {
+ }
+ }
+ attrib.put(URL_SOURCES, l);
+
+ l = new LinkedList();
+ for (int i = 0; (s = getProperty(PROGS + i)) != null; i++)
+ {
+ try
+ {
+ l.add(parseString(s.trim()));
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ }
+ attrib.put(PROGRAM_SOURCES, l);
+
+ l = new LinkedList();
+ for (int i = 0; (s = getProperty(OTHER + i)) != null; i++)
+ {
+ try
+ {
+ Class c = Class.forName(s.trim());
+ l.add(c.newInstance());
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ }
+ catch (InstantiationException ie)
+ {
+ }
+ catch (IllegalAccessException iae)
+ {
+ }
+ }
+ attrib.put(OTHER_SOURCES, l);
+
+ instance.init(attrib);
+ return instance;
+ }
+
+ private static String getProperty(final String name)
+ {
+ return (String) AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return Properties.getProperty(name);
+ }
+ });
+ }
+
+ private static List parseString(String s) throws NumberFormatException
+ {
+ StringTokenizer tok = new StringTokenizer(s, ";");
+ if (tok.countTokens() != 4)
+ {
+ throw new IllegalArgumentException("malformed property");
+ }
+ Double quality = new Double(tok.nextToken());
+ Integer offset = new Integer(tok.nextToken());
+ Integer length = new Integer(tok.nextToken());
+ String str = tok.nextToken();
+ return new SimpleList(quality, offset, length, str);
+ }
+
+ private static List parseURL(String s) throws MalformedURLException,
+ NumberFormatException
+ {
+ StringTokenizer tok = new StringTokenizer(s, ";");
+ if (tok.countTokens() != 4)
+ {
+ throw new IllegalArgumentException("malformed property");
+ }
+ Double quality = new Double(tok.nextToken());
+ Integer offset = new Integer(tok.nextToken());
+ Integer length = new Integer(tok.nextToken());
+ URL url = new URL(tok.nextToken());
+ return new SimpleList(quality, offset, length, url);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new CSPRNG();
+ }
+
+ public void setup(Map attrib)
+ {
+ List list = null;
+
+ if (DEBUG)
+ {
+ debug(String.valueOf(attrib));
+ }
+ try
+ {
+ list = (List) attrib.get(FILE_SOURCES);
+ if (DEBUG)
+ {
+ debug(String.valueOf(list));
+ }
+ if (list != null)
+ {
+ files.clear();
+ for (Iterator it = list.iterator(); it.hasNext();)
+ {
+ List l = (List) it.next();
+ if (DEBUG)
+ {
+ debug("l=" + l);
+ }
+ if (l.size() != 4)
+ {
+ if (DEBUG)
+ {
+ debug("file list too small: " + l.size());
+ }
+ throw new IllegalArgumentException("invalid file list");
+ }
+ Double quality = (Double) l.get(0);
+ Integer offset = (Integer) l.get(1);
+ Integer length = (Integer) l.get(2);
+ String source = (String) l.get(3);
+ files.add(new SimpleList(quality, offset, length, source));
+ }
+ }
+ }
+ catch (ClassCastException cce)
+ {
+ if (DEBUG)
+ {
+ debug("bad file list: " + cce.getMessage());
+ cce.printStackTrace();
+ }
+ throw new IllegalArgumentException("invalid file list");
+ }
+
+ try
+ {
+ list = (List) attrib.get(URL_SOURCES);
+ if (DEBUG)
+ {
+ debug(String.valueOf(list));
+ }
+ if (list != null)
+ {
+ urls.clear();
+ for (Iterator it = list.iterator(); it.hasNext();)
+ {
+ List l = (List) it.next();
+ if (DEBUG)
+ {
+ debug("l=" + l);
+ }
+ if (l.size() != 4)
+ {
+ if (DEBUG)
+ {
+ debug("URL list too small: " + l.size());
+ }
+ throw new IllegalArgumentException("invalid URL list");
+ }
+ Double quality = (Double) l.get(0);
+ Integer offset = (Integer) l.get(1);
+ Integer length = (Integer) l.get(2);
+ URL source = (URL) l.get(3);
+ urls.add(new SimpleList(quality, offset, length, source));
+ }
+ }
+ }
+ catch (ClassCastException cce)
+ {
+ if (DEBUG)
+ {
+ debug("bad URL list: " + cce.getMessage());
+ cce.printStackTrace();
+ }
+ throw new IllegalArgumentException("invalid URL list");
+ }
+
+ try
+ {
+ list = (List) attrib.get(PROGRAM_SOURCES);
+ if (DEBUG)
+ {
+ debug(String.valueOf(list));
+ }
+ if (list != null)
+ {
+ progs.clear();
+ for (Iterator it = list.iterator(); it.hasNext();)
+ {
+ List l = (List) it.next();
+ if (DEBUG)
+ {
+ debug("l=" + l);
+ }
+ if (l.size() != 4)
+ {
+ if (DEBUG)
+ {
+ debug("program list too small: " + l.size());
+ }
+ throw new IllegalArgumentException("invalid program list");
+ }
+ Double quality = (Double) l.get(0);
+ Integer offset = (Integer) l.get(1);
+ Integer length = (Integer) l.get(2);
+ String source = (String) l.get(3);
+ progs.add(new SimpleList(quality, offset, length, source));
+ }
+ }
+ }
+ catch (ClassCastException cce)
+ {
+ if (DEBUG)
+ {
+ debug("bad program list: " + cce.getMessage());
+ cce.printStackTrace();
+ }
+ throw new IllegalArgumentException("invalid program list");
+ }
+
+ try
+ {
+ list = (List) attrib.get(OTHER_SOURCES);
+ if (DEBUG)
+ {
+ debug(String.valueOf(list));
+ }
+ if (list != null)
+ {
+ other.clear();
+ for (Iterator it = list.iterator(); it.hasNext();)
+ {
+ EntropySource src = (EntropySource) it.next();
+ if (DEBUG)
+ {
+ debug("src=" + src);
+ }
+ if (src == null)
+ {
+ throw new NullPointerException("null source in source list");
+ }
+ other.add(src);
+ }
+ }
+ }
+ catch (ClassCastException cce)
+ {
+ throw new IllegalArgumentException("invalid source list");
+ }
+
+ try
+ {
+ Boolean block = (Boolean) attrib.get(BLOCKING);
+ if (block != null)
+ {
+ blocking = block.booleanValue();
+ }
+ else
+ {
+ blocking = true;
+ }
+ }
+ catch (ClassCastException cce)
+ {
+ throw new IllegalArgumentException("invalid blocking parameter");
+ }
+
+ poller = new Poller(files, urls, progs, other, this);
+ try
+ {
+ fillBlock();
+ }
+ catch (LimitReachedException lre)
+ {
+ throw new RuntimeException("bootstrapping CSPRNG failed");
+ }
+ }
+
+ public void fillBlock() throws LimitReachedException
+ {
+ if (DEBUG)
+ {
+ debug("fillBlock");
+ }
+ if (getQuality() < 100.0)
+ {
+ if (DEBUG)
+ {
+ debug("doing slow poll");
+ }
+ slowPoll();
+ }
+
+ do
+ {
+ fastPoll();
+ mixRandomPool();
+ }
+ while (mixCount < MIX_COUNT);
+
+ if (!x917init || x917count >= X917_LIFETIME)
+ {
+ mixRandomPool(pool);
+ Map attr = new HashMap();
+ byte[] key = new byte[32];
+ System.arraycopy(pool, 0, key, 0, 32);
+ cipher.reset();
+ attr.put(IBlockCipher.KEY_MATERIAL, key);
+ try
+ {
+ cipher.init(attr);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new Error(ike.toString());
+ }
+
+ mixRandomPool(pool);
+ generateX917(pool);
+ mixRandomPool(pool);
+ generateX917(pool);
+
+ if (x917init)
+ {
+ quality = 0.0;
+ }
+ x917init = true;
+ x917count = 0;
+ }
+
+ byte[] export = new byte[ALLOC_SIZE];
+ for (int i = 0; i < ALLOC_SIZE; i++)
+ {
+ export[i] = (byte) (pool[i] ^ 0xFF);
+ }
+
+ mixRandomPool();
+ mixRandomPool(export);
+
+ generateX917(export);
+
+ for (int i = 0; i < OUTPUT_SIZE; i++)
+ {
+ buffer[i] = (byte) (export[i] ^ export[i + OUTPUT_SIZE]);
+ }
+ Arrays.fill(export, (byte) 0);
+ }
+
+ /**
+ * Add an array of bytes into the randomness pool. Note that this method
+ * will <i>not</i> increment the pool's quality counter (this can only be
+ * done via a source provided to the setup method).
+ *
+ * @param buf The byte array.
+ * @param off The offset from whence to start reading bytes.
+ * @param len The number of bytes to add.
+ * @throws ArrayIndexOutOfBoundsException If <i>off</i> or <i>len</i> are
+ * out of the range of <i>buf</i>.
+ */
+ public synchronized void addRandomBytes(byte[] buf, int off, int len)
+ {
+ if (off < 0 || len < 0 || off + len > buf.length)
+ {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (DEBUG)
+ {
+ debug("adding random bytes:");
+ debug(Util.toString(buf, off, len));
+ }
+ final int count = off + len;
+ for (int i = off; i < count; i++)
+ {
+ pool[index++] ^= buf[i];
+ if (index == pool.length)
+ {
+ mixRandomPool();
+ index = 0;
+ }
+ }
+ }
+
+ /**
+ * Add a single random byte to the randomness pool. Note that this method
+ * will <i>not</i> increment the pool's quality counter (this can only be
+ * done via a source provided to the setup method).
+ *
+ * @param b The byte to add.
+ */
+ public synchronized void addRandomByte(byte b)
+ {
+ if (DEBUG)
+ {
+ debug("adding byte " + Integer.toHexString(b));
+ }
+ pool[index++] ^= b;
+ if (index >= pool.length)
+ {
+ mixRandomPool();
+ index = 0;
+ }
+ }
+
+ // Package methods.
+ // -------------------------------------------------------------------------
+
+ synchronized void addQuality(double quality)
+ {
+ if (DEBUG)
+ {
+ debug("adding quality " + quality);
+ }
+ if (this.quality < 100)
+ {
+ this.quality += quality;
+ }
+ if (DEBUG)
+ {
+ debug("quality now " + this.quality);
+ }
+ }
+
+ synchronized double getQuality()
+ {
+ return quality;
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The mix operation. This method will, for every 20-byte block in the
+ * random pool, hash that block, the previous 20 bytes, and the next
+ * 44 bytes with SHA-1, writing the result back into that block.
+ */
+ private void mixRandomPool(byte[] buf)
+ {
+ int hashSize = hash.hashSize();
+ for (int i = 0; i < buf.length; i += hashSize)
+ {
+ // First update the bytes [p-19..p-1].
+ if (i == 0)
+ {
+ hash.update(buf, buf.length - hashSize, hashSize);
+ }
+ else
+ {
+ hash.update(buf, i - hashSize, hashSize);
+ }
+
+ // Now the next 64 bytes.
+ if (i + 64 < buf.length)
+ {
+ hash.update(buf, i, 64);
+ }
+ else
+ {
+ hash.update(buf, i, buf.length - i);
+ hash.update(buf, 0, 64 - (buf.length - i));
+ }
+
+ byte[] digest = hash.digest();
+ System.arraycopy(digest, 0, buf, i, hashSize);
+ }
+ }
+
+ private void mixRandomPool()
+ {
+ mixRandomPool(pool);
+ mixCount++;
+ }
+
+ private void generateX917(byte[] buf)
+ {
+ int off = 0;
+ for (int i = 0; i < buf.length; i += X917_POOL_SIZE)
+ {
+ int copy = Math.min(buf.length - i, X917_POOL_SIZE);
+ for (int j = 0; j < copy; j++)
+ {
+ x917pool[j] ^= pool[off + j];
+ }
+
+ cipher.encryptBlock(x917pool, 0, x917pool, 0);
+ System.arraycopy(x917pool, 0, buf, off, copy);
+ cipher.encryptBlock(x917pool, 0, x917pool, 0);
+
+ off += copy;
+ x917count++;
+ }
+ }
+
+ /**
+ * Add random data always immediately available into the random pool, such
+ * as the values of the eight asynchronous counters, the current time, the
+ * current memory usage, the calling thread name, and the current stack
+ * trace.
+ *
+ * <p>This method does not alter the quality counter, and is provided more
+ * to maintain randomness, not to seriously improve the current random
+ * state.
+ */
+ private void fastPoll()
+ {
+ byte b = 0;
+ for (int i = 0; i < SPINNER_COUNT; i++)
+ b ^= SPINNERS[i].counter;
+ addRandomByte(b);
+ addRandomByte((byte) System.currentTimeMillis());
+ addRandomByte((byte) Runtime.getRuntime().freeMemory());
+
+ String s = Thread.currentThread().getName();
+ if (s != null)
+ {
+ byte[] buf = s.getBytes();
+ addRandomBytes(buf, 0, buf.length);
+ }
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
+ PrintStream pout = new PrintStream(bout);
+ Throwable t = new Throwable();
+ t.printStackTrace(pout);
+ pout.flush();
+ byte[] buf = bout.toByteArray();
+ addRandomBytes(buf, 0, buf.length);
+ }
+
+ private void slowPoll() throws LimitReachedException
+ {
+ if (DEBUG)
+ {
+ debug("poller is alive? "
+ + (pollerThread == null ? false : pollerThread.isAlive()));
+ }
+ if (pollerThread == null || !pollerThread.isAlive())
+ {
+ boolean interrupted = false;
+ pollerThread = new Thread(poller);
+ pollerThread.setDaemon(true);
+ pollerThread.setPriority(Thread.NORM_PRIORITY - 1);
+ pollerThread.start();
+ if (blocking)
+ {
+ try
+ {
+ pollerThread.join();
+ }
+ catch (InterruptedException ie)
+ {
+ interrupted = true;
+ }
+ }
+
+ // If the full slow poll has completed after we waited for it,
+ // and there in insufficient randomness, throw an exception.
+ if (!interrupted && blocking && quality < 100.0)
+ {
+ if (DEBUG)
+ {
+ debug("insufficient quality: " + quality);
+ }
+ throw new LimitReachedException(
+ "insufficient randomness was polled");
+ }
+ }
+ }
+
+ protected void finalize() throws Throwable
+ {
+ if (poller != null && pollerThread != null && pollerThread.isAlive())
+ {
+ pollerThread.interrupt();
+ poller.stopUpdating();
+ pollerThread.interrupt();
+ }
+ Arrays.fill(pool, (byte) 0);
+ Arrays.fill(x917pool, (byte) 0);
+ Arrays.fill(buffer, (byte) 0);
+ }
+
+ // Inner classes.
+ // -------------------------------------------------------------------------
+
+ /**
+ * A simple thread that constantly updates a byte counter. This class is
+ * used in a group of lowest-priority threads and the values of their
+ * counters (updated in competition with all other threads) is used as a
+ * source of entropy bits.
+ */
+ private static class Spinner implements Runnable
+ {
+
+ // Field.
+ // -----------------------------------------------------------------------
+
+ private byte counter;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ private Spinner()
+ {
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public void run()
+ {
+ while (true)
+ {
+ counter++;
+ try
+ {
+ Thread.sleep(100);
+ }
+ catch (InterruptedException ie)
+ {
+ }
+ }
+ }
+ }
+
+ private final class Poller implements Runnable
+ {
+
+ // Fields.
+ // -----------------------------------------------------------------------
+
+ private final List files;
+
+ private final List urls;
+
+ private final List progs;
+
+ private final List other;
+
+ private final CSPRNG pool;
+
+ private boolean running;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ Poller(List files, List urls, List progs, List other, CSPRNG pool)
+ {
+ super();
+ this.files = Collections.unmodifiableList(files);
+ this.urls = Collections.unmodifiableList(urls);
+ this.progs = Collections.unmodifiableList(progs);
+ this.other = Collections.unmodifiableList(other);
+ this.pool = pool;
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public void run()
+ {
+ running = true;
+ if (DEBUG)
+ {
+ debug("files: " + files);
+ debug("URLs: " + urls);
+ debug("progs: " + progs);
+ }
+ Iterator files_it = files.iterator();
+ Iterator urls_it = urls.iterator();
+ Iterator prog_it = progs.iterator();
+ Iterator other_it = other.iterator();
+
+ while (files_it.hasNext() || urls_it.hasNext() || prog_it.hasNext()
+ || other_it.hasNext())
+ {
+
+ // There is enough random data. Go away.
+ if (pool.getQuality() >= 100.0 || !running)
+ {
+ return;
+ }
+
+ if (files_it.hasNext())
+ {
+ try
+ {
+ List l = (List) files_it.next();
+ if (DEBUG)
+ {
+ debug(l.toString());
+ }
+ double qual = ((Double) l.get(0)).doubleValue();
+ int offset = ((Integer) l.get(1)).intValue();
+ int count = ((Integer) l.get(2)).intValue();
+ String src = (String) l.get(3);
+ InputStream in = new FileInputStream(src);
+ byte[] buf = new byte[count];
+ if (offset > 0)
+ {
+ in.skip(offset);
+ }
+ int len = in.read(buf);
+ if (len >= 0)
+ {
+ pool.addRandomBytes(buf, 0, len);
+ pool.addQuality(qual * ((double) len / (double) count));
+ }
+ if (DEBUG)
+ {
+ debug("got " + len + " bytes from " + src);
+ }
+ }
+ catch (Exception x)
+ {
+ if (DEBUG)
+ {
+ debug(x.toString());
+ x.printStackTrace();
+ }
+ }
+ }
+
+ if (pool.getQuality() >= 100.0 || !running)
+ {
+ return;
+ }
+
+ if (urls_it.hasNext())
+ {
+ try
+ {
+ List l = (List) urls_it.next();
+ if (DEBUG)
+ {
+ debug(l.toString());
+ }
+ double qual = ((Double) l.get(0)).doubleValue();
+ int offset = ((Integer) l.get(1)).intValue();
+ int count = ((Integer) l.get(2)).intValue();
+ URL src = (URL) l.get(3);
+ InputStream in = src.openStream();
+ byte[] buf = new byte[count];
+ if (offset > 0)
+ {
+ in.skip(offset);
+ }
+ int len = in.read(buf);
+ if (len >= 0)
+ {
+ pool.addRandomBytes(buf, 0, len);
+ pool.addQuality(qual * ((double) len / (double) count));
+ }
+ if (DEBUG)
+ {
+ debug("got " + len + " bytes from " + src);
+ }
+ }
+ catch (Exception x)
+ {
+ if (DEBUG)
+ {
+ debug(x.toString());
+ x.printStackTrace();
+ }
+ }
+ }
+
+ if (pool.getQuality() >= 100.0 || !running)
+ {
+ return;
+ }
+
+ Process proc = null;
+ if (prog_it.hasNext())
+ {
+ try
+ {
+ List l = (List) prog_it.next();
+ if (DEBUG)
+ {
+ debug(l.toString());
+ }
+ double qual = ((Double) l.get(0)).doubleValue();
+ int offset = ((Integer) l.get(1)).intValue();
+ int count = ((Integer) l.get(2)).intValue();
+ String src = (String) l.get(3);
+ proc = null;
+ proc = Runtime.getRuntime().exec(src);
+ InputStream in = proc.getInputStream();
+ byte[] buf = new byte[count];
+ if (offset > 0)
+ {
+ in.skip(offset);
+ }
+ int len = in.read(buf);
+ if (len >= 0)
+ {
+ pool.addRandomBytes(buf, 0, len);
+ pool.addQuality(qual * ((double) len / (double) count));
+ }
+ proc.destroy();
+ proc.waitFor();
+ if (DEBUG)
+ {
+ debug("got " + len + " bytes from " + src);
+ }
+ }
+ catch (Exception x)
+ {
+ if (DEBUG)
+ {
+ debug(x.toString());
+ x.printStackTrace();
+ }
+ try
+ {
+ if (proc != null)
+ {
+ proc.destroy();
+ proc.waitFor();
+ }
+ }
+ catch (Exception ignored)
+ {
+ }
+ }
+ }
+
+ if (pool.getQuality() >= 100.0 || !running)
+ {
+ return;
+ }
+
+ if (other_it.hasNext())
+ {
+ try
+ {
+ EntropySource src = (EntropySource) other_it.next();
+ byte[] buf = src.nextBytes();
+ if (pool == null)
+ {
+ return;
+ }
+ pool.addRandomBytes(buf, 0, buf.length);
+ pool.addQuality(src.quality());
+ if (DEBUG)
+ {
+ debug("got " + buf.length + " bytes from " + src);
+ }
+ }
+ catch (Exception x)
+ {
+ if (DEBUG)
+ {
+ debug(x.toString());
+ x.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ public void stopUpdating()
+ {
+ running = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/prng/Fortuna.java b/gnu/javax/crypto/prng/Fortuna.java
new file mode 100644
index 000000000..6453a9d02
--- /dev/null
+++ b/gnu/javax/crypto/prng/Fortuna.java
@@ -0,0 +1,366 @@
+/* Fortuna.java -- The Fortuna PRNG.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.prng;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.prng.BasePRNG;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.prng.RandomEvent;
+import gnu.java.security.prng.RandomEventListener;
+
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import java.security.InvalidKeyException;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * The Fortuna continuously-seeded pseudo-random number generator. This
+ * generator is composed of two major pieces: the entropy accumulator
+ * and the generator function. The former takes in random bits and
+ * incorporates them into the generator's state. The latter takes this
+ * base entropy and generates pseudo-random bits from it.
+ *
+ * <p>There are some things users of this class <em>must</em> be aware of:
+ *
+ * <dl>
+ * <dt>Adding Random Data</dt>
+ * <dd>This class does not do any polling of random sources, but rather
+ * provides an interface for adding random events. Applications that use
+ * this code <em>must</em> provide this mechanism. We use this design
+ * because an application writer who knows the system he is targeting
+ * is in a better position to judge what random data is available.</dd>
+ *
+ * <dt>Storing the Seed</dt>
+ * <dd>This class implements {@link Serializable} in such a way that it
+ * writes a 64 byte seed to the stream, and reads it back again when being
+ * deserialized. This is the extent of seed file management, however, and
+ * those using this class are encouraged to think deeply about when, how
+ * often, and where to store the seed.</dd>
+ * </dl>
+ *
+ * <p><b>References:</b></p>
+ *
+ * <ul>
+ * <li>Niels Ferguson and Bruce Schneier, <i>Practical Cryptography</i>,
+ * pp. 155--184. Wiley Publishing, Indianapolis. (2003 Niels Ferguson and
+ * Bruce Schneier). ISBN 0-471-22357-3.</li>
+ * </ul>
+ */
+public class Fortuna extends BasePRNG implements Serializable,
+ RandomEventListener
+{
+
+ private static final long serialVersionUID = 0xFACADE;
+
+ private static final int SEED_FILE_SIZE = 64;
+
+ private static final int NUM_POOLS = 32;
+
+ private static final int MIN_POOL_SIZE = 64;
+
+ private final Generator generator;
+
+ private final IMessageDigest[] pools;
+
+ private long lastReseed;
+
+ private int pool;
+
+ private int pool0Count;
+
+ private int reseedCount;
+
+ public static final String SEED = "gnu.crypto.prng.fortuna.seed";
+
+ public Fortuna()
+ {
+ super(Registry.FORTUNA_PRNG);
+ generator = new Generator(
+ CipherFactory.getInstance(Registry.RIJNDAEL_CIPHER),
+ HashFactory.getInstance(Registry.SHA256_HASH));
+ pools = new IMessageDigest[NUM_POOLS];
+ for (int i = 0; i < NUM_POOLS; i++)
+ pools[i] = HashFactory.getInstance(Registry.SHA256_HASH);
+ lastReseed = 0;
+ pool = 0;
+ pool0Count = 0;
+ buffer = new byte[256];
+ }
+
+ public void setup(Map attributes)
+ {
+ lastReseed = 0;
+ reseedCount = 0;
+ pool = 0;
+ pool0Count = 0;
+ generator.init(attributes);
+ }
+
+ public void fillBlock() throws LimitReachedException
+ {
+ if (pool0Count >= MIN_POOL_SIZE
+ && System.currentTimeMillis() - lastReseed > 100)
+ {
+ reseedCount++;
+ byte[] seed = new byte[0];
+ for (int i = 0; i < NUM_POOLS; i++)
+ {
+ if (reseedCount % (1 << i) == 0)
+ generator.addRandomBytes(pools[i].digest());
+ }
+ lastReseed = System.currentTimeMillis();
+ pool0Count = 0;
+ }
+ generator.nextBytes(buffer);
+ }
+
+ public void addRandomByte(byte b)
+ {
+ pools[pool].update(b);
+ if (pool == 0)
+ pool0Count++;
+ pool = (pool + 1) % NUM_POOLS;
+ }
+
+ public void addRandomBytes(byte[] buf, int offset, int length)
+ {
+ pools[pool].update(buf, offset, length);
+ if (pool == 0)
+ pool0Count += length;
+ pool = (pool + 1) % NUM_POOLS;
+ }
+
+ public void addRandomEvent(RandomEvent event)
+ {
+ if (event.getPoolNumber() < 0 || event.getPoolNumber() >= pools.length)
+ throw new IllegalArgumentException("pool number out of range: "
+ + event.getPoolNumber());
+ pools[event.getPoolNumber()].update(event.getSourceNumber());
+ pools[event.getPoolNumber()].update((byte) event.getData().length);
+ pools[event.getPoolNumber()].update(event.getData());
+ if (event.getPoolNumber() == 0)
+ pool0Count += event.getData().length;
+ }
+
+ // Reading and writing this object is equivalent to storing and retrieving
+ // the seed.
+
+ private void writeObject(ObjectOutputStream out) throws IOException
+ {
+ byte[] seed = new byte[SEED_FILE_SIZE];
+ try
+ {
+ generator.nextBytes(seed);
+ }
+ catch (LimitReachedException shouldNeverHappen)
+ {
+ throw new Error(shouldNeverHappen);
+ }
+ out.write(seed);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException
+ {
+ byte[] seed = new byte[SEED_FILE_SIZE];
+ in.readFully(seed);
+ generator.addRandomBytes(seed);
+ }
+
+ /**
+ * The Fortuna generator function. The generator is a PRNG in its own
+ * right; Fortuna itself is basically a wrapper around this generator
+ * that manages reseeding in a secure way.
+ */
+ public static class Generator extends BasePRNG implements Cloneable
+ {
+
+ private static final int LIMIT = 1 << 20;
+
+ private final IBlockCipher cipher;
+
+ private final IMessageDigest hash;
+
+ private final byte[] counter;
+
+ private final byte[] key;
+
+ private boolean seeded;
+
+ public Generator(final IBlockCipher cipher, final IMessageDigest hash)
+ {
+ super(Registry.FORTUNA_GENERATOR_PRNG);
+ this.cipher = cipher;
+ this.hash = hash;
+ counter = new byte[cipher.defaultBlockSize()];
+ buffer = new byte[cipher.defaultBlockSize()];
+ int keysize = 0;
+ for (Iterator it = cipher.keySizes(); it.hasNext();)
+ {
+ int ks = ((Integer) it.next()).intValue();
+ if (ks > keysize)
+ keysize = ks;
+ if (keysize >= 32)
+ break;
+ }
+ key = new byte[keysize];
+ }
+
+ public byte nextByte()
+ {
+ byte[] b = new byte[1];
+ nextBytes(b, 0, 1);
+ return b[0];
+ }
+
+ public void nextBytes(byte[] out, int offset, int length)
+ {
+ if (!seeded)
+ throw new IllegalStateException("generator not seeded");
+
+ int count = 0;
+ do
+ {
+ int amount = Math.min(LIMIT, length - count);
+ try
+ {
+ super.nextBytes(out, offset + count, amount);
+ }
+ catch (LimitReachedException shouldNeverHappen)
+ {
+ throw new Error(shouldNeverHappen);
+ }
+ count += amount;
+
+ for (int i = 0; i < key.length; i += counter.length)
+ {
+ fillBlock();
+ int l = Math.min(key.length - i, cipher.currentBlockSize());
+ System.arraycopy(buffer, 0, key, i, l);
+ }
+ resetKey();
+ }
+ while (count < length);
+ fillBlock();
+ ndx = 0;
+ }
+
+ public void addRandomByte(byte b)
+ {
+ addRandomBytes(new byte[] { b });
+ }
+
+ public void addRandomBytes(byte[] seed, int offset, int length)
+ {
+ hash.update(key);
+ hash.update(seed, offset, length);
+ byte[] newkey = hash.digest();
+ System.arraycopy(newkey, 0, key, 0, Math.min(key.length, newkey.length));
+ resetKey();
+ incrementCounter();
+ seeded = true;
+ }
+
+ public void fillBlock()
+ {
+ if (!seeded)
+ throw new IllegalStateException("generator not seeded");
+ cipher.encryptBlock(counter, 0, buffer, 0);
+ incrementCounter();
+ }
+
+ public void setup(Map attributes)
+ {
+ seeded = false;
+ Arrays.fill(key, (byte) 0);
+ Arrays.fill(counter, (byte) 0);
+ byte[] seed = (byte[]) attributes.get(SEED);
+ if (seed != null)
+ addRandomBytes(seed);
+ }
+
+ /**
+ * Resets the cipher's key. This is done after every reseed, which
+ * combines the old key and the seed, and processes that throigh the
+ * hash function.
+ */
+ private void resetKey()
+ {
+ try
+ {
+ cipher.reset();
+ cipher.init(Collections.singletonMap(IBlockCipher.KEY_MATERIAL, key));
+ }
+ // We expect to never get an exception here.
+ catch (InvalidKeyException ike)
+ {
+ throw new Error(ike);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new Error(iae);
+ }
+ }
+
+ /**
+ * Increment `counter' as a sixteen-byte little-endian unsigned integer
+ * by one.
+ */
+ private void incrementCounter()
+ {
+ for (int i = 0; i < counter.length; i++)
+ {
+ counter[i]++;
+ if (counter[i] != 0)
+ break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/prng/ICMGenerator.java b/gnu/javax/crypto/prng/ICMGenerator.java
new file mode 100644
index 000000000..0de38e256
--- /dev/null
+++ b/gnu/javax/crypto/prng/ICMGenerator.java
@@ -0,0 +1,379 @@
+/* ICMGenerator.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.prng;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.BasePRNG;
+import gnu.java.security.prng.LimitReachedException;
+
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.cipher.CipherFactory;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>Counter Mode is a way to define a pseudorandom keystream generator using
+ * a block cipher. The keystream can be used for additive encryption, key
+ * derivation, or any other application requiring pseudorandom data.</p>
+ *
+ * <p>In ICM, the keystream is logically broken into segments. Each segment is
+ * identified with a segment index, and the segments have equal lengths. This
+ * segmentation makes ICM especially appropriate for securing packet-based
+ * protocols.</p>
+ *
+ * <p>This implementation adheres to the definition of the ICM keystream
+ * generation function that allows for any symetric key block cipher algorithm
+ * (initialisation parameter <code>gnu.crypto.prng.icm.cipher.name</code> taken
+ * to be an instance of {@link java.lang.String}) to be used. If such a
+ * parameter is not defined/included in the initialisation <code>Map</code>,
+ * then the "Rijndael" algorithm is used. Furthermore, if the initialisation
+ * parameter <code>gnu.crypto.cipher.block.size</code> (taken to be a instance
+ * of {@link java.lang.Integer}) is missing or undefined in the initialisation
+ * <code>Map</code>, then the cipher's <em>default</em> block size is used.</p>
+ *
+ * <p>The practical limits and constraints of such generator are:</p>
+ * <ul>
+ * <li>The number of blocks in any segment <b>MUST NOT</b> exceed <code>
+ * 256 ** BLOCK_INDEX_LENGTH</code>. The number of segments <b>MUST NOT</b>
+ * exceed <code>256 ** SEGMENT_INDEX_LENGTH</code>. These restrictions ensure
+ * the uniqueness of each block cipher input.</li>
+ *
+ * <li>Each segment contains <code>SEGMENT_LENGTH</code> octets; this value
+ * <b>MUST NOT</b> exceed the value <code>(256 ** BLOCK_INDEX_LENGTH) *
+ * BLOCK_LENGTH</code>.</li>
+ *
+ * <li>The sum of <code>SEGMENT_INDEX_LENGTH</code> and
+ * <code>BLOCK_INDEX_LENGTH</code> <b>MUST NOT</b> exceed <code>BLOCK_LENGTH
+ * / 2</code>. This requirement protects the ICM keystream generator from
+ * potentially failing to be pseudorandom.</li>
+ * </ul>
+ *
+ * <p><b>NOTE</b>: Rijndael is used as the default symmetric key block cipher
+ * algorithm because, with its default block and key sizes, it is the AES. Yet
+ * being Rijndael, the algorithm offers more versatile block and key sizes which
+ * may prove to be useful for generating <em>longer</em> key streams.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-mcgrew-saag-icm-00.txt">
+ * Integer Counter Mode</a>, David A. McGrew.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class ICMGenerator extends BasePRNG implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Property name of underlying block cipher for this ICM generator. */
+ public static final String CIPHER = "gnu.crypto.prng.icm.cipher.name";
+
+ /** Property name of ICM's block index length. */
+ public static final String BLOCK_INDEX_LENGTH = "gnu.crypto.prng.icm.block.index.length";
+
+ /** Property name of ICM's segment index length. */
+ public static final String SEGMENT_INDEX_LENGTH = "gnu.crypto.prng.icm.segment.index.length";
+
+ /** Property name of ICM's offset. */
+ public static final String OFFSET = "gnu.crypto.prng.icm.offset";
+
+ /** Property name of ICM's segment index. */
+ public static final String SEGMENT_INDEX = "gnu.crypto.prng.icm.segment.index";
+
+ /** The integer value 256 as a BigInteger. */
+ private static final BigInteger TWO_FIFTY_SIX = new BigInteger("256");
+
+ /** The underlying cipher implementation. */
+ private IBlockCipher cipher;
+
+ /** This keystream block index length in bytes. */
+ private int blockNdxLength = -1;
+
+ /** This keystream segment index length in bytes. */
+ private int segmentNdxLength = -1;
+
+ /** The index of the next block for a given keystream segment. */
+ private BigInteger blockNdx = BigInteger.ZERO;
+
+ /** The segment index for this keystream. */
+ private BigInteger segmentNdx;
+
+ /** The initial counter for a given keystream segment. */
+ private BigInteger C0;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public ICMGenerator()
+ {
+ super(Registry.ICM_PRNG);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in BasePRNG --------------------------
+
+ // Conceptually, ICM is a keystream generator that takes a secret key
+ // and a segment index as an input and then outputs a keystream
+ // segment. The segmentation lends itself to packet encryption, as
+ // each keystream segment can be used to encrypt a distinct packet.
+ //
+ // An ICM key consists of the block cipher key and an Offset. The
+ // Offset is an integer with BLOCK_LENGTH octets...
+ //
+ public void setup(Map attributes)
+ {
+ // find out which cipher algorithm to use
+ boolean newCipher = true;
+ String underlyingCipher = (String) attributes.get(CIPHER);
+ if (underlyingCipher == null)
+ {
+ if (cipher == null)
+ { // happy birthday
+ // ensure we have a reliable implementation of this cipher
+ cipher = CipherFactory.getInstance(Registry.RIJNDAEL_CIPHER);
+ }
+ else
+ { // we already have one. use it as is
+ newCipher = false;
+ }
+ }
+ else
+ { // ensure we have a reliable implementation of this cipher
+ cipher = CipherFactory.getInstance(underlyingCipher);
+ }
+
+ // find out what block size we should use it in
+ int cipherBlockSize = 0;
+ Integer bs = (Integer) attributes.get(IBlockCipher.CIPHER_BLOCK_SIZE);
+ if (bs != null)
+ {
+ cipherBlockSize = bs.intValue();
+ }
+ else
+ {
+ if (newCipher)
+ { // assume we'll use its default block size
+ cipherBlockSize = cipher.defaultBlockSize();
+ } // else use as is
+ }
+
+ // get the key material
+ byte[] key = (byte[]) attributes.get(IBlockCipher.KEY_MATERIAL);
+ if (key == null)
+ {
+ throw new IllegalArgumentException(IBlockCipher.KEY_MATERIAL);
+ }
+
+ // now initialise the cipher
+ HashMap map = new HashMap();
+ if (cipherBlockSize != 0)
+ { // only needed if new or changed
+ map.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(cipherBlockSize));
+ }
+ map.put(IBlockCipher.KEY_MATERIAL, key);
+ try
+ {
+ cipher.init(map);
+ }
+ catch (InvalidKeyException x)
+ {
+ throw new IllegalArgumentException(IBlockCipher.KEY_MATERIAL);
+ }
+
+ // at this point we have an initialised (new or otherwise) cipher
+ // ensure that remaining params make sense
+
+ cipherBlockSize = cipher.currentBlockSize();
+ BigInteger counterRange = TWO_FIFTY_SIX.pow(cipherBlockSize);
+
+ // offset, like the underlying cipher key is not cloneable
+ // always look for it and throw an exception if it's not there
+ Object obj = attributes.get(OFFSET);
+ // allow either a byte[] or a BigInteger
+ BigInteger r;
+ if (obj instanceof BigInteger)
+ {
+ r = (BigInteger) obj;
+ }
+ else
+ { // assume byte[]. should be same length as cipher block size
+ byte[] offset = (byte[]) obj;
+ if (offset.length != cipherBlockSize)
+ {
+ throw new IllegalArgumentException(OFFSET);
+ }
+
+ r = new BigInteger(1, offset);
+ }
+
+ int wantBlockNdxLength = -1; // number of octets in the block index
+ Integer i = (Integer) attributes.get(BLOCK_INDEX_LENGTH);
+ if (i != null)
+ {
+ wantBlockNdxLength = i.intValue();
+ if (wantBlockNdxLength < 1)
+ {
+ throw new IllegalArgumentException(BLOCK_INDEX_LENGTH);
+ }
+ }
+
+ int wantSegmentNdxLength = -1; // number of octets in the segment index
+ i = (Integer) attributes.get(SEGMENT_INDEX_LENGTH);
+ if (i != null)
+ {
+ wantSegmentNdxLength = i.intValue();
+ if (wantSegmentNdxLength < 1)
+ {
+ throw new IllegalArgumentException(SEGMENT_INDEX_LENGTH);
+ }
+ }
+
+ // if both are undefined check if it's a reuse
+ if ((wantBlockNdxLength == -1) && (wantSegmentNdxLength == -1))
+ {
+ if (blockNdxLength == -1)
+ { // new instance
+ throw new IllegalArgumentException(BLOCK_INDEX_LENGTH + ", "
+ + SEGMENT_INDEX_LENGTH);
+ } // else reuse old values
+ }
+ else
+ { // only one is undefined, set it to BLOCK_LENGTH/2 minus the other
+ int limit = cipherBlockSize / 2;
+ if (wantBlockNdxLength == -1)
+ {
+ wantBlockNdxLength = limit - wantSegmentNdxLength;
+ }
+ else if (wantSegmentNdxLength == -1)
+ {
+ wantSegmentNdxLength = limit - wantBlockNdxLength;
+ }
+ else if ((wantSegmentNdxLength + wantBlockNdxLength) > limit)
+ {
+ throw new IllegalArgumentException(BLOCK_INDEX_LENGTH + ", "
+ + SEGMENT_INDEX_LENGTH);
+ }
+ // save new values
+ blockNdxLength = wantBlockNdxLength;
+ segmentNdxLength = wantSegmentNdxLength;
+ }
+
+ // get the segment index as a BigInteger
+ BigInteger s = (BigInteger) attributes.get(SEGMENT_INDEX);
+ if (s == null)
+ {
+ if (segmentNdx == null)
+ { // segment index was never set
+ throw new IllegalArgumentException(SEGMENT_INDEX);
+ }
+ // reuse; check if still valid
+ if (segmentNdx.compareTo(TWO_FIFTY_SIX.pow(segmentNdxLength)) > 0)
+ {
+ throw new IllegalArgumentException(SEGMENT_INDEX);
+ }
+ }
+ else
+ {
+ if (s.compareTo(TWO_FIFTY_SIX.pow(segmentNdxLength)) > 0)
+ {
+ throw new IllegalArgumentException(SEGMENT_INDEX);
+ }
+ segmentNdx = s;
+ }
+
+ // The initial counter of the keystream segment with segment index s is
+ // defined as follows, where r denotes the Offset:
+ //
+ // C[0] = (s * (256^BLOCK_INDEX_LENGTH) + r) modulo (256^BLOCK_LENGTH)
+ //
+ C0 = segmentNdx.multiply(TWO_FIFTY_SIX.pow(blockNdxLength)).add(r).modPow(
+ BigInteger.ONE,
+ counterRange);
+ }
+
+ public void fillBlock() throws LimitReachedException
+ {
+ if (C0 == null)
+ {
+ throw new IllegalStateException();
+ }
+ if (blockNdx.compareTo(TWO_FIFTY_SIX.pow(blockNdxLength)) >= 0)
+ {
+ throw new LimitReachedException();
+ }
+
+ int cipherBlockSize = cipher.currentBlockSize();
+ BigInteger counterRange = TWO_FIFTY_SIX.pow(cipherBlockSize);
+
+ // encrypt the counter for the current blockNdx
+ // C[i] = (C[0] + i) modulo (256^BLOCK_LENGTH).
+
+ BigInteger Ci = C0.add(blockNdx).modPow(BigInteger.ONE, counterRange);
+ buffer = Ci.toByteArray();
+ int limit = buffer.length;
+ if (limit < cipherBlockSize)
+ {
+ byte[] data = new byte[cipherBlockSize];
+ System.arraycopy(buffer, 0, data, cipherBlockSize - limit, limit);
+ buffer = data;
+ }
+ else if (limit > cipherBlockSize)
+ {
+ byte[] data = new byte[cipherBlockSize];
+ System.arraycopy(buffer, limit - cipherBlockSize, data, 0,
+ cipherBlockSize);
+ buffer = data;
+ }
+
+ cipher.encryptBlock(buffer, 0, buffer, 0);
+ blockNdx = blockNdx.add(BigInteger.ONE); // increment blockNdx
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/prng/IPBE.java b/gnu/javax/crypto/prng/IPBE.java
new file mode 100644
index 000000000..531e7ead8
--- /dev/null
+++ b/gnu/javax/crypto/prng/IPBE.java
@@ -0,0 +1,69 @@
+/* IPBE.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.prng;
+
+/**
+ * <p>Trivial interface to group Password-based encryption property names.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface IPBE
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /**
+ * Property name for the iteration count in a PBE algorithm. The property
+ * associated with this is expected to be an {@link Integer}.
+ */
+ public static final String ITERATION_COUNT = "gnu.crypto.pbe.iteration.count";
+
+ /**
+ * Property name for the password in a PBE algorithm. The property associated
+ * with this is expected to be a char array.
+ */
+ public static final String PASSWORD = "gnu.crypto.pbe.password";
+
+ /**
+ * Property name for the salt in a PBE algorithm. The property associated
+ * with this is expected to be a byte array.
+ */
+ public static final String SALT = "gnu.crypto.pbe.salt";
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/prng/PBKDF2.java b/gnu/javax/crypto/prng/PBKDF2.java
new file mode 100644
index 000000000..5146bd4b9
--- /dev/null
+++ b/gnu/javax/crypto/prng/PBKDF2.java
@@ -0,0 +1,216 @@
+/* PBKDF2.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.prng;
+
+import gnu.java.security.prng.BasePRNG;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.mac.HMac;
+import gnu.javax.crypto.mac.IMac;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>An implementation of the <i>key derivation function</i> KDF2 from PKCS #5:
+ * Password-Based Cryptography (<b>PBE</b>). This KDF is essentially a way to
+ * transform a password and a salt into a stream of random bytes, which may then
+ * be used to initialize a cipher or a MAC.</p>
+ *
+ * <p>This version uses a MAC as its pseudo-random function, and the password is
+ * used as the key.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li>B. Kaliski, <a href="http://www.ietf.org/rfc/rfc2898.txt">RFC 2898:
+ * Password-Based Cryptography Specification, Version 2.0</a></li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class PBKDF2 extends BasePRNG implements Cloneable
+{
+
+ // Contstants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * The bytes fed into the MAC. This is initially the concatenation of the
+ * salt and the block number.
+ */
+ private byte[] in;
+
+ /** The iteration count. */
+ private int iterationCount;
+
+ /** The salt. */
+ private byte[] salt;
+
+ /** The MAC (the pseudo-random function we use). */
+ private IMac mac;
+
+ /** The number of hLen-sized blocks generated. */
+ private long count;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Creates a new PBKDF2 object. The argument is the MAC that will serve as
+ * the pseudo-random function. The MAC does not need to be initialized.</p>
+ *
+ * @param mac The pseudo-random function.
+ */
+ public PBKDF2(IMac mac)
+ {
+ super("PBKDF2-" + mac.name());
+ this.mac = mac;
+ iterationCount = -1;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public void setup(Map attributes)
+ {
+ Map macAttrib = new HashMap();
+ macAttrib.put(HMac.USE_WITH_PKCS5_V2, Boolean.TRUE);
+
+ byte[] s = (byte[]) attributes.get(IPBE.SALT);
+ if (s == null)
+ {
+ if (salt == null)
+ {
+ throw new IllegalArgumentException("no salt specified");
+ } // Otherwise re-use.
+ }
+ else
+ {
+ salt = s;
+ }
+
+ char[] password = (char[]) attributes.get(IPBE.PASSWORD);
+ if (password != null)
+ {
+ try
+ {
+ macAttrib.put(IMac.MAC_KEY_MATERIAL,
+ new String(password).getBytes("UTF-8"));
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ throw new Error(uee.getMessage());
+ }
+ }
+ else if (!initialised)
+ {
+ throw new IllegalArgumentException("no password specified");
+ } // otherwise re-use previous password.
+
+ try
+ {
+ mac.init(macAttrib);
+ }
+ catch (Exception x)
+ {
+ throw new IllegalArgumentException(x.getMessage());
+ }
+
+ Integer ic = (Integer) attributes.get(IPBE.ITERATION_COUNT);
+ if (ic != null)
+ {
+ iterationCount = ic.intValue();
+ }
+ if (iterationCount <= 0)
+ {
+ throw new IllegalArgumentException("bad iteration count");
+ }
+
+ count = 0L;
+ buffer = new byte[mac.macSize()];
+ try
+ {
+ fillBlock();
+ // } catch (Exception x) {
+ }
+ catch (LimitReachedException x)
+ {
+ // x.printStackTrace(System.err);
+ throw new Error(x.getMessage());
+ }
+ }
+
+ public void fillBlock() throws LimitReachedException
+ {
+ if (++count > ((1L << 32) - 1))
+ {
+ throw new LimitReachedException();
+ }
+ // for (int i = 0; i < buffer.length; i++) {
+ // buffer[i] = 0;
+ // }
+ Arrays.fill(buffer, (byte) 0x00);
+ int limit = salt.length;
+ // in = new byte[salt.length + 4];
+ in = new byte[limit + 4];
+ System.arraycopy(salt, 0, in, 0, salt.length);
+ // in[salt.length ] = (byte)(count >>> 24);
+ // in[salt.length+1] = (byte)(count >>> 16);
+ // in[salt.length+2] = (byte)(count >>> 8);
+ // in[salt.length+3] = (byte) count;
+ in[limit++] = (byte) (count >>> 24);
+ in[limit++] = (byte) (count >>> 16);
+ in[limit++] = (byte) (count >>> 8);
+ in[limit] = (byte) count;
+ for (int i = 0; i < iterationCount; i++)
+ {
+ mac.reset();
+ mac.update(in, 0, in.length);
+ in = mac.digest();
+ for (int j = 0; j < buffer.length; j++)
+ {
+ buffer[j] ^= in[j];
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/prng/PRNGFactory.java b/gnu/javax/crypto/prng/PRNGFactory.java
new file mode 100644
index 000000000..9ff6558b0
--- /dev/null
+++ b/gnu/javax/crypto/prng/PRNGFactory.java
@@ -0,0 +1,143 @@
+/* PRNGFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.prng;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.IRandom;
+
+
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+import gnu.javax.crypto.mac.HMacFactory;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <p>A Factory to instantiate pseudo random number generators.</p>
+ */
+public class PRNGFactory implements Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce <i>Singleton</i> pattern. */
+ private PRNGFactory()
+ {
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a padding algorithm given its name.</p>
+ *
+ * @param prng the case-insensitive name of the PRNG.
+ * @return an instance of the pseudo-random number generator.
+ * @exception InternalError if the implementation does not pass its self-
+ * test.
+ */
+ public static IRandom getInstance(String prng)
+ {
+ if (prng == null)
+ {
+ return null;
+ }
+
+ prng = prng.trim();
+ IRandom result = null;
+ if (prng.equalsIgnoreCase(ARCFOUR_PRNG) || prng.equalsIgnoreCase(RC4_PRNG))
+ {
+ result = new ARCFour();
+ }
+ else if (prng.equalsIgnoreCase(ICM_PRNG))
+ {
+ result = new ICMGenerator();
+ }
+ else if (prng.equalsIgnoreCase(UMAC_PRNG))
+ {
+ result = new UMacGenerator();
+ }
+ else if (prng.toLowerCase().startsWith(PBKDF2_PRNG_PREFIX))
+ {
+ String macName = prng.substring(PBKDF2_PRNG_PREFIX.length());
+ IMac mac = MacFactory.getInstance(macName);
+ if (mac == null)
+ {
+ return null;
+ }
+ result = new PBKDF2(mac);
+ }
+
+ if (result != null)
+ return result;
+
+ return gnu.java.security.prng.PRNGFactory.getInstance (prng);
+ }
+
+ /**
+ * <p>Returns a {@link Set} of names of padding algorithms supported by this
+ * <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of pseudo-random number generator algorithm names
+ * (Strings).
+ */
+ public static Set getNames()
+ {
+ HashSet hs = new HashSet (gnu.java.security.prng.PRNGFactory.getNames ());
+ hs.add(ICM_PRNG);
+ hs.add(UMAC_PRNG);
+ // add all hmac implementations as candidate PBKDF2 ones too
+ for (Iterator it = HMacFactory.getNames().iterator(); it.hasNext();)
+ {
+ hs.add(PBKDF2_PRNG_PREFIX + ((String) it.next()));
+ }
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/gnu/javax/crypto/prng/UMacGenerator.java b/gnu/javax/crypto/prng/UMacGenerator.java
new file mode 100644
index 000000000..0e3725ce9
--- /dev/null
+++ b/gnu/javax/crypto/prng/UMacGenerator.java
@@ -0,0 +1,228 @@
+/* UMacGenerator.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.prng;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.BasePRNG;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.security.InvalidKeyException;
+
+/**
+ * <p><i>KDF</i>s (Key Derivation Functions) are used to stretch user-supplied
+ * key material to specific size(s) required by high level cryptographic
+ * primitives. Described in the <A
+ * HREF="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">UMAC</A>
+ * paper, this function basically operates an underlying <em>symmetric key block
+ * cipher</em> instance in output feedback mode (OFB), as a <b>strong</b>
+ * pseudo-random number generator.</p>
+ *
+ * <p><code>UMacGenerator</code> requires an <em>index</em> parameter
+ * (initialisation parameter <code>gnu.crypto.prng.umac.kdf.index</code> taken
+ * to be an instance of {@link java.lang.Integer} with a value between
+ * <code>0</code> and <code>255</code>). Using the same key, but different
+ * indices, generates different pseudorandom outputs.</p>
+ *
+ * <p>This implementation generalises the definition of the
+ * <code>UmacGenerator</code> algorithm to allow for other than the AES symetric
+ * key block cipher algorithm (initialisation parameter
+ * <code>gnu.crypto.prng.umac.cipher.name</code> taken to be an instance of
+ * {@link java.lang.String}). If such a parameter is not defined/included in the
+ * initialisation <code>Map</code>, then the "Rijndael" algorithm is used.
+ * Furthermore, if the initialisation parameter
+ * <code>gnu.crypto.cipher.block.size</code> (taken to be a instance of {@link
+ * java.lang.Integer}) is missing or undefined in the initialisation <code>Map
+ * </code>, then the cipher's <em>default</em> block size is used.</p>
+ *
+ * <p><b>NOTE</b>: Rijndael is used as the default symmetric key block cipher
+ * algorithm because, with its default block and key sizes, it is the AES. Yet
+ * being Rijndael, the algorithm offers more versatile block and key sizes which
+ * may prove to be useful for generating "longer" key streams.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-krovetz-umac-01.txt">
+ * UMAC</a>: Message Authentication Code using Universal Hashing.<br>
+ * T. Krovetz, J. Black, S. Halevi, A. Hevia, H. Krawczyk, and P. Rogaway.</li>
+ * </ol>
+ */
+public class UMacGenerator extends BasePRNG implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Property name of the KDF <code>index</code> value to use in this
+ * instance. The value is taken to be an {@link Integer} less than
+ * <code>256</code>.</p>
+ */
+ public static final String INDEX = "gnu.crypto.prng.umac.index";
+
+ /** The name of the underlying symmetric key block cipher algorithm. */
+ public static final String CIPHER = "gnu.crypto.prng.umac.cipher.name";
+
+ /** The generator's underlying block cipher. */
+ private IBlockCipher cipher;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public UMacGenerator()
+ {
+ super(Registry.UMAC_PRNG);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in BasePRNG --------------------------
+
+ public void setup(Map attributes)
+ {
+ boolean newCipher = true;
+ String cipherName = (String) attributes.get(CIPHER);
+ if (cipherName == null)
+ {
+ if (cipher == null)
+ { // happy birthday
+ cipher = CipherFactory.getInstance(Registry.RIJNDAEL_CIPHER);
+ }
+ else
+ { // we already have one. use it as is
+ newCipher = false;
+ }
+ }
+ else
+ {
+ cipher = CipherFactory.getInstance(cipherName);
+ }
+
+ // find out what block size we should use it in
+ int cipherBlockSize = 0;
+ Integer bs = (Integer) attributes.get(IBlockCipher.CIPHER_BLOCK_SIZE);
+ if (bs != null)
+ {
+ cipherBlockSize = bs.intValue();
+ }
+ else
+ {
+ if (newCipher)
+ { // assume we'll use its default block size
+ cipherBlockSize = cipher.defaultBlockSize();
+ } // else use as is
+ }
+
+ // get the key material
+ byte[] key = (byte[]) attributes.get(IBlockCipher.KEY_MATERIAL);
+ if (key == null)
+ {
+ throw new IllegalArgumentException(IBlockCipher.KEY_MATERIAL);
+ }
+
+ int keyLength = key.length;
+ // ensure that keyLength is valid for the chosen underlying cipher
+ boolean ok = false;
+ for (Iterator it = cipher.keySizes(); it.hasNext();)
+ {
+ ok = (keyLength == ((Integer) it.next()).intValue());
+ if (ok)
+ {
+ break;
+ }
+ }
+ if (!ok)
+ {
+ throw new IllegalArgumentException("key length");
+ }
+
+ // ensure that remaining params make sense
+ int index = -1;
+ Integer i = (Integer) attributes.get(INDEX);
+ if (i != null)
+ {
+ index = i.intValue();
+ if (index < 0 || index > 255)
+ {
+ throw new IllegalArgumentException(INDEX);
+ }
+ }
+
+ // now initialise the underlying cipher
+ Map map = new HashMap();
+ if (cipherBlockSize != 0)
+ { // only needed if new or changed
+ map.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(cipherBlockSize));
+ }
+ map.put(IBlockCipher.KEY_MATERIAL, key);
+ try
+ {
+ cipher.init(map);
+ }
+ catch (InvalidKeyException x)
+ {
+ throw new IllegalArgumentException(IBlockCipher.KEY_MATERIAL);
+ }
+
+ buffer = new byte[cipher.currentBlockSize()];
+ buffer[cipher.currentBlockSize() - 1] = (byte) index;
+ try
+ {
+ fillBlock();
+ }
+ catch (LimitReachedException impossible)
+ {
+ }
+ }
+
+ public void fillBlock() throws LimitReachedException
+ {
+ cipher.encryptBlock(buffer, 0, buffer, 0);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/AuthInfo.java b/gnu/javax/crypto/sasl/AuthInfo.java
new file mode 100644
index 000000000..1e942559d
--- /dev/null
+++ b/gnu/javax/crypto/sasl/AuthInfo.java
@@ -0,0 +1,143 @@
+/* AuthInfo.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.Registry;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+/**
+ * A static class for creating {@link IAuthInfoProvider} providers. It
+ * transparently locates and uses any provider instances, based on the value
+ * assigned to the System property with the key
+ * <code>gnu.crypto.sasl.auth.info.provider.pkgs</code>. If more than one is
+ * specified they SHOULD be separated with a vertical bar character. Please note
+ * that the GNU provider is always added last to the list, disregarding whether
+ * it was mentioned or not in the value of that property, or if it that property
+ * was not defined.
+ */
+public class AuthInfo
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final ArrayList factories = new ArrayList();
+ static
+ {
+ IAuthInfoProviderFactory ours = new AuthInfoProviderFactory();
+ // if SASL_AUTH_INFO_PROVIDER_PKGS is defined then parse it
+ String clazz;
+ String pkgs = System.getProperty(Registry.SASL_AUTH_INFO_PROVIDER_PKGS,
+ null);
+ if (pkgs != null)
+ {
+ for (StringTokenizer st = new StringTokenizer(pkgs, "|"); st.hasMoreTokens();)
+ {
+ clazz = st.nextToken();
+ if (!"gnu.crypto.sasl".equals(clazz))
+ {
+ clazz += ".AuthInfoProviderFactory";
+ try
+ {
+ IAuthInfoProviderFactory factory = (IAuthInfoProviderFactory) Class.forName(
+ clazz).newInstance();
+ factories.add(factory);
+ }
+ catch (ClassCastException ignored)
+ {
+ }
+ catch (ClassNotFoundException ignored)
+ {
+ }
+ catch (InstantiationException ignored)
+ {
+ }
+ catch (IllegalAccessException ignored)
+ {
+ }
+ }
+ }
+ }
+ // always add ours last; unless it's already there
+ if (!factories.contains(ours))
+ {
+ factories.add(ours);
+ }
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private AuthInfo()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * A convenience method to return the authentication information provider
+ * for a designated SASL mechnanism. It goes through all the installed
+ * provider factories, one at a time, and attempts to return a new instance
+ * of the provider for the designated mechanism. It stops at the first
+ * factory returning a non-null provider.
+ *
+ * @param mechanism the name of a SASL mechanism.
+ * @return an implementation that provides {@link IAuthInfoProvider} for that
+ * mechanism; or <code>null</code> if none found.
+ */
+ public static IAuthInfoProvider getProvider(String mechanism)
+ {
+ for (Iterator it = factories.iterator(); it.hasNext();)
+ {
+ IAuthInfoProviderFactory factory = (IAuthInfoProviderFactory) it.next();
+ IAuthInfoProvider result = factory.getInstance(mechanism);
+ if (result != null)
+ {
+ return result;
+ }
+ }
+ return null;
+ }
+}
diff --git a/gnu/javax/crypto/sasl/AuthInfoProviderFactory.java b/gnu/javax/crypto/sasl/AuthInfoProviderFactory.java
new file mode 100644
index 000000000..6ba5fc562
--- /dev/null
+++ b/gnu/javax/crypto/sasl/AuthInfoProviderFactory.java
@@ -0,0 +1,89 @@
+/* AuthInfoProviderFactory.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.crammd5.CramMD5AuthInfoProvider;
+import gnu.javax.crypto.sasl.plain.PlainAuthInfoProvider;
+import gnu.javax.crypto.sasl.srp.SRPAuthInfoProvider;
+
+/**
+ * The concrete SASL authentication information provider factory.
+ */
+public class AuthInfoProviderFactory implements IAuthInfoProviderFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-args constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IAuthInfoProviderFactory interface implementation -----------------------
+
+ public IAuthInfoProvider getInstance(String mechanism)
+ {
+ if (mechanism == null)
+ {
+ return null;
+ }
+ mechanism = mechanism.trim().toUpperCase();
+ if (mechanism.startsWith(Registry.SASL_SRP_MECHANISM))
+ {
+ return new SRPAuthInfoProvider();
+ }
+ if (mechanism.equals(Registry.SASL_CRAM_MD5_MECHANISM))
+ {
+ return new CramMD5AuthInfoProvider();
+ }
+ if (mechanism.equals(Registry.SASL_PLAIN_MECHANISM))
+ {
+ return new PlainAuthInfoProvider();
+ }
+ return null;
+ }
+}
diff --git a/gnu/javax/crypto/sasl/ClientFactory.java b/gnu/javax/crypto/sasl/ClientFactory.java
new file mode 100644
index 000000000..ef184632c
--- /dev/null
+++ b/gnu/javax/crypto/sasl/ClientFactory.java
@@ -0,0 +1,210 @@
+/* ClientFactory.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.anonymous.AnonymousClient;
+import gnu.javax.crypto.sasl.crammd5.CramMD5Client;
+import gnu.javax.crypto.sasl.plain.PlainClient;
+import gnu.javax.crypto.sasl.srp.SRPClient;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashMap;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslClientFactory;
+import javax.security.sasl.SaslException;
+
+/**
+ * The implementation of {@link SaslClientFactory}.
+ */
+public class ClientFactory implements SaslClientFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final Set getNames()
+ {
+ return Collections.unmodifiableSet(new HashSet(
+ Arrays.asList(getNamesInternal(null))));
+ }
+
+ private static final String[] getNamesInternal(Map props)
+ {
+ String[] all = new String[] { Registry.SASL_SRP_MECHANISM,
+ Registry.SASL_CRAM_MD5_MECHANISM,
+ Registry.SASL_PLAIN_MECHANISM,
+ Registry.SASL_ANONYMOUS_MECHANISM };
+
+ if (props == null)
+ {
+ return all;
+ }
+ if (hasPolicy(Sasl.POLICY_PASS_CREDENTIALS, props))
+ {
+ return new String[0];
+ }
+
+ List result = new ArrayList(all.length);
+ ;
+ for (int i = 0; i < all.length;)
+ {
+ result.add(all[i++]);
+ }
+
+ if (hasPolicy(Sasl.POLICY_NOPLAINTEXT, props))
+ {
+ result.remove(Registry.SASL_PLAIN_MECHANISM);
+ }
+ if (hasPolicy(Sasl.POLICY_NOACTIVE, props))
+ {
+ result.remove(Registry.SASL_CRAM_MD5_MECHANISM);
+ result.remove(Registry.SASL_PLAIN_MECHANISM);
+ }
+ if (hasPolicy(Sasl.POLICY_NODICTIONARY, props))
+ {
+ result.remove(Registry.SASL_CRAM_MD5_MECHANISM);
+ result.remove(Registry.SASL_PLAIN_MECHANISM);
+ }
+ if (hasPolicy(Sasl.POLICY_NOANONYMOUS, props))
+ {
+ result.remove(Registry.SASL_ANONYMOUS_MECHANISM);
+ }
+ if (hasPolicy(Sasl.POLICY_FORWARD_SECRECY, props))
+ {
+ result.remove(Registry.SASL_CRAM_MD5_MECHANISM);
+ result.remove(Registry.SASL_ANONYMOUS_MECHANISM);
+ result.remove(Registry.SASL_PLAIN_MECHANISM);
+ }
+ return (String[]) result.toArray(new String[0]);
+ }
+
+ public static final ClientMechanism getInstance(String mechanism)
+ {
+ if (mechanism == null)
+ {
+ return null;
+ }
+ mechanism = mechanism.trim().toUpperCase();
+ if (mechanism.equals(Registry.SASL_SRP_MECHANISM))
+ {
+ return new SRPClient();
+ }
+ if (mechanism.equals(Registry.SASL_CRAM_MD5_MECHANISM))
+ {
+ return new CramMD5Client();
+ }
+ if (mechanism.equals(Registry.SASL_PLAIN_MECHANISM))
+ {
+ return new PlainClient();
+ }
+ if (mechanism.equals(Registry.SASL_ANONYMOUS_MECHANISM))
+ {
+ return new AnonymousClient();
+ }
+ return null;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public SaslClient createSaslClient(String[] mechanisms,
+ String authorisationID, String protocol,
+ String serverName, Map props,
+ CallbackHandler cbh) throws SaslException
+ {
+ ClientMechanism result = null;
+ String mechanism;
+ for (int i = 0; i < mechanisms.length; i++)
+ {
+ mechanism = mechanisms[i];
+ result = getInstance(mechanism);
+ if (result != null)
+ {
+ break;
+ }
+ }
+
+ if (result != null)
+ {
+ HashMap attributes = new HashMap();
+ if (props != null)
+ {
+ attributes.putAll(props);
+ }
+ attributes.put(Registry.SASL_AUTHORISATION_ID, authorisationID);
+ attributes.put(Registry.SASL_PROTOCOL, protocol);
+ attributes.put(Registry.SASL_SERVER_NAME, serverName);
+ attributes.put(Registry.SASL_CALLBACK_HANDLER, cbh);
+
+ result.init(attributes);
+ return result;
+ }
+
+ throw new SaslException(
+ "No supported mechanism found in given mechanism list");
+ }
+
+ public String[] getMechanismNames(Map props)
+ {
+ return getNamesInternal(props);
+ }
+
+ private static boolean hasPolicy(String propertyName, Map props)
+ {
+ return "true".equalsIgnoreCase(String.valueOf(props.get(propertyName)));
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/ClientMechanism.java b/gnu/javax/crypto/sasl/ClientMechanism.java
new file mode 100644
index 000000000..45873ae6b
--- /dev/null
+++ b/gnu/javax/crypto/sasl/ClientMechanism.java
@@ -0,0 +1,365 @@
+/* ClientMechanism.java --
+ Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.Registry;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+/**
+ * <p>A base class to facilitate implementing SASL client-side mechanisms.</p>
+ */
+public abstract class ClientMechanism implements SaslClient
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Name of this mechanism. */
+ protected String mechanism;
+
+ /** The authorisation identity. */
+ protected String authorizationID;
+
+ /** Name of protocol using this mechanism. */
+ protected String protocol;
+
+ /** Name of server to authenticate to. */
+ protected String serverName;
+
+ /** Properties of qualities desired for this mechanism. */
+ protected Map properties;
+
+ /** Callback handler to use with this mechanism instance. */
+ protected CallbackHandler handler;
+
+ /** Channel binding data to use with this mechanism instance. */
+ protected byte[] channelBinding;
+
+ /** Whether authentication phase is completed (true) or not (false). */
+ protected boolean complete = false;
+
+ /** The state of the authentication automaton. */
+ protected int state = -1;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected ClientMechanism(final String mechanism)
+ {
+ super();
+
+ this.mechanism = mechanism;
+ this.state = -1;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods to be implemented by concrete subclasses ---------------
+
+ protected abstract void initMechanism() throws SaslException;
+
+ protected abstract void resetMechanism() throws SaslException;
+
+ // javax.security.sasl.SaslClient interface implementation -----------------
+
+ public abstract byte[] evaluateChallenge(byte[] challenge)
+ throws SaslException;
+
+ public abstract boolean hasInitialResponse();
+
+ public boolean isComplete()
+ {
+ return complete;
+ }
+
+ public byte[] unwrap(final byte[] incoming, final int offset, final int len)
+ throws SaslException
+ {
+ if (!isComplete())
+ {
+ throw new IllegalMechanismStateException();
+ }
+ return this.engineUnwrap(incoming, offset, len);
+ }
+
+ public byte[] wrap(final byte[] outgoing, final int offset, final int len)
+ throws SaslException
+ {
+ if (!isComplete())
+ {
+ throw new IllegalMechanismStateException();
+ }
+ return this.engineWrap(outgoing, offset, len);
+ }
+
+ public String getMechanismName()
+ {
+ return mechanism;
+ }
+
+ public Object getNegotiatedProperty(final String propName)
+ {
+ if (!isComplete())
+ {
+ throw new IllegalStateException();
+ }
+ if (Sasl.QOP.equals(propName))
+ {
+ return getNegotiatedQOP();
+ }
+ if (Sasl.STRENGTH.equals(propName))
+ {
+ return getNegotiatedStrength();
+ }
+ if (Sasl.SERVER_AUTH.equals(propName))
+ {
+ return getNegotiatedServerAuth();
+ }
+ if (Sasl.MAX_BUFFER.equals(propName))
+ {
+ return getNegotiatedMaxBuffer();
+ }
+ if (Sasl.RAW_SEND_SIZE.equals(propName))
+ {
+ return getNegotiatedRawSendSize();
+ }
+ if (Sasl.POLICY_NOPLAINTEXT.equals(propName))
+ {
+ return getNegotiatedPolicyNoPlainText();
+ }
+ if (Sasl.POLICY_NOACTIVE.equals(propName))
+ {
+ return getNegotiatedPolicyNoActive();
+ }
+ if (Sasl.POLICY_NODICTIONARY.equals(propName))
+ {
+ return getNegotiatedPolicyNoDictionary();
+ }
+ if (Sasl.POLICY_NOANONYMOUS.equals(propName))
+ {
+ return getNegotiatedPolicyNoAnonymous();
+ }
+ if (Sasl.POLICY_FORWARD_SECRECY.equals(propName))
+ {
+ return getNegotiatedPolicyForwardSecrecy();
+ }
+ if (Sasl.POLICY_PASS_CREDENTIALS.equals(propName))
+ {
+ return getNegotiatedPolicyPassCredentials();
+ }
+ if (Sasl.REUSE.equals(propName))
+ {
+ return getReuse();
+ }
+ return null;
+ }
+
+ public void dispose() throws SaslException
+ {
+ }
+
+ // other Instance methods --------------------------------------------------
+
+ public String getAuthorizationID()
+ {
+ return authorizationID;
+ }
+
+ protected String getNegotiatedQOP()
+ {
+ return Registry.QOP_AUTH;
+ }
+
+ protected String getNegotiatedStrength()
+ {
+ return Registry.STRENGTH_LOW;
+ }
+
+ protected String getNegotiatedServerAuth()
+ {
+ return Registry.SERVER_AUTH_FALSE;
+ }
+
+ protected String getNegotiatedMaxBuffer()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedRawSendSize()
+ {
+ return String.valueOf(Registry.SASL_BUFFER_MAX_LIMIT);
+ }
+
+ protected String getNegotiatedPolicyNoPlainText()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyNoActive()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyNoDictionary()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyNoAnonymous()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyForwardSecrecy()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyPassCredentials()
+ {
+ return null;
+ }
+
+ protected String getReuse()
+ {
+ return Registry.REUSE_FALSE;
+ }
+
+ protected byte[] engineUnwrap(final byte[] incoming, final int offset,
+ final int len) throws SaslException
+ {
+ final byte[] result = new byte[len];
+ System.arraycopy(incoming, offset, result, 0, len);
+ return result;
+ }
+
+ protected byte[] engineWrap(final byte[] outgoing, final int offset,
+ final int len) throws SaslException
+ {
+ final byte[] result = new byte[len];
+ System.arraycopy(outgoing, offset, result, 0, len);
+ return result;
+ }
+
+ /**
+ * <p>Initialises the mechanism with designated attributes. Permissible names
+ * and values are mechanism specific.</p>
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalMechanismStateException if the instance is already
+ * initialised.
+ * @throws SaslException if an exception occurs during the process.
+ */
+ public void init(final Map attributes) throws SaslException
+ {
+ if (state != -1)
+ {
+ throw new IllegalMechanismStateException("init()");
+ }
+
+ if (properties == null)
+ {
+ properties = new HashMap();
+ }
+ else
+ {
+ properties.clear();
+ }
+ if (attributes != null)
+ {
+ authorizationID = (String) attributes.get(Registry.SASL_AUTHORISATION_ID);
+ protocol = (String) attributes.get(Registry.SASL_PROTOCOL);
+ serverName = (String) attributes.get(Registry.SASL_SERVER_NAME);
+ handler = (CallbackHandler) attributes.get(Registry.SASL_CALLBACK_HANDLER);
+ channelBinding = (byte[]) attributes.get(Registry.SASL_CHANNEL_BINDING);
+ properties.putAll(attributes);
+ }
+ else
+ {
+ handler = null;
+ }
+
+ if (authorizationID == null)
+ {
+ authorizationID = "";
+ }
+ if (protocol == null)
+ {
+ protocol = "";
+ }
+ if (serverName == null)
+ {
+ serverName = "";
+ }
+ if (channelBinding == null)
+ {
+ channelBinding = new byte[0];
+ }
+ initMechanism();
+ complete = false;
+ state = 0;
+ }
+
+ /**
+ * <p>Resets the mechanism instance for re-initialisation and use with other
+ * characteristics.</p>
+ *
+ * @throws SaslException if an exception occurs during the process.
+ */
+ public void reset() throws SaslException
+ {
+ resetMechanism();
+ properties.clear();
+ authorizationID = protocol = serverName = null;
+ channelBinding = null;
+ complete = false;
+ state = -1;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/ConfidentialityException.java b/gnu/javax/crypto/sasl/ConfidentialityException.java
new file mode 100644
index 000000000..561827d8d
--- /dev/null
+++ b/gnu/javax/crypto/sasl/ConfidentialityException.java
@@ -0,0 +1,84 @@
+/* ConfidentialityException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import javax.security.sasl.SaslException;
+
+/**
+ * Used by mechanisms that offer a security services layer, this checked
+ * exception is thrown to indicate that a violation has occured during the
+ * processing of a <i>confidentiality</i> protection filter.
+ *
+ * @version $Revision: 1.1 $
+ */
+public class ConfidentialityException extends SaslException
+{
+
+ /**
+ * Constructs a new instance of <code>ConfidentialityException</code> with no
+ * detail message.
+ */
+ public ConfidentialityException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of <code>ConfidentialityException</code> with
+ * the specified detail message.
+ *
+ * @param s the detail message.
+ */
+ public ConfidentialityException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Constructs a new instance of <code>ConfidentialityException</code> with a
+ * detailed message and a root exception.
+ *
+ * @param s possibly null additional detail about the exception.
+ * @param x a possibly null root exception that caused this one.
+ */
+ public ConfidentialityException(String s, Throwable x)
+ {
+ super(s, x);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/IAuthInfoProvider.java b/gnu/javax/crypto/sasl/IAuthInfoProvider.java
new file mode 100644
index 000000000..2b913a137
--- /dev/null
+++ b/gnu/javax/crypto/sasl/IAuthInfoProvider.java
@@ -0,0 +1,117 @@
+/* IAuthInfoProvider.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import java.util.Map;
+
+import javax.security.sasl.AuthenticationException;
+
+/**
+ * The visible methods of any authentication information provider.
+ */
+public interface IAuthInfoProvider
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Activates (initialises) this provider instance. SHOULD be the first method
+ * invoked on the provider.
+ *
+ * @param context a collection of name-value bindings describing the
+ * activation context.
+ * @throws AuthenticationException if an exception occurs during the operation.
+ */
+ void activate(Map context) throws AuthenticationException;
+
+ /**
+ * Passivates (releases) this provider instance. SHOULD be the last method
+ * invoked on the provider. Once it is done, no other method may be invoked
+ * on the same instance before it is <i>activated</i> agains.
+ *
+ * @throws AuthenticationException if an exception occurs during the operation.
+ */
+ void passivate() throws AuthenticationException;
+
+ /**
+ * Checks if a user with a designated name is known to this provider.
+ *
+ * @param userName the name of a user to check.
+ * @return <code>true</code> if the user with the designated name is known to
+ * this provider; <code>false</code> otherwise.
+ * @throws AuthenticationException if an exception occurs during the operation.
+ */
+ boolean contains(String userName) throws AuthenticationException;
+
+ /**
+ * Returns a collection of information about a designated user. The contents
+ * of the returned map is provider-specific of name-to-value mappings.
+ *
+ * @param userID a map of name-to-value bindings that fully describe a user.
+ * @return a collection of information about the designated user.
+ * @throws AuthenticationException if an exception occurs during the operation.
+ */
+ Map lookup(Map userID) throws AuthenticationException;
+
+ /**
+ * Updates the credentials of a designated user.
+ *
+ * @param userCredentials a map of name-to-value bindings that fully describe
+ * a user, including per new credentials.
+ * @throws AuthenticationException if an exception occurs during the operation.
+ */
+ void update(Map userCredentials) throws AuthenticationException;
+
+ /**
+ * A provider may operate in more than mode; e.g. SRP-II caters for user
+ * credentials computed in more than one message digest algorithm. This
+ * method returns the set of name-to-value bindings describing the mode of
+ * the provider.
+ *
+ * @param mode a unique identifier describing the operational mode.
+ * @return a collection of name-to-value bindings describing the designated
+ * mode.
+ * @throws AuthenticationException if an exception occurs during the operation.
+ */
+ Map getConfiguration(String mode) throws AuthenticationException;
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java b/gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java
new file mode 100644
index 000000000..e630b8da1
--- /dev/null
+++ b/gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java
@@ -0,0 +1,62 @@
+/* IAuthInfoProviderFactory.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+/**
+ * The visible method of every authentication information provider factory.
+ */
+public interface IAuthInfoProviderFactory
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns an implementation of a provider for a designated mechanism
+ * capable of honouring {@link IAuthInfoProvider} requests.
+ *
+ * @param mechanism the unique name of a mechanism.
+ * @return an implementation of {@link IAuthInfoProvider} for that mechanism
+ * or <code>null</code> if none found.
+ */
+ IAuthInfoProvider getInstance(String mechanism);
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/IllegalMechanismStateException.java b/gnu/javax/crypto/sasl/IllegalMechanismStateException.java
new file mode 100644
index 000000000..94d9269a1
--- /dev/null
+++ b/gnu/javax/crypto/sasl/IllegalMechanismStateException.java
@@ -0,0 +1,86 @@
+/* IllegalMechanismStateException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import javax.security.sasl.AuthenticationException;
+
+/**
+ * A checked exception thrown to indicate that an operation that should be
+ * invoked on a completed mechanism was invoked but the authentication phase of
+ * that mechanism was not completed yet, or that an operation that should be
+ * invoked on incomplete mechanisms was invoked but the authentication phase of
+ * that mechanism was already completed.
+ *
+ * @version $Revision: 1.1 $
+ */
+public class IllegalMechanismStateException extends AuthenticationException
+{
+
+ /**
+ * Constructs a new instance of <code>IllegalMechanismStateException</code>
+ * with no detail message.
+ */
+ public IllegalMechanismStateException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of <code>IllegalMechanismStateException</code>
+ * with the specified detail message.
+ *
+ * @param detail the detail message.
+ */
+ public IllegalMechanismStateException(String detail)
+ {
+ super(detail);
+ }
+
+ /**
+ * Constructs a new instance of <code>IllegalMechanismStateException</code>
+ * with the specified detail message, and cause.
+ *
+ * @param detail the detail message.
+ * @param ex the original cause.
+ */
+ public IllegalMechanismStateException(String detail, Throwable ex)
+ {
+ super(detail, ex);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/InputBuffer.java b/gnu/javax/crypto/sasl/InputBuffer.java
new file mode 100644
index 000000000..a64ea3e0e
--- /dev/null
+++ b/gnu/javax/crypto/sasl/InputBuffer.java
@@ -0,0 +1,339 @@
+/* InputBuffer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.Registry;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+/**
+ * <p>The implementation of an incoming SASL buffer.</p>
+ *
+ * <p>The data elements this class caters for are described in [1].</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
+ * Secure Remote Password Authentication Mechanism</a>;<br/>
+ * draft-burdis-cat-srp-sasl-09,<br/>
+ * <a href="mailto:keith@rucus.ru.ac.za">Keith Burdis</a> and
+ * <a href="mailto:raif@forge.com.au">Ra&iuml;f S. Naffah</a>.</li>
+ * </ol>
+ */
+public class InputBuffer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The internal buffer stream containing the buffer's contents. */
+ protected ByteArrayInputStream in;
+
+ /** The length of the buffer, according to its header. */
+ protected int length;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Constructs a SASL buffer given the buffer's encoded form, including its
+ * header bytes.</p>
+ *
+ * @param frame the encoded form, including the header bytes, of a SASL buffer.
+ * @throws SaslEncodingException if the buffer is malformed.
+ */
+ public InputBuffer(byte[] frame) throws SaslEncodingException
+ {
+ this();
+
+ if (frame.length < 4)
+ {
+ throw new SaslEncodingException("SASL buffer header too short");
+ }
+
+ length = (frame[0] & 0xFF) << 24 | (frame[1] & 0xFF) << 16
+ | (frame[2] & 0xFF) << 8 | (frame[3] & 0xFF);
+ if (length > Registry.SASL_BUFFER_MAX_LIMIT || length < 0)
+ {
+ throw new SaslEncodingException("SASL buffer size limit exceeded");
+ }
+
+ in = new ByteArrayInputStream(frame, 4, length);
+ }
+
+ /** Trivial private constructor for use by the class method. */
+ private InputBuffer()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a SASL buffer given the buffer's encoded contents,
+ * excluding the buffer's header bytes.</p>
+ *
+ * <p>Calls the method with the same name and three arguments as:
+ * <code>getInstance(raw, 0, raw.length)</code>.
+ *
+ * @param raw the encoded form, excluding the header bytes, of a SASL buffer.
+ * @return a new instance of {@link InputBuffer}.
+ */
+ public static InputBuffer getInstance(byte[] raw)
+ {
+ return getInstance(raw, 0, raw.length);
+ }
+
+ /**
+ * <p>Returns an instance of a SASL buffer given the buffer's encoded
+ * contents, excluding the buffer's header bytes.</p>
+ *
+ * @param raw the encoded form, excluding the header bytes, of a SASL buffer.
+ * @param offset offset where to start using raw bytes from.
+ * @param len number of bytes to use.
+ * @return a new instance of {@link InputBuffer}.
+ */
+ public static InputBuffer getInstance(byte[] raw, int offset, int len)
+ {
+ InputBuffer result = new InputBuffer();
+ result.in = new ByteArrayInputStream(raw, offset, len);
+ return result;
+ }
+
+ /**
+ * <p>Converts four octets into the number that they represent.</p>
+ *
+ * @param b the four octets.
+ * @return the length.
+ */
+ // public static int fourBytesToLength(byte[] b) throws SaslEncodingException {
+ // int result = b[0] << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8 | (b[3] & 0xFF);
+ // if (result > Registry.SASL_FOUR_BYTE_MAX_LIMIT || result < 0) {
+ // throw new SaslEncodingException("SASL EOS size limit exceeded");
+ // }
+ // return result;
+ // }
+ /**
+ * <p>Converts two octets into the number that they represent.</p>
+ *
+ * @param b the two octets.
+ * @return the length.
+ */
+ public static int twoBytesToLength(byte[] b) throws SaslEncodingException
+ {
+ final int result = (b[0] & 0xFF) << 8 | (b[1] & 0xFF);
+ if (result > Registry.SASL_TWO_BYTE_MAX_LIMIT)
+ {
+ throw new SaslEncodingException("SASL MPI/Text size limit exceeded");
+ }
+ return result;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public boolean hasMoreElements()
+ {
+ return (in.available() > 0);
+ }
+
+ /**
+ * <p>Decodes a SASL scalar quantity, <code>count</code>-octet long, from the
+ * current buffer.</p>
+ *
+ * @param count the number of octets of this scalar quantity.
+ * @return a native representation of a SASL scalar (unsigned integer) quantity.
+ * @throws SaslEncodingException if an encoding exception occurs during the
+ * operation.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public long getScalar(int count) throws IOException
+ {
+ if (count < 0 || count > 4)
+ {
+ throw new SaslEncodingException("Invalid SASL scalar octet count: "
+ + String.valueOf(count));
+ }
+ if (!hasMoreElements())
+ {
+ throw new SaslEncodingException(
+ "Not enough bytes for a scalar in buffer");
+ }
+ if (in.available() < count)
+ {
+ throw new SaslEncodingException("Illegal SASL scalar encoding");
+ }
+ byte[] element = new byte[count];
+ in.read(element);
+
+ long result = 0L;
+ for (int i = 0; i < count; i++)
+ {
+ result <<= 8;
+ result |= element[i] & 0xFFL;
+ }
+ return result;
+ }
+
+ /**
+ * <p>Decodes a SASL OS from the current buffer.</p>
+ *
+ * @return a native representation of a SASL OS.
+ * @throws SaslEncodingException if an encoding exception occurs during the
+ * operation.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public byte[] getOS() throws IOException
+ {
+ if (!hasMoreElements())
+ {
+ throw new SaslEncodingException(
+ "Not enough bytes for an octet-sequence in buffer");
+ }
+ final int elementLength = in.read();
+ if (elementLength > Registry.SASL_ONE_BYTE_MAX_LIMIT)
+ {
+ throw new SaslEncodingException(
+ "SASL octet-sequence size limit exceeded");
+ }
+
+ if (in.available() < elementLength)
+ {
+ throw new SaslEncodingException("Illegal SASL octet-sequence encoding");
+ }
+
+ byte[] result = new byte[elementLength];
+ in.read(result);
+
+ return result;
+ }
+
+ /**
+ * <p>Decodes a SASL EOS from the current buffer.</p>
+ *
+ * @return a native representation of a SASL EOS.
+ * @throws SaslEncodingException if an encoding exception occurs during the
+ * operation.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public byte[] getEOS() throws IOException
+ {
+ if (in.available() < 2)
+ {
+ throw new SaslEncodingException(
+ "Not enough bytes for an extended octet-sequence in buffer");
+ }
+
+ byte[] elementLengthBytes = new byte[2];
+ in.read(elementLengthBytes);
+ final int elementLength = twoBytesToLength(elementLengthBytes);
+ if (in.available() < elementLength)
+ {
+ throw new SaslEncodingException(
+ "Illegal SASL extended octet-sequence encoding");
+ }
+
+ byte[] result = new byte[elementLength];
+ in.read(result);
+
+ return result;
+ }
+
+ /**
+ * <p>Decodes a SASL MPI from the current buffer.</p>
+ *
+ * @return a native representation of a SASL MPI.
+ * @throws SaslEncodingException if an encoding exception occurs during the
+ * operation.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public BigInteger getMPI() throws IOException
+ {
+ if (in.available() < 2)
+ {
+ throw new SaslEncodingException("Not enough bytes for an MPI in buffer");
+ }
+ byte[] elementLengthBytes = new byte[2];
+ in.read(elementLengthBytes);
+ final int elementLength = twoBytesToLength(elementLengthBytes);
+ if (in.available() < elementLength)
+ {
+ throw new SaslEncodingException(
+ "Illegal SASL multi-precision integer encoding");
+ }
+
+ byte[] element = new byte[elementLength];
+ in.read(element);
+
+ return new BigInteger(1, element);
+ }
+
+ /**
+ * <p>Decodes a SASL Text from the current buffer.</p>
+ *
+ * @return a native representation of a SASL Text.
+ * @throws SaslEncodingException if an encoding exception occurs during the
+ * operation.
+ * @throws SaslEncodingException if the UTF-8 character encoding is not
+ * supported on this platform.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public String getText() throws IOException
+ {
+ if (in.available() < 2)
+ {
+ throw new SaslEncodingException("Not enough bytes for a text in buffer");
+ }
+ byte[] elementLengthBytes = new byte[2];
+ in.read(elementLengthBytes);
+ final int elementLength = twoBytesToLength(elementLengthBytes);
+ if (in.available() < elementLength)
+ {
+ throw new SaslEncodingException("Illegal SASL text encoding");
+ }
+
+ byte[] element = new byte[elementLength];
+ in.read(element);
+
+ return new String(element, "UTF8");
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/IntegrityException.java b/gnu/javax/crypto/sasl/IntegrityException.java
new file mode 100644
index 000000000..4a56ca2d5
--- /dev/null
+++ b/gnu/javax/crypto/sasl/IntegrityException.java
@@ -0,0 +1,83 @@
+/* IntegrityException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import javax.security.sasl.SaslException;
+
+/**
+ * Used by mechanisms that offer a security services layer, this checked
+ * exception is thrown to indicate that a violation has occured during the
+ * processing of an <i>integrity</i> protection filter, including <i>replay
+ * detection</i>.
+ */
+public class IntegrityException extends SaslException
+{
+
+ /**
+ * Constructs a new instance of <code>IntegrityException</code> with no
+ * detail message.
+ */
+ public IntegrityException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of <code>IntegrityException</code> with the
+ * specified detail message.
+ *
+ * @param s the detail message.
+ */
+ public IntegrityException(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Constructs a new instance of <code>IntegrityException</code> with a
+ * detailed message and a root exception.
+ *
+ * @param s possibly null additional detail about the exception.
+ * @param x a possibly null root exception that caused this one.
+ */
+ public IntegrityException(String s, Throwable x)
+ {
+ super(s, x);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/NoSuchMechanismException.java b/gnu/javax/crypto/sasl/NoSuchMechanismException.java
new file mode 100644
index 000000000..65432082a
--- /dev/null
+++ b/gnu/javax/crypto/sasl/NoSuchMechanismException.java
@@ -0,0 +1,62 @@
+/* NoSuchMechanismException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import javax.security.sasl.SaslException;
+
+/**
+ * A checked exception thrown to indicate that a designated SASL mechanism
+ * implementation was not found.
+ */
+public class NoSuchMechanismException extends SaslException
+{
+
+ /**
+ * Constructs a <code>NoSuchMechanismException</code> with the specified
+ * detail message. In the case of this exception, the detail message
+ * designates the offending mechanism name.
+ *
+ * @param arg the detail message, which in this case is the offending
+ * mechanism name.
+ */
+ public NoSuchMechanismException(String arg)
+ {
+ super(arg);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/NoSuchUserException.java b/gnu/javax/crypto/sasl/NoSuchUserException.java
new file mode 100644
index 000000000..fe362c742
--- /dev/null
+++ b/gnu/javax/crypto/sasl/NoSuchUserException.java
@@ -0,0 +1,67 @@
+/* NoSuchUserException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import javax.security.sasl.AuthenticationException;
+
+/**
+ * A checked exception thrown to indicate that a designated user is unknown to
+ * the authentication layer.
+ */
+public class NoSuchUserException extends AuthenticationException
+{
+
+ /** Constructs a <code>NoSuchUserException</code> with no detail message. */
+ public NoSuchUserException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a <code>NoSuchUserException</code> with the specified detail
+ * message. In the case of this exception, the detail message designates
+ * the offending username.
+ *
+ * @param arg the detail message, which in this case is the username.
+ */
+ public NoSuchUserException(String arg)
+ {
+ super(arg);
+ }
+}
diff --git a/gnu/javax/crypto/sasl/OutputBuffer.java b/gnu/javax/crypto/sasl/OutputBuffer.java
new file mode 100644
index 000000000..d219e7e9f
--- /dev/null
+++ b/gnu/javax/crypto/sasl/OutputBuffer.java
@@ -0,0 +1,225 @@
+/* OutputBuffer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+/**
+ * <p>The implementation of an outgoing SASL buffer.</p>
+ *
+ * <p>The data elements this class caters for are described in [1].</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
+ * Secure Remote Password Authentication Mechanism</a>;<br/>
+ * draft-burdis-cat-srp-sasl-09,<br/>
+ * <a href="mailto:keith@rucus.ru.ac.za">Keith Burdis</a> and
+ * <a href="mailto:raif@forge.com.au">Ra&iuml;f S. Naffah</a>.</li>
+ * </ol>
+ */
+public class OutputBuffer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The internal output stream. */
+ private ByteArrayOutputStream out;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public OutputBuffer()
+ {
+ super();
+
+ out = new ByteArrayOutputStream();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Encodes a SASL scalar quantity, <code>count</code>-octet long, to the
+ * current buffer.</p>
+ *
+ * @param count number of octets to encode <code>b</code> with.
+ * @param b the scalar quantity.
+ * @throws SaslEncodingException if an encoding size constraint is violated.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public void setScalar(int count, int b) throws IOException
+ {
+ if (count < 0 || count > 4)
+ {
+ throw new SaslEncodingException("Invalid SASL scalar octet count: "
+ + String.valueOf(count));
+ }
+ byte[] element = new byte[count];
+ for (int i = count; --i >= 0; b >>>= 8)
+ {
+ element[i] = (byte) b;
+ }
+ out.write(element);
+ }
+
+ /**
+ * <p>Encodes a SASL OS to the current buffer.</p>
+ *
+ * @param b the OS element.
+ * @throws SaslEncodingException if an encoding size constraint is violated.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public void setOS(byte[] b) throws IOException
+ {
+ final int length = b.length;
+ if (length > Registry.SASL_ONE_BYTE_MAX_LIMIT)
+ {
+ throw new SaslEncodingException("SASL octet-sequence too long");
+ }
+ out.write(length & 0xFF);
+ out.write(b);
+ }
+
+ /**
+ * <p>Encodes a SASL EOS to the current buffer.</p>
+ *
+ * @param b the EOS element.
+ * @throws SaslEncodingException if an encoding size constraint is violated.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public void setEOS(byte[] b) throws IOException
+ {
+ final int length = b.length;
+ if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
+ {
+ throw new SaslEncodingException("SASL extended octet-sequence too long");
+ }
+ byte[] lengthBytes = { (byte) (length >>> 8), (byte) length };
+ out.write(lengthBytes);
+ out.write(b);
+ }
+
+ /**
+ * <p>Encodes a SASL MPI to the current buffer.</p>
+ *
+ * @param val the MPI element.
+ * @throws SaslEncodingException if an encoding size constraint is violated.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public void setMPI(BigInteger val) throws IOException
+ {
+ byte[] b = Util.trim(val);
+ final int length = b.length;
+ if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
+ {
+ throw new SaslEncodingException("SASL multi-precision integer too long");
+ }
+ byte[] lengthBytes = { (byte) (length >>> 8), (byte) length };
+ out.write(lengthBytes);
+ out.write(b);
+ }
+
+ /**
+ * <p>Encodes a SASL Text to the current buffer.</p>
+ *
+ * @param str the Text element.
+ * @throws SaslEncodingException if an encoding size constraint is violated.
+ * @throws SaslEncodingException if the UTF-8 encoding is not supported on
+ * this platform.
+ * @throws IOException if any other I/O exception occurs during the operation.
+ */
+ public void setText(String str) throws IOException
+ {
+ byte[] b = str.getBytes("UTF8");
+ final int length = b.length;
+ if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
+ {
+ throw new SaslEncodingException("SASL text too long");
+ }
+ byte[] lengthBytes = { (byte) (length >>> 8), (byte) length };
+ out.write(lengthBytes);
+ out.write(b);
+ }
+
+ /**
+ * <p>Returns the encoded form of the current buffer including the 4-byte
+ * length header.</p>
+ *
+ * @throws SaslEncodingException if an encoding size constraint is violated.
+ */
+ public byte[] encode() throws SaslEncodingException
+ {
+ byte[] buffer = wrap();
+ final int length = buffer.length;
+ byte[] result = new byte[length + 4];
+ result[0] = (byte) (length >>> 24);
+ result[1] = (byte) (length >>> 16);
+ result[2] = (byte) (length >>> 8);
+ result[3] = (byte) length;
+ System.arraycopy(buffer, 0, result, 4, length);
+
+ return result;
+ }
+
+ /**
+ * <p>Returns the encoded form of the current buffer excluding the 4-byte
+ * length header.</p>
+ *
+ * @throws SaslEncodingException if an encoding size constraint is violated.
+ */
+ public byte[] wrap() throws SaslEncodingException
+ {
+ final int length = out.size();
+ if (length > Registry.SASL_BUFFER_MAX_LIMIT || length < 0)
+ {
+ throw new SaslEncodingException("SASL buffer too long");
+ }
+ return out.toByteArray();
+ }
+}
diff --git a/gnu/javax/crypto/sasl/SaslEncodingException.java b/gnu/javax/crypto/sasl/SaslEncodingException.java
new file mode 100644
index 000000000..9f4c59f1c
--- /dev/null
+++ b/gnu/javax/crypto/sasl/SaslEncodingException.java
@@ -0,0 +1,66 @@
+/* SaslEncodingException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import javax.security.sasl.SaslException;
+
+/**
+ * A checked exception, thrown when an exception occurs while decoding a SASL
+ * buffer and/or a SASL data element from/to a buffer.
+ */
+public class SaslEncodingException extends SaslException
+{
+
+ /** Constructs a <code>SaslEncodingException</code> with no detail message. */
+ public SaslEncodingException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a <code>SaslEncodingException</code> with the specified detail
+ * message.
+ *
+ * @param s the detail message.
+ */
+ public SaslEncodingException(String s)
+ {
+ super(s);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/SaslInputStream.java b/gnu/javax/crypto/sasl/SaslInputStream.java
new file mode 100644
index 000000000..57eb2b5c5
--- /dev/null
+++ b/gnu/javax/crypto/sasl/SaslInputStream.java
@@ -0,0 +1,459 @@
+/* SaslInputStream.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.util.Util;
+
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslServer;
+
+/**
+ * An input stream that uses either a {@link SaslClient} or a {@link SaslServer}
+ * to process the data through these entities' security layer filter(s).
+ */
+public class SaslInputStream extends InputStream
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "SaslOutputStream";
+
+ private static final String ERROR = "ERROR";
+
+ private static final String WARN = " WARN";
+
+ // private static final String INFO = " INFO";
+ private static final String TRACE = "DEBUG";
+
+ private static final boolean DEBUG = true;
+
+ private static final int debuglevel = 3;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String level, Object obj)
+ {
+ err.println("[" + level + "] " + NAME + ": " + String.valueOf(obj));
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private SaslClient client;
+
+ private SaslServer server;
+
+ private int maxRawSendSize;
+
+ private InputStream source;
+
+ private byte[] internalBuf;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public SaslInputStream(SaslClient client, InputStream source)
+ throws IOException
+ {
+ super();
+
+ this.client = client;
+ maxRawSendSize = Integer.parseInt((String) client.getNegotiatedProperty(Sasl.RAW_SEND_SIZE));
+ server = null;
+ this.source = source;
+ }
+
+ public SaslInputStream(SaslServer server, InputStream source)
+ throws IOException
+ {
+ super();
+
+ this.server = server;
+ maxRawSendSize = Integer.parseInt((String) server.getNegotiatedProperty(Sasl.RAW_SEND_SIZE));
+ client = null;
+ this.source = source;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Overloaded java.io.InputStream methods ----------------------------------
+
+ public int available() throws IOException
+ {
+ return (internalBuf == null) ? 0 : internalBuf.length;
+ }
+
+ public void close() throws IOException
+ {
+ source.close();
+ }
+
+ /**
+ * <p>Reads the next byte of data from the input stream. The value byte is
+ * returned as an <code>int</code> in the range <code>0</code> to
+ * <code>255</code>. If no byte is available because the end of the stream
+ * has been reached, the value <code>-1</code> is returned. This method
+ * blocks until input data is available, the end of the stream is detected,
+ * or an exception is thrown.</p>
+ *
+ * <p>From a SASL mechanism provider's perspective, if a security layer has
+ * been negotiated, the underlying <i>source</i> is expected to contain SASL
+ * buffers, as defined in RFC 2222. Four octets in network byte order in the
+ * front of each buffer identify the length of the buffer. The provider is
+ * responsible for performing any integrity checking or other processing on
+ * the buffer before returning the data as a stream of octets. For example,
+ * the protocol driver's request for a single octet from the stream might;
+ * i.e. an invocation of this method, may result in an entire SASL buffer
+ * being read and processed before that single octet can be returned.</p>
+ *
+ * @return the next byte of data, or <code>-1</code> if the end of the stream
+ * is reached.
+ * @throws IOException if an I/O error occurs.
+ */
+ public int read() throws IOException
+ {
+ int result = -1;
+ if (internalBuf != null && internalBuf.length > 0)
+ {
+ result = internalBuf[0] & 0xFF;
+ if (internalBuf.length == 1)
+ internalBuf = new byte[0];
+ else
+ {
+ byte[] tmp = new byte[internalBuf.length - 1];
+ // System.arraycopy(internalBuf, 0, tmp, 0, tmp.length);
+ System.arraycopy(internalBuf, 1, tmp, 0, tmp.length);
+ internalBuf = tmp;
+ }
+ }
+ else
+ {
+ byte[] buf = new byte[1];
+ int check = read(buf);
+ result = (check > 0) ? (buf[0] & 0xFF) : -1;
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Reads up to <code>len</code> bytes of data from the underlying
+ * <i>source</i> input stream into an array of bytes. An attempt is made to
+ * read as many as <code>len</code> bytes, but a smaller number may be read,
+ * possibly zero. The number of bytes actually read is returned as an
+ * integer.</p>
+ *
+ * <p>This method blocks until input data is available, end of file is
+ * detected, or an exception is thrown.</p>
+ *
+ * <p>If <code>b</code> is <code>null</code>, a {@link NullPointerException} is
+ * thrown.</p>
+ *
+ * <p>If <code>off</code> is negative, or <code>len</code> is negative, or
+ * <code>off+len</code> is greater than the length of the array <code>b</code>,
+ * then an {@link IndexOutOfBoundsException} is thrown.</p>
+ *
+ * <p>If <code>len</code> is zero, then no bytes are read and <code>0</code>
+ * is returned; otherwise, there is an attempt to read at least one byte. If
+ * no byte is available because the stream is at end of file, the value
+ * <code>-1</code> is returned; otherwise, at least one byte is read and
+ * stored into <code>b</code>.</p>
+ *
+ * <p>The first byte read is stored into element <code>b[off]</code>, the
+ * next one into <code>b[off+1]</code>, and so on. The number of bytes read
+ * is, at most, equal to <code>len</code>. Let <code>k</code> be the number
+ * of bytes actually read; these bytes will be stored in elements
+ * <code>b[off]</code> through <code>b[off+k-1]</code>, leaving elements
+ * <code>b[off+k]</code> through <code>b[off+len-1]</code> unaffected.</p>
+ *
+ * <p>In every case, elements <code>b[0]</code> through <code>b[off]</code>
+ * and elements <code>b[off+len]</code> through <code>b[b.length-1]</code>
+ * are unaffected.</p>
+ *
+ * <p>If the first byte cannot be read for any reason other than end of file,
+ * then an {@link IOException} is thrown. In particular, an {@link IOException}
+ * is thrown if the input stream has been closed.</p>
+ *
+ * <p>From the SASL mechanism provider's perspective, if a security layer has
+ * been negotiated, the underlying <i>source</i> is expected to contain SASL
+ * buffers, as defined in RFC 2222. Four octets in network byte order in the
+ * front of each buffer identify the length of the buffer. The provider is
+ * responsible for performing any integrity checking or other processing on
+ * the buffer before returning the data as a stream of octets. The protocol
+ * driver's request for a single octet from the stream might result in an
+ * entire SASL buffer being read and processed before that single octet can
+ * be returned.</p>
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in array <code>b</code> at which the data is
+ * wricodeen.
+ * @param len the maximum number of bytes to read.
+ * @return the total number of bytes read into the buffer, or <code>-1</code>
+ * if there is no more data because the end of the stream has been reached.
+ * @throws IOException if an I/O error occurs.
+ */
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> read(b, " + String.valueOf(off) + ", "
+ + String.valueOf(len) + ")");
+
+ if (b == null)
+ {
+ throw new NullPointerException("b");
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length)
+ || ((off + len) < 0))
+ {
+ throw new IndexOutOfBoundsException("off=" + String.valueOf(off)
+ + ", len=" + String.valueOf(len)
+ + ", b.length="
+ + String.valueOf(b.length));
+ }
+ if (len == 0)
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== read() --> 0");
+ return 0;
+ }
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Available: " + String.valueOf(available()));
+
+ int result = 0;
+ if (internalBuf == null || internalBuf.length < 1)
+ try
+ {
+ internalBuf = readSaslBuffer();
+ if (internalBuf == null)
+ {
+ if (DEBUG && debuglevel > 4)
+ debug(WARN, "Underlying stream empty. Returning -1");
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== read() --> -1");
+ return -1;
+ }
+ }
+ catch (InterruptedIOException x)
+ {
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, x);
+ if (DEBUG && debuglevel > 4)
+ debug(WARN, "Reading thread was interrupted. Returning -1");
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== read() --> -1");
+ return -1;
+ }
+
+ if (len <= internalBuf.length)
+ {
+ result = len;
+ System.arraycopy(internalBuf, 0, b, off, len);
+ if (len == internalBuf.length)
+ internalBuf = null;
+ else
+ {
+ byte[] tmp = new byte[internalBuf.length - len];
+ System.arraycopy(internalBuf, len, tmp, 0, tmp.length);
+ internalBuf = tmp;
+ }
+ }
+ else
+ {
+ // first copy the available bytes to b
+ result = internalBuf.length;
+ System.arraycopy(internalBuf, 0, b, off, result);
+ internalBuf = null;
+
+ off += result;
+ len -= result;
+
+ int remaining; // count of bytes remaining in buffer after an iteration
+ int delta; // count of bytes moved to b after an iteration
+ int datalen;
+ byte[] data;
+ while (len > 0)
+ // we need to read SASL buffers, as long as there are at least
+ // 4 bytes available at the source
+ if (source.available() > 3)
+ {
+ // process a buffer
+ data = readSaslBuffer();
+ if (data == null)
+ {
+ if (DEBUG && debuglevel > 4)
+ debug(WARN, "Underlying stream exhausted. Breaking...");
+ break;
+ }
+
+ datalen = data.length;
+
+ // copy [part of] the result to b
+ remaining = (datalen <= len) ? 0 : datalen - len;
+ delta = datalen - remaining;
+ System.arraycopy(data, 0, b, off, delta);
+ if (remaining > 0)
+ {
+ internalBuf = new byte[remaining];
+ System.arraycopy(data, delta, internalBuf, 0, remaining);
+ }
+
+ // update off, result and len
+ off += delta;
+ result += delta;
+ len -= delta;
+ }
+ else
+ { // nothing much we can do except return what we have
+ if (DEBUG && debuglevel > 4)
+ debug(WARN,
+ "Not enough bytes in source to read a buffer. Breaking...");
+ break;
+ }
+ }
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Remaining: "
+ + (internalBuf == null ? 0 : internalBuf.length));
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== read() --> " + String.valueOf(result));
+ return result;
+ }
+
+ // other nstance methods ---------------------------------------------------
+
+ /**
+ * Reads a SASL buffer from the underlying source if at least 4 bytes are
+ * available.
+ *
+ * @return the byte[] of decoded buffer contents, or null if the underlying
+ * source was exhausted.
+ * @throws IOException if an I/O exception occurs during the operation.
+ */
+ private byte[] readSaslBuffer() throws IOException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> readSaslBuffer()");
+
+ int realLength; // check if we read as many bytes as we're supposed to
+ byte[] result = new byte[4];
+ try
+ {
+ realLength = source.read(result);
+ if (realLength == -1)
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== readSaslBuffer() --> null");
+ return null;
+ }
+ }
+ catch (IOException x)
+ {
+ if (DEBUG && debuglevel > 0)
+ debug(ERROR, x);
+ throw x;
+ }
+
+ if (realLength != 4)
+ {
+ throw new IOException("Was expecting 4 but found "
+ + String.valueOf(realLength));
+ }
+ int bufferLength = result[0] << 24 | (result[1] & 0xFF) << 16
+ | (result[2] & 0xFF) << 8 | (result[3] & 0xFF);
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "SASL buffer size: " + bufferLength);
+ if (bufferLength > maxRawSendSize || bufferLength < 0)
+ {
+ throw new SaslEncodingException("SASL buffer (security layer) too long");
+ }
+
+ result = new byte[bufferLength];
+ try
+ {
+ realLength = source.read(result);
+ }
+ catch (IOException x)
+ {
+ if (DEBUG && debuglevel > 0)
+ debug(ERROR, x);
+ throw x;
+ }
+
+ if (realLength != bufferLength)
+ throw new IOException("Was expecting " + String.valueOf(bufferLength)
+ + " but found " + String.valueOf(realLength));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Incoming buffer (before security) (hex): "
+ + Util.dumpString(result));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Incoming buffer (before security) (str): \""
+ + new String(result) + "\"");
+
+ if (client != null)
+ {
+ result = client.unwrap(result, 0, realLength);
+ }
+ else
+ {
+ result = server.unwrap(result, 0, realLength);
+ }
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Incoming buffer (after security) (hex): "
+ + Util.dumpString(result));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Incoming buffer (after security) (str): \""
+ + new String(result) + "\"");
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== readSaslBuffer()");
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/SaslOutputStream.java b/gnu/javax/crypto/sasl/SaslOutputStream.java
new file mode 100644
index 000000000..699720137
--- /dev/null
+++ b/gnu/javax/crypto/sasl/SaslOutputStream.java
@@ -0,0 +1,218 @@
+/* SaslOutputStream.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.util.Util;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslServer;
+
+/**
+ * An output stream that uses either a {@link SaslClient} or a {@link SaslServer}
+ * to process the data through these entities' security layer filter(s).
+ */
+public class SaslOutputStream extends OutputStream
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "SaslOutputStream";
+
+ // private static final String ERROR = "ERROR";
+ // private static final String WARN = " WARN";
+ // private static final String INFO = " INFO";
+ private static final String TRACE = "DEBUG";
+
+ private static final boolean DEBUG = true;
+
+ private static final int debuglevel = 3;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String level, Object obj)
+ {
+ err.println("[" + level + "] " + NAME + ": " + String.valueOf(obj));
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private SaslClient client;
+
+ private SaslServer server;
+
+ private int maxRawSendSize;
+
+ private OutputStream dest;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public SaslOutputStream(SaslClient client, OutputStream dest)
+ throws IOException
+ {
+ super();
+
+ this.client = client;
+ maxRawSendSize = Integer.parseInt((String) client.getNegotiatedProperty(Sasl.RAW_SEND_SIZE));
+ server = null;
+ this.dest = dest;
+ }
+
+ public SaslOutputStream(SaslServer server, OutputStream dest)
+ throws IOException
+ {
+ super();
+
+ this.server = server;
+ maxRawSendSize = Integer.parseInt((String) server.getNegotiatedProperty(Sasl.RAW_SEND_SIZE));
+ client = null;
+ this.dest = dest;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Overloaded java.io.OutputStream methods
+ // -------------------------------------------------------------------------
+
+ public void close() throws IOException
+ {
+ dest.flush();
+ dest.close();
+ }
+
+ public void flush() throws IOException
+ {
+ dest.flush();
+ }
+
+ /**
+ * When writing octets to the resulting stream, if a security layer has been
+ * negotiated, each piece of data written (by a single invocation of
+ * <code>write()</code>) will be encapsulated as a SASL buffer, as defined in
+ * RFC 2222, and then written to the underlying <i>dest</i> output stream.
+ */
+ public void write(int b) throws IOException
+ {
+ write(new byte[] { (byte) b });
+ }
+
+ /**
+ * When writing octets to the resulting stream, if a security layer has been
+ * negotiated, each piece of data written (by a single invocation of
+ * <code>write()</code>) will be encapsulated as a SASL buffer, as defined in
+ * RFC 2222, and then written to the underlying <i>dest</i> output stream.
+ */
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ if (b == null)
+ {
+ throw new NullPointerException("b");
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length)
+ || ((off + len) < 0))
+ {
+ throw new IndexOutOfBoundsException("off=" + String.valueOf(off)
+ + ", len=" + String.valueOf(len)
+ + ", b.length="
+ + String.valueOf(b.length));
+ }
+ if (len == 0)
+ {
+ return;
+ }
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> write()");
+
+ int chunckSize, length, chunck = 1;
+ byte[] output = null, result;
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "About to wrap " + String.valueOf(len) + " byte(s)...");
+ while (len > 0)
+ {
+ chunckSize = (len > maxRawSendSize ? maxRawSendSize : len);
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Outgoing buffer (before security) (hex): "
+ + Util.dumpString(b, off, chunckSize));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Outgoing buffer (before security) (str): \""
+ + new String(b, off, chunckSize) + "\"");
+
+ if (client != null)
+ output = client.wrap(b, off, chunckSize);
+ else
+ output = server.wrap(b, off, chunckSize);
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Outgoing buffer (after security) (hex): "
+ + Util.dumpString(output));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Outgoing buffer (after security) (str): \""
+ + new String(output) + "\"");
+
+ length = output.length;
+ result = new byte[length + 4];
+ result[0] = (byte) (length >>> 24);
+ result[1] = (byte) (length >>> 16);
+ result[2] = (byte) (length >>> 8);
+ result[3] = (byte) length;
+ System.arraycopy(output, 0, result, 4, length);
+
+ dest.write(result);
+
+ off += chunckSize;
+ len -= chunckSize;
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Wrapped chunck #" + String.valueOf(chunck));
+ chunck++;
+ }
+
+ dest.flush();
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== write()");
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/SaslUtil.java b/gnu/javax/crypto/sasl/SaslUtil.java
new file mode 100644
index 000000000..e70312c0d
--- /dev/null
+++ b/gnu/javax/crypto/sasl/SaslUtil.java
@@ -0,0 +1,89 @@
+/* SaslUtil.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.util.Util;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+
+/**
+ * Utility methods for SASL-related classes.
+ */
+public class SaslUtil
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ private SaslUtil()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final boolean validEmailAddress(String address)
+ {
+ // need to do better than this
+ return (address.indexOf("@") != -1);
+ }
+
+ // Visualisation methods
+ // -------------------------------------------------------------------------
+
+ /** Returns the context of the designated hash as a string. */
+ public static final String dump(MessageDigest md)
+ {
+ String result;
+ try
+ {
+ result = Util.dumpString(((MessageDigest) md.clone()).digest());
+ }
+ catch (Exception ignored)
+ {
+ result = "...";
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/ServerFactory.java b/gnu/javax/crypto/sasl/ServerFactory.java
new file mode 100644
index 000000000..e9b08dbd4
--- /dev/null
+++ b/gnu/javax/crypto/sasl/ServerFactory.java
@@ -0,0 +1,194 @@
+/* ServerFactory.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.anonymous.AnonymousServer;
+import gnu.javax.crypto.sasl.crammd5.CramMD5Server;
+import gnu.javax.crypto.sasl.plain.PlainServer;
+import gnu.javax.crypto.sasl.srp.SRPServer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslServerFactory;
+
+/**
+ * The implementation of the {@link SaslServerFactory}.
+ */
+public class ServerFactory implements SaslServerFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final Set getNames()
+ {
+ return Collections.unmodifiableSet(new HashSet(
+ Arrays.asList(getNamesInternal(null))));
+ }
+
+ private static final String[] getNamesInternal(Map props)
+ {
+ String[] all = new String[] { Registry.SASL_SRP_MECHANISM,
+ Registry.SASL_CRAM_MD5_MECHANISM,
+ Registry.SASL_PLAIN_MECHANISM,
+ Registry.SASL_ANONYMOUS_MECHANISM };
+
+ List result = new ArrayList(4);
+ int i;
+ for (i = 0; i < all.length;)
+ {
+ result.add(all[i++]);
+ }
+
+ if (props == null)
+ {
+ return (String[]) result.toArray(new String[0]); // all
+ }
+ if (hasPolicy(Sasl.POLICY_PASS_CREDENTIALS, props))
+ { // none
+ return new String[0];
+ }
+
+ if (hasPolicy(Sasl.POLICY_NOPLAINTEXT, props))
+ {
+ result.remove(Registry.SASL_PLAIN_MECHANISM);
+ }
+ if (hasPolicy(Sasl.POLICY_NOACTIVE, props))
+ {
+ result.remove(Registry.SASL_CRAM_MD5_MECHANISM);
+ result.remove(Registry.SASL_PLAIN_MECHANISM);
+ }
+ if (hasPolicy(Sasl.POLICY_NODICTIONARY, props))
+ {
+ result.remove(Registry.SASL_CRAM_MD5_MECHANISM);
+ result.remove(Registry.SASL_PLAIN_MECHANISM);
+ }
+ if (hasPolicy(Sasl.POLICY_NOANONYMOUS, props))
+ {
+ result.remove(Registry.SASL_ANONYMOUS_MECHANISM);
+ }
+ if (hasPolicy(Sasl.POLICY_FORWARD_SECRECY, props))
+ {
+ result.remove(Registry.SASL_CRAM_MD5_MECHANISM);
+ result.remove(Registry.SASL_ANONYMOUS_MECHANISM);
+ result.remove(Registry.SASL_PLAIN_MECHANISM);
+ }
+ return (String[]) result.toArray(new String[0]);
+ }
+
+ public static final ServerMechanism getInstance(String mechanism)
+ {
+ if (mechanism == null)
+ {
+ return null;
+ }
+ mechanism = mechanism.trim().toUpperCase();
+ if (mechanism.equals(Registry.SASL_SRP_MECHANISM))
+ {
+ return new SRPServer();
+ }
+ if (mechanism.equals(Registry.SASL_CRAM_MD5_MECHANISM))
+ {
+ return new CramMD5Server();
+ }
+ if (mechanism.equals(Registry.SASL_PLAIN_MECHANISM))
+ {
+ return new PlainServer();
+ }
+ if (mechanism.equals(Registry.SASL_ANONYMOUS_MECHANISM))
+ {
+ return new AnonymousServer();
+ }
+ return null;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public SaslServer createSaslServer(String mechanism, String protocol,
+ String serverName, Map props,
+ CallbackHandler cbh) throws SaslException
+ {
+ ServerMechanism result = getInstance(mechanism);
+ if (result != null)
+ {
+ HashMap attributes = new HashMap();
+ if (props != null)
+ {
+ attributes.putAll(props);
+ }
+ attributes.put(Registry.SASL_PROTOCOL, protocol);
+ attributes.put(Registry.SASL_SERVER_NAME, serverName);
+ attributes.put(Registry.SASL_CALLBACK_HANDLER, cbh);
+
+ result.init(attributes);
+ }
+ return result;
+ }
+
+ public String[] getMechanismNames(Map props)
+ {
+ return getNamesInternal(props);
+ }
+
+ private static boolean hasPolicy(String propertyName, Map props)
+ {
+ return "true".equalsIgnoreCase(String.valueOf(props.get(propertyName)));
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/ServerMechanism.java b/gnu/javax/crypto/sasl/ServerMechanism.java
new file mode 100644
index 000000000..f12a075d9
--- /dev/null
+++ b/gnu/javax/crypto/sasl/ServerMechanism.java
@@ -0,0 +1,371 @@
+/* ServerMechanism.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import gnu.java.security.Registry;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslException;
+
+/**
+ * <p>A base class to facilitate implementing SASL server-side mechanisms.</p>
+ */
+public abstract class ServerMechanism implements SaslServer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Name of this mechanism. */
+ protected String mechanism;
+
+ /** Name of protocol using this mechanism. */
+ protected String protocol;
+
+ /** Name of server to authenticate to. */
+ protected String serverName;
+
+ /** Properties of qualities desired for this mechanism. */
+ protected Map properties;
+
+ /** Callback handler to use with this mechanism instance. */
+ protected CallbackHandler handler;
+
+ /** Whether authentication phase is completed (true) or not (false). */
+ protected boolean complete = false;
+
+ /** The authorisation identity. */
+ protected String authorizationID;
+
+ /** Channel binding data to use with this mechanism instance. */
+ protected byte[] channelBinding;
+
+ /** The state of the authentication automaton. -1 means uninitialised. */
+ protected int state = -1;
+
+ /** The provider for authentication information. */
+ protected IAuthInfoProvider authenticator;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ protected ServerMechanism(final String mechanism)
+ {
+ super();
+
+ this.mechanism = mechanism;
+ this.authenticator = AuthInfo.getProvider(mechanism);
+ this.state = -1;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods to be implemented by concrete subclasses ---------------
+
+ protected abstract void initMechanism() throws SaslException;
+
+ protected abstract void resetMechanism() throws SaslException;
+
+ // javax.security.sasl.SaslServer interface implementation -----------------
+
+ public abstract byte[] evaluateResponse(byte[] response) throws SaslException;
+
+ public boolean isComplete()
+ {
+ return complete;
+ }
+
+ public byte[] unwrap(final byte[] incoming, final int offset, final int len)
+ throws SaslException
+ {
+ if (!isComplete())
+ {
+ throw new IllegalMechanismStateException();
+ }
+ return this.engineUnwrap(incoming, offset, len);
+ }
+
+ public byte[] wrap(final byte[] outgoing, final int offset, final int len)
+ throws SaslException
+ {
+ if (!isComplete())
+ {
+ throw new IllegalMechanismStateException();
+ }
+ return this.engineWrap(outgoing, offset, len);
+ }
+
+ public String getMechanismName()
+ {
+ return this.mechanism;
+ }
+
+ public String getAuthorizationID()
+ {
+ return this.authorizationID;
+ }
+
+ public Object getNegotiatedProperty(final String propName)
+ {
+ if (!isComplete())
+ {
+ throw new IllegalStateException();
+ }
+ if (Sasl.QOP.equals(propName))
+ {
+ return getNegotiatedQOP();
+ }
+ if (Sasl.STRENGTH.equals(propName))
+ {
+ return getNegotiatedStrength();
+ }
+ if (Sasl.SERVER_AUTH.equals(propName))
+ {
+ return getNegotiatedServerAuth();
+ }
+ if (Sasl.MAX_BUFFER.equals(propName))
+ {
+ return getNegotiatedMaxBuffer();
+ }
+ if (Sasl.RAW_SEND_SIZE.equals(propName))
+ {
+ return getNegotiatedRawSendSize();
+ }
+ if (Sasl.POLICY_NOPLAINTEXT.equals(propName))
+ {
+ return getNegotiatedPolicyNoPlainText();
+ }
+ if (Sasl.POLICY_NOACTIVE.equals(propName))
+ {
+ return getNegotiatedPolicyNoActive();
+ }
+ if (Sasl.POLICY_NODICTIONARY.equals(propName))
+ {
+ return getNegotiatedPolicyNoDictionary();
+ }
+ if (Sasl.POLICY_NOANONYMOUS.equals(propName))
+ {
+ return getNegotiatedPolicyNoAnonymous();
+ }
+ if (Sasl.POLICY_FORWARD_SECRECY.equals(propName))
+ {
+ return getNegotiatedPolicyForwardSecrecy();
+ }
+ if (Sasl.POLICY_PASS_CREDENTIALS.equals(propName))
+ {
+ return getNegotiatedPolicyPassCredentials();
+ }
+ if (Sasl.REUSE.equals(propName))
+ {
+ return getReuse();
+ }
+ return null;
+ }
+
+ public void dispose() throws SaslException
+ {
+ reset();
+ }
+
+ // other Instance methods --------------------------------------------------
+
+ protected String getNegotiatedQOP()
+ {
+ return Registry.QOP_AUTH;
+ }
+
+ protected String getNegotiatedStrength()
+ {
+ return Registry.STRENGTH_LOW;
+ }
+
+ protected String getNegotiatedServerAuth()
+ {
+ return Registry.SERVER_AUTH_FALSE;
+ }
+
+ protected String getNegotiatedMaxBuffer()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyNoPlainText()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyNoActive()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyNoDictionary()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyNoAnonymous()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyForwardSecrecy()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedPolicyPassCredentials()
+ {
+ return null;
+ }
+
+ protected String getNegotiatedRawSendSize()
+ {
+ return String.valueOf(Registry.SASL_BUFFER_MAX_LIMIT);
+ }
+
+ protected String getReuse()
+ {
+ return Registry.REUSE_FALSE;
+ }
+
+ protected byte[] engineUnwrap(final byte[] incoming, final int offset,
+ final int len) throws SaslException
+ {
+ final byte[] result = new byte[len];
+ System.arraycopy(incoming, offset, result, 0, len);
+ return result;
+ }
+
+ protected byte[] engineWrap(final byte[] outgoing, final int offset,
+ final int len) throws SaslException
+ {
+ final byte[] result = new byte[len];
+ System.arraycopy(outgoing, offset, result, 0, len);
+ return result;
+ }
+
+ /**
+ * <p>Initialises the mechanism with designated attributes. Permissible names
+ * and values are mechanism specific.</p>
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @throws IllegalMechanismStateException if the instance is already
+ * initialised.
+ * @throws SaslException if an exception occurs during the process.
+ */
+ public void init(final Map attributes) throws SaslException
+ {
+ if (state != -1)
+ {
+ throw new IllegalMechanismStateException("init()");
+ }
+
+ if (properties == null)
+ {
+ properties = new HashMap();
+ }
+ else
+ {
+ properties.clear();
+ }
+ if (attributes != null)
+ {
+ protocol = (String) attributes.get(Registry.SASL_PROTOCOL);
+ serverName = (String) attributes.get(Registry.SASL_SERVER_NAME);
+ handler = (CallbackHandler) attributes.get(Registry.SASL_CALLBACK_HANDLER);
+ channelBinding = (byte[]) attributes.get(Registry.SASL_CHANNEL_BINDING);
+ properties.putAll(attributes);
+ }
+ else
+ {
+ handler = null;
+ }
+
+ if (protocol == null)
+ {
+ protocol = "";
+ }
+ if (serverName == null)
+ {
+ serverName = "";
+ }
+ if (authenticator != null)
+ {
+ authenticator.activate(properties);
+ }
+ if (channelBinding == null)
+ {
+ channelBinding = new byte[0];
+ }
+ initMechanism();
+ complete = false;
+ state = 0;
+ }
+
+ /**
+ * <p>Resets the mechanism instance for re-initialisation and use with other
+ * characteristics.</p>
+ *
+ * @throws SaslException if an exception occurs during the process.
+ */
+ public void reset() throws SaslException
+ {
+ resetMechanism();
+ properties.clear();
+ if (authenticator != null)
+ {
+ authenticator.passivate();
+ }
+ protocol = serverName = null;
+ channelBinding = null;
+ complete = false;
+ state = -1;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/UserAlreadyExistsException.java b/gnu/javax/crypto/sasl/UserAlreadyExistsException.java
new file mode 100644
index 000000000..764a36df3
--- /dev/null
+++ b/gnu/javax/crypto/sasl/UserAlreadyExistsException.java
@@ -0,0 +1,70 @@
+/* UserAlreadyExistsException.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl;
+
+import javax.security.sasl.SaslException;
+
+/**
+ * A checked exception thrown to indicate that a designated user is already
+ * known to the the authentication layer.
+ */
+public class UserAlreadyExistsException extends SaslException
+{
+
+ /**
+ * Constructs a <code>UserAlreadyExistsException</code> with no detail
+ * message.
+ */
+ public UserAlreadyExistsException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a <code>UserAlreadyExistsException</code> with the specified
+ * detail message. In the case of this exception, the detail message
+ * designates the offending username.
+ *
+ * @param userName the detail message, which in this case is the username.
+ */
+ public UserAlreadyExistsException(String userName)
+ {
+ super(userName);
+ }
+}
diff --git a/gnu/javax/crypto/sasl/anonymous/AnonymousClient.java b/gnu/javax/crypto/sasl/anonymous/AnonymousClient.java
new file mode 100644
index 000000000..f5b1faab2
--- /dev/null
+++ b/gnu/javax/crypto/sasl/anonymous/AnonymousClient.java
@@ -0,0 +1,120 @@
+/* AnonymousClient.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.anonymous;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.ClientMechanism;
+import gnu.javax.crypto.sasl.IllegalMechanismStateException;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.AuthenticationException;
+
+/**
+ * <p>The ANONYMOUS client-side mechanism.</p>
+ */
+public class AnonymousClient extends ClientMechanism implements SaslClient
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public AnonymousClient()
+ {
+ super(Registry.SASL_ANONYMOUS_MECHANISM);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods implementation -----------------------------------------
+
+ protected void initMechanism() throws SaslException
+ {
+ }
+
+ protected void resetMechanism() throws SaslException
+ {
+ }
+
+ // javax.security.sasl.SaslClient interface implementation -----------------
+
+ public boolean hasInitialResponse()
+ {
+ return true;
+ }
+
+ public byte[] evaluateChallenge(final byte[] challenge) throws SaslException
+ {
+ if (complete)
+ {
+ throw new IllegalMechanismStateException("evaluateChallenge()");
+ }
+ return response();
+ }
+
+ private byte[] response() throws SaslException
+ {
+ if (!AnonymousUtil.isValidTraceInformation(authorizationID))
+ {
+ throw new AuthenticationException(
+ "Authorisation ID is not a valid email address");
+ }
+ complete = true;
+ // return authorizationID.getBytes();
+ final byte[] result;
+ try
+ {
+ result = authorizationID.getBytes("UTF-8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new AuthenticationException("response()", x);
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/anonymous/AnonymousServer.java b/gnu/javax/crypto/sasl/anonymous/AnonymousServer.java
new file mode 100644
index 000000000..2c10f78a7
--- /dev/null
+++ b/gnu/javax/crypto/sasl/anonymous/AnonymousServer.java
@@ -0,0 +1,107 @@
+/* AnonymousServer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.anonymous;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.ServerMechanism;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.security.sasl.AuthenticationException;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+/**
+ * The ANONYMOUS server-side mechanism.
+ */
+public class AnonymousServer extends ServerMechanism implements SaslServer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public AnonymousServer()
+ {
+ super(Registry.SASL_ANONYMOUS_MECHANISM);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods implementation -----------------------------------------
+
+ protected void initMechanism() throws SaslException
+ {
+ }
+
+ protected void resetMechanism() throws SaslException
+ {
+ }
+
+ // javax.security.sasl.SaslServer interface implementation -----------------
+
+ public byte[] evaluateResponse(final byte[] response) throws SaslException
+ {
+ if (response == null)
+ {
+ return null;
+ }
+ try
+ {
+ authorizationID = new String(response, "UTF-8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new AuthenticationException("evaluateResponse()", x);
+ }
+ if (AnonymousUtil.isValidTraceInformation(authorizationID))
+ {
+ this.complete = true;
+ return null;
+ }
+ authorizationID = null;
+ throw new AuthenticationException("Invalid email address");
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java b/gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java
new file mode 100644
index 000000000..99e95eaec
--- /dev/null
+++ b/gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java
@@ -0,0 +1,109 @@
+/* AnonymousUtil.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.anonymous;
+
+import gnu.javax.crypto.sasl.SaslUtil;
+
+/**
+ * An ANONYMOUS-specific utility class.
+ */
+public class AnonymousUtil
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial private constructor to enforce Singleton pattern. */
+ private AnonymousUtil()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ static boolean isValidTraceInformation(String traceInformation)
+ {
+ if (traceInformation == null)
+ {
+ return false;
+ }
+ if (traceInformation.length() == 0)
+ {
+ return true;
+ }
+ if (SaslUtil.validEmailAddress(traceInformation))
+ {
+ return true;
+ }
+ return isValidToken(traceInformation);
+ }
+
+ static boolean isValidToken(String token)
+ {
+ if (token == null)
+ {
+ return false;
+ }
+ if (token.length() == 0)
+ {
+ return false;
+ }
+ if (token.length() > 255)
+ {
+ return false;
+ }
+ if (token.indexOf('@') != -1)
+ {
+ return false;
+ }
+ for (int i = 0; i < token.length(); i++)
+ {
+ char c = token.charAt(i);
+ if (c < 0x20 || c > 0x7E)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java b/gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java
new file mode 100644
index 000000000..cf73b6f98
--- /dev/null
+++ b/gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java
@@ -0,0 +1,200 @@
+/* CramMD5AuthInfoProvider.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.crammd5;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.IAuthInfoProvider;
+import gnu.javax.crypto.sasl.NoSuchUserException;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.sasl.AuthenticationException;
+
+/**
+ * The CRAM-MD5 mechanism authentication information provider implementation.
+ */
+public class CramMD5AuthInfoProvider implements IAuthInfoProvider
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private PasswordFile passwordFile = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-args constrcutor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // IAuthInfoProvider interface implementation
+ // -------------------------------------------------------------------------
+
+ public void activate(Map context) throws AuthenticationException
+ {
+ try
+ {
+ if (context == null)
+ {
+ passwordFile = new PasswordFile();
+ }
+ else
+ {
+ String pfn = (String) context.get(CramMD5Registry.PASSWORD_FILE);
+ if (pfn == null)
+ {
+ passwordFile = new PasswordFile();
+ }
+ else
+ {
+ passwordFile = new PasswordFile(pfn);
+ }
+ }
+ }
+ catch (IOException x)
+ {
+ throw new AuthenticationException("activate()", x);
+ }
+ }
+
+ public void passivate() throws AuthenticationException
+ {
+ passwordFile = null;
+ }
+
+ public boolean contains(String userName) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("contains()",
+ new IllegalStateException());
+ }
+ boolean result = false;
+ try
+ {
+ result = passwordFile.contains(userName);
+ }
+ catch (IOException x)
+ {
+ throw new AuthenticationException("contains()", x);
+ }
+ return result;
+ }
+
+ public Map lookup(Map userID) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("lookup()",
+ new IllegalStateException());
+ }
+ Map result = new HashMap();
+ try
+ {
+ String userName = (String) userID.get(Registry.SASL_USERNAME);
+ if (userName == null)
+ {
+ throw new NoSuchUserException("");
+ }
+ String[] data = passwordFile.lookup(userName);
+ result.put(Registry.SASL_USERNAME, data[0]);
+ result.put(Registry.SASL_PASSWORD, data[1]);
+ result.put(CramMD5Registry.UID_FIELD, data[2]);
+ result.put(CramMD5Registry.GID_FIELD, data[3]);
+ result.put(CramMD5Registry.GECOS_FIELD, data[4]);
+ result.put(CramMD5Registry.DIR_FIELD, data[5]);
+ result.put(CramMD5Registry.SHELL_FIELD, data[6]);
+ }
+ catch (Exception x)
+ {
+ if (x instanceof AuthenticationException)
+ {
+ throw (AuthenticationException) x;
+ }
+ throw new AuthenticationException("lookup()", x);
+ }
+ return result;
+ }
+
+ public void update(Map userCredentials) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("update()",
+ new IllegalStateException());
+ }
+ try
+ {
+ String userName = (String) userCredentials.get(Registry.SASL_USERNAME);
+ String password = (String) userCredentials.get(Registry.SASL_PASSWORD);
+ String uid = (String) userCredentials.get(CramMD5Registry.UID_FIELD);
+ String gid = (String) userCredentials.get(CramMD5Registry.GID_FIELD);
+ String gecos = (String) userCredentials.get(CramMD5Registry.GECOS_FIELD);
+ String dir = (String) userCredentials.get(CramMD5Registry.DIR_FIELD);
+ String shell = (String) userCredentials.get(CramMD5Registry.SHELL_FIELD);
+ if (uid == null || gid == null || gecos == null || dir == null
+ || shell == null)
+ {
+ passwordFile.changePasswd(userName, password);
+ }
+ else
+ {
+ String[] attributes = new String[] { uid, gid, gecos, dir, shell };
+ passwordFile.add(userName, password, attributes);
+ }
+ }
+ catch (Exception x)
+ {
+ if (x instanceof AuthenticationException)
+ {
+ throw (AuthenticationException) x;
+ }
+ throw new AuthenticationException("update()", x);
+ }
+ }
+
+ public Map getConfiguration(String mode) throws AuthenticationException
+ {
+ throw new AuthenticationException("", new UnsupportedOperationException());
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/crammd5/CramMD5Client.java b/gnu/javax/crypto/sasl/crammd5/CramMD5Client.java
new file mode 100644
index 000000000..094109ff9
--- /dev/null
+++ b/gnu/javax/crypto/sasl/crammd5/CramMD5Client.java
@@ -0,0 +1,201 @@
+/* CramMD5Client.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.crammd5;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.sasl.ClientMechanism;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthenticationException;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+/**
+ * The CRAM-MD5 SASL client-side mechanism.
+ */
+public class CramMD5Client extends ClientMechanism implements SaslClient
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public CramMD5Client()
+ {
+ super(Registry.SASL_CRAM_MD5_MECHANISM);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods implementation -----------------------------------------
+
+ protected void initMechanism() throws SaslException
+ {
+ }
+
+ protected void resetMechanism() throws SaslException
+ {
+ }
+
+ // javax.security.sasl.SaslClient interface implementation -----------------
+
+ public boolean hasInitialResponse()
+ {
+ return false;
+ }
+
+ public byte[] evaluateChallenge(final byte[] challenge) throws SaslException
+ {
+ if (challenge == null)
+ {
+ throw new SaslException("null challenge");
+ }
+ try
+ {
+ final String username;
+ final char[] password;
+ Callback[] callbacks;
+
+ if ((!properties.containsKey(Registry.SASL_USERNAME))
+ && (!properties.containsKey(Registry.SASL_PASSWORD)))
+ {
+ callbacks = new Callback[2];
+
+ final NameCallback nameCB;
+ final String defaultName = System.getProperty("user.name");
+ if (defaultName == null)
+ {
+ nameCB = new NameCallback("username: ");
+ }
+ else
+ {
+ nameCB = new NameCallback("username: ", defaultName);
+ }
+ final PasswordCallback pwdCB = new PasswordCallback("password: ",
+ false);
+ callbacks[0] = nameCB;
+ callbacks[1] = pwdCB;
+ this.handler.handle(callbacks);
+ username = nameCB.getName();
+ password = pwdCB.getPassword();
+ }
+ else
+ {
+ if (properties.containsKey(Registry.SASL_USERNAME))
+ {
+ username = (String) properties.get(Registry.SASL_USERNAME);
+ }
+ else
+ {
+ callbacks = new Callback[1];
+ final NameCallback nameCB;
+ final String defaultName = System.getProperty("user.name");
+ if (defaultName == null)
+ {
+ nameCB = new NameCallback("username: ");
+ }
+ else
+ {
+ nameCB = new NameCallback("username: ", defaultName);
+ }
+ callbacks[0] = nameCB;
+ this.handler.handle(callbacks);
+ username = nameCB.getName();
+ }
+
+ if (properties.containsKey(Registry.SASL_PASSWORD))
+ {
+ password = ((String) properties.get(Registry.SASL_PASSWORD)).toCharArray();
+ }
+ else
+ {
+ callbacks = new Callback[1];
+ final PasswordCallback pwdCB = new PasswordCallback(
+ "password: ",
+ false);
+ callbacks[0] = pwdCB;
+ this.handler.handle(callbacks);
+ password = pwdCB.getPassword();
+ }
+ }
+
+ if (password == null)
+ {
+ throw new SaslException("null password supplied");
+ }
+ final byte[] digest;
+ try
+ {
+ digest = CramMD5Util.createHMac(password, challenge);
+ }
+ catch (InvalidKeyException x)
+ {
+ throw new AuthenticationException("evaluateChallenge()", x);
+ }
+ final String response = username + " "
+ + Util.toString(digest).toLowerCase();
+ this.complete = true;
+
+ return response.getBytes("UTF-8");
+ }
+ catch (UnsupportedCallbackException x)
+ {
+ throw new AuthenticationException("evaluateChallenge()", x);
+ }
+ catch (IOException x)
+ {
+ throw new AuthenticationException("evaluateChallenge()", x);
+ }
+ }
+
+ protected String getNegotiatedQOP()
+ {
+ return Registry.QOP_AUTH;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java b/gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java
new file mode 100644
index 000000000..1c61cace4
--- /dev/null
+++ b/gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java
@@ -0,0 +1,66 @@
+/* CramMD5Registry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.crammd5;
+
+/**
+ * A list of properties common to CRAM-MD5 classes.
+ */
+public interface CramMD5Registry
+{
+ /** Name of the password file (used by the server) property. */
+ String PASSWORD_FILE = "gnu.crypto.sasl.crammd5.password.file";
+
+ /** Default password file (used by the server) pathname. */
+ String DEFAULT_PASSWORD_FILE = "/etc/passwd";
+
+ /** Name of the UID field in the plain password file. */
+ String UID_FIELD = "crammd5.uid";
+
+ /** Name of the GID field in the plain password file. */
+ String GID_FIELD = "crammd5.gid";
+
+ /** Name of the GECOS field in the plain password file. */
+ String GECOS_FIELD = "crammd5.gecos";
+
+ /** Name of the DIR field in the plain password file. */
+ String DIR_FIELD = "crammd5.dir";
+
+ /** Name of the SHELL field in the plain password file. */
+ String SHELL_FIELD = "crammd5.shell";
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/crammd5/CramMD5Server.java b/gnu/javax/crypto/sasl/crammd5/CramMD5Server.java
new file mode 100644
index 000000000..d6622b6db
--- /dev/null
+++ b/gnu/javax/crypto/sasl/crammd5/CramMD5Server.java
@@ -0,0 +1,185 @@
+/* CramMD5Server.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.crammd5;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.sasl.NoSuchUserException;
+import gnu.javax.crypto.sasl.ServerMechanism;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidKeyException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.sasl.AuthenticationException;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+/**
+ * <p>The CRAM-MD5 SASL server-side mechanism.</p>
+ */
+public class CramMD5Server extends ServerMechanism implements SaslServer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private byte[] msgID;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public CramMD5Server()
+ {
+ super(Registry.SASL_CRAM_MD5_MECHANISM);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods implementation -----------------------------------------
+
+ protected void initMechanism() throws SaslException
+ {
+ }
+
+ protected void resetMechanism() throws SaslException
+ {
+ }
+
+ // javax.security.sasl.SaslServer interface implementation -----------------
+
+ public byte[] evaluateResponse(final byte[] response) throws SaslException
+ {
+ if (state == 0)
+ {
+ msgID = CramMD5Util.createMsgID();
+ state++;
+ return msgID;
+ }
+
+ final String responseStr = new String(response);
+ final int index = responseStr.lastIndexOf(" ");
+ final String username = responseStr.substring(0, index);
+ final byte[] responseDigest;
+ try
+ {
+ responseDigest = responseStr.substring(index + 1).getBytes("UTF-8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new AuthenticationException("evaluateResponse()", x);
+ }
+
+ // Look up the password
+ final char[] password = lookupPassword(username);
+
+ // Compute the digest
+ byte[] digest;
+ try
+ {
+ digest = CramMD5Util.createHMac(password, msgID);
+ }
+ catch (InvalidKeyException x)
+ {
+ throw new AuthenticationException("evaluateResponse()", x);
+ }
+ try
+ {
+ // digest = (new String(Util.toString(digest).toLowerCase())).getBytes("UTF-8");
+ digest = Util.toString(digest).toLowerCase().getBytes("UTF-8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new AuthenticationException("evaluateResponse()", x);
+ }
+
+ // Compare the received and computed digests
+ if (!Arrays.equals(digest, responseDigest))
+ {
+ throw new AuthenticationException("Digest mismatch");
+ }
+ state++;
+ return null;
+ }
+
+ public boolean isComplete()
+ {
+ return (state == 2);
+ }
+
+ protected String getNegotiatedQOP()
+ {
+ return Registry.QOP_AUTH;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ private char[] lookupPassword(final String userName) throws SaslException
+ {
+ try
+ {
+ if (!authenticator.contains(userName))
+ {
+ throw new NoSuchUserException(userName);
+ }
+ final Map userID = new HashMap();
+ userID.put(Registry.SASL_USERNAME, userName);
+ final Map credentials = authenticator.lookup(userID);
+ final String password = (String) credentials.get(Registry.SASL_PASSWORD);
+ if (password == null)
+ {
+ throw new AuthenticationException("lookupPassword()",
+ new InternalError());
+ }
+ return password.toCharArray();
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("lookupPassword()", x);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/crammd5/CramMD5Util.java b/gnu/javax/crypto/sasl/crammd5/CramMD5Util.java
new file mode 100644
index 000000000..6e7539349
--- /dev/null
+++ b/gnu/javax/crypto/sasl/crammd5/CramMD5Util.java
@@ -0,0 +1,137 @@
+/* CramMD5Util.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.crammd5;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.mac.HMacFactory;
+import gnu.javax.crypto.mac.IMac;
+
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.InvalidKeyException;
+import java.util.HashMap;
+
+import javax.security.sasl.SaslException;
+
+/**
+ * A package-private CRAM-MD5-specific utility class.
+ */
+class CramMD5Util
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ private CramMD5Util()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ static byte[] createMsgID() throws SaslException
+ {
+ // <process-ID.clock@hostname>
+ final String encoded;
+ try
+ {
+ encoded = Util.toBase64(Thread.currentThread().getName().getBytes(
+ "UTF-8"));
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new SaslException("createMsgID()", x);
+ }
+ String hostname = "localhost";
+ try
+ {
+ hostname = InetAddress.getLocalHost().getHostAddress();
+ }
+ catch (UnknownHostException ignored)
+ {
+ }
+
+ final byte[] result;
+ try
+ {
+ result = new StringBuffer().append("<").append(
+ encoded.substring(
+ 0,
+ encoded.length())).append(
+ ".").append(
+ String.valueOf(System.currentTimeMillis())).append(
+ "@").append(
+ hostname).append(
+ ">").toString().getBytes(
+ "UTF-8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new SaslException("createMsgID()", x);
+ }
+ return result;
+ }
+
+ static byte[] createHMac(final char[] passwd, final byte[] data)
+ throws InvalidKeyException, SaslException
+ {
+ final IMac mac = HMacFactory.getInstance(Registry.HMAC_NAME_PREFIX
+ + Registry.MD5_HASH);
+ final HashMap map = new HashMap();
+ final byte[] km;
+ try
+ {
+ km = new String(passwd).getBytes("UTF-8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new SaslException("createHMac()", x);
+ }
+ map.put(IMac.MAC_KEY_MATERIAL, km);
+ mac.init(map);
+ mac.update(data, 0, data.length);
+ return mac.digest();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/crammd5/PasswordFile.java b/gnu/javax/crypto/sasl/crammd5/PasswordFile.java
new file mode 100644
index 000000000..081af4615
--- /dev/null
+++ b/gnu/javax/crypto/sasl/crammd5/PasswordFile.java
@@ -0,0 +1,301 @@
+/* PasswordFile.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.crammd5;
+
+import gnu.javax.crypto.sasl.NoSuchUserException;
+import gnu.javax.crypto.sasl.UserAlreadyExistsException;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * The CRAM-MD5 password file representation.
+ */
+public class PasswordFile
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static String DEFAULT_FILE;
+ static
+ {
+ DEFAULT_FILE = System.getProperty(CramMD5Registry.PASSWORD_FILE,
+ CramMD5Registry.DEFAULT_PASSWORD_FILE);
+ }
+
+ private HashMap entries;
+
+ private File passwdFile;
+
+ private long lastmod;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public PasswordFile() throws IOException
+ {
+ this(DEFAULT_FILE);
+ }
+
+ public PasswordFile(final File pwFile) throws IOException
+ {
+ this(pwFile.getAbsolutePath());
+ }
+
+ public PasswordFile(final String fileName) throws IOException
+ {
+ passwdFile = new File(fileName);
+ update();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public synchronized void add(final String user, final String passwd,
+ final String[] attributes) throws IOException
+ {
+ checkCurrent(); // check if the entry exists
+ if (entries.containsKey(user))
+ {
+ throw new UserAlreadyExistsException(user);
+ }
+ if (attributes.length != 5)
+ {
+ throw new IllegalArgumentException("Wrong number of attributes");
+ }
+
+ final String[] fields = new String[7]; // create the new entry
+ fields[0] = user;
+ fields[1] = passwd;
+ System.arraycopy(attributes, 0, fields, 2, 5);
+ entries.put(user, fields);
+ savePasswd();
+ }
+
+ public synchronized void changePasswd(final String user, final String passwd)
+ throws IOException
+ {
+ checkCurrent();
+ if (!entries.containsKey(user))
+ { // check if the entry exists
+ throw new NoSuchUserException(user);
+ }
+
+ final String[] fields = (String[]) entries.get(user); // get the existing entry
+ fields[1] = passwd; // modify the password field
+ entries.remove(user); // delete the existing entry
+ entries.put(user, fields); // add the new entry
+
+ savePasswd();
+ }
+
+ public synchronized String[] lookup(final String user) throws IOException
+ {
+ checkCurrent();
+ if (!entries.containsKey(user))
+ {
+ throw new NoSuchUserException(user);
+ }
+ return (String[]) entries.get(user);
+ }
+
+ public synchronized boolean contains(final String s) throws IOException
+ {
+ checkCurrent();
+
+ return entries.containsKey(s);
+ }
+
+ private synchronized void update() throws IOException
+ {
+ lastmod = passwdFile.lastModified();
+ readPasswd(new FileInputStream(passwdFile));
+ }
+
+ private void checkCurrent() throws IOException
+ {
+ if (passwdFile.lastModified() > lastmod)
+ {
+ update();
+ }
+ }
+
+ private synchronized void readPasswd(final InputStream in) throws IOException
+ {
+ final BufferedReader din = new BufferedReader(new InputStreamReader(in));
+ String line;
+ entries = new HashMap();
+ while ((line = din.readLine()) != null)
+ {
+ final String[] fields = new String[7];
+ final StringTokenizer st = new StringTokenizer(line, ":", true);
+ try
+ {
+ fields[0] = st.nextToken(); // username
+ st.nextToken();
+
+ fields[1] = st.nextToken(); // passwd
+ if (fields[1].equals(":"))
+ {
+ fields[1] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[2] = st.nextToken(); // uid
+ if (fields[2].equals(":"))
+ {
+ fields[2] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[3] = st.nextToken(); // gid
+ if (fields[3].equals(":"))
+ {
+ fields[3] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[4] = st.nextToken(); // gecos
+ if (fields[4].equals(":"))
+ {
+ fields[4] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[5] = st.nextToken(); // dir
+ if (fields[5].equals(":"))
+ {
+ fields[5] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[6] = st.nextToken(); // shell
+ if (fields[6].equals(":"))
+ {
+ fields[6] = "";
+ }
+ }
+ catch (NoSuchElementException x)
+ {
+ continue;
+ }
+
+ entries.put(fields[0], fields);
+ }
+ }
+
+ private synchronized void savePasswd() throws IOException
+ {
+ if (passwdFile != null)
+ {
+ final FileOutputStream fos = new FileOutputStream(passwdFile);
+ PrintWriter pw = null;
+ try
+ {
+ pw = new PrintWriter(fos);
+ String key;
+ String[] fields;
+ StringBuffer sb;
+ int i;
+ for (Iterator it = entries.keySet().iterator(); it.hasNext();)
+ {
+ key = (String) it.next();
+ fields = (String[]) entries.get(key);
+ sb = new StringBuffer(fields[0]);
+ for (i = 1; i < fields.length; i++)
+ {
+ sb.append(":").append(fields[i]);
+ }
+ pw.println(sb.toString());
+ }
+ }
+ finally
+ {
+ if (pw != null)
+ {
+ try
+ {
+ pw.flush();
+ }
+ finally
+ {
+ pw.close();
+ }
+ }
+ try
+ {
+ fos.close();
+ }
+ catch (IOException ignored)
+ {
+ }
+ lastmod = passwdFile.lastModified();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/plain/PasswordFile.java b/gnu/javax/crypto/sasl/plain/PasswordFile.java
new file mode 100644
index 000000000..4ef6b8541
--- /dev/null
+++ b/gnu/javax/crypto/sasl/plain/PasswordFile.java
@@ -0,0 +1,309 @@
+/* PasswordFile.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.plain;
+
+import gnu.classpath.SystemProperties;
+
+import gnu.javax.crypto.sasl.NoSuchUserException;
+import gnu.javax.crypto.sasl.UserAlreadyExistsException;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.NoSuchElementException;
+
+/**
+ * A representation of a Plain password file.
+ */
+public class PasswordFile
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static String DEFAULT_FILE;
+ static
+ {
+ DEFAULT_FILE = SystemProperties.getProperty(PlainRegistry.PASSWORD_FILE,
+ PlainRegistry.DEFAULT_PASSWORD_FILE);
+ }
+
+ private Hashtable entries;
+
+ private File passwdFile;
+
+ // private String[] last_params;
+ private long lastmod;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public PasswordFile() throws IOException
+ {
+ this(DEFAULT_FILE);
+ }
+
+ public PasswordFile(File pwFile) throws IOException
+ {
+ this(pwFile.getAbsolutePath());
+ }
+
+ public PasswordFile(String fileName) throws IOException
+ {
+ passwdFile = new File(fileName);
+ update();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public synchronized void add(String user, String passwd, String[] attributes)
+ throws IOException
+ {
+ checkCurrent();
+ if (entries.containsKey(user))
+ {
+ throw new UserAlreadyExistsException(user);
+ }
+ if (attributes.length != 5)
+ {
+ throw new IllegalArgumentException("Wrong number of attributes");
+ }
+ // create the new entry
+ String[] fields = new String[7];
+ fields[0] = user;
+ fields[1] = passwd;
+ System.arraycopy(attributes, 0, fields, 2, 5);
+ entries.put(user, fields);
+
+ savePasswd();
+ }
+
+ public synchronized void changePasswd(String user, String passwd)
+ throws IOException
+ {
+ checkCurrent();
+ if (!entries.containsKey(user))
+ {
+ throw new NoSuchUserException(user);
+ }
+
+ String[] fields = (String[]) entries.get(user); // get the existing entry
+ fields[1] = passwd; // modify the password field
+ entries.remove(user); // delete the existing entry
+ entries.put(user, fields); // add the new entry
+
+ savePasswd();
+ }
+
+ public synchronized String[] lookup(String user) throws IOException
+ {
+ checkCurrent();
+ if (!entries.containsKey(user))
+ {
+ throw new NoSuchUserException(user);
+ }
+ return (String[]) entries.get(user);
+ }
+
+ public synchronized boolean contains(String s) throws IOException
+ {
+ checkCurrent();
+ return entries.containsKey(s);
+ }
+
+ //----------------------------------------------------------------//
+
+ private synchronized void update() throws IOException
+ {
+ lastmod = passwdFile.lastModified();
+ readPasswd(new FileInputStream(passwdFile));
+ }
+
+ private void checkCurrent() throws IOException
+ {
+ if (passwdFile.lastModified() > lastmod)
+ {
+ update();
+ }
+ }
+
+ private synchronized void readPasswd(InputStream in) throws IOException
+ {
+ BufferedReader din = new BufferedReader(new InputStreamReader(in));
+ String line;
+ entries = new Hashtable();
+ String[] fields = new String[7];
+ while ((line = din.readLine()) != null)
+ {
+ StringTokenizer st = new StringTokenizer(line, ":", true);
+ try
+ {
+ fields[0] = st.nextToken(); // username
+ st.nextToken();
+
+ fields[1] = st.nextToken(); // passwd
+ if (fields[1].equals(":"))
+ {
+ fields[1] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[2] = st.nextToken(); // uid
+ if (fields[2].equals(":"))
+ {
+ fields[2] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[3] = st.nextToken(); // gid
+ if (fields[3].equals(":"))
+ {
+ fields[3] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[4] = st.nextToken(); // gecos
+ if (fields[4].equals(":"))
+ {
+ fields[4] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[5] = st.nextToken(); // dir
+ if (fields[5].equals(":"))
+ {
+ fields[5] = "";
+ }
+ else
+ {
+ st.nextToken();
+ }
+
+ fields[6] = st.nextToken(); // shell
+ if (fields[6].equals(":"))
+ {
+ fields[6] = "";
+ }
+ }
+ catch (NoSuchElementException ignored)
+ {
+ continue;
+ }
+
+ entries.put(fields[0], fields);
+ }
+ }
+
+ private synchronized void savePasswd() throws IOException
+ {
+ if (passwdFile != null)
+ {
+ FileOutputStream fos = new FileOutputStream(passwdFile);
+ PrintWriter pw = null;
+ try
+ {
+ pw = new PrintWriter(fos);
+ String key;
+ String[] fields;
+ StringBuffer sb;
+ Enumeration keys = entries.keys();
+ while (keys.hasMoreElements())
+ {
+ key = (String) keys.nextElement();
+ fields = (String[]) entries.get(key);
+ sb = new StringBuffer(fields[0]);
+ for (int i = 1; i < fields.length; i++)
+ {
+ sb.append(":" + fields[i]);
+ }
+ pw.println(sb.toString());
+ }
+ }
+ finally
+ {
+ if (pw != null)
+ {
+ try
+ {
+ pw.flush();
+ }
+ finally
+ {
+ pw.close();
+ }
+ }
+ if (fos != null)
+ {
+ try
+ {
+ fos.close();
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ lastmod = passwdFile.lastModified();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java b/gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java
new file mode 100644
index 000000000..9882ce9bb
--- /dev/null
+++ b/gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java
@@ -0,0 +1,206 @@
+/* PlainAuthInfoProvider.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.plain;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.IAuthInfoProvider;
+import gnu.javax.crypto.sasl.NoSuchUserException;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.sasl.AuthenticationException;
+
+/**
+ * The PLAIN mechanism authentication information provider implementation.
+ */
+public class PlainAuthInfoProvider implements IAuthInfoProvider, PlainRegistry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private PasswordFile passwordFile = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-args constrcutor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // IAuthInfoProvider interface implementation
+ // -------------------------------------------------------------------------
+
+ public void activate(Map context) throws AuthenticationException
+ {
+ try
+ {
+ if (context == null)
+ {
+ passwordFile = new PasswordFile();
+ }
+ else
+ {
+ String pfn = (String) context.get(PASSWORD_FILE);
+ if (pfn == null)
+ {
+ passwordFile = new PasswordFile();
+ }
+ else
+ {
+ passwordFile = new PasswordFile(pfn);
+ }
+ }
+ }
+ catch (IOException x)
+ {
+ throw new AuthenticationException("activate()", x);
+ }
+ }
+
+ public void passivate() throws AuthenticationException
+ {
+ passwordFile = null;
+ }
+
+ public boolean contains(String userName) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("contains()",
+ new IllegalStateException());
+ }
+ boolean result = false;
+ try
+ {
+ result = passwordFile.contains(userName);
+ }
+ catch (IOException x)
+ {
+ throw new AuthenticationException("contains()", x);
+ }
+ return result;
+ }
+
+ public Map lookup(Map userID) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("lookup()",
+ new IllegalStateException());
+ }
+ Map result = new HashMap();
+ try
+ {
+ String userName = (String) userID.get(Registry.SASL_USERNAME);
+ if (userName == null)
+ {
+ throw new NoSuchUserException("");
+ }
+ String[] data = passwordFile.lookup(userName);
+ result.put(Registry.SASL_USERNAME, data[0]);
+ result.put(Registry.SASL_PASSWORD, data[1]);
+ result.put(UID_FIELD, data[2]);
+ result.put(GID_FIELD, data[3]);
+ result.put(GECOS_FIELD, data[4]);
+ result.put(DIR_FIELD, data[5]);
+ result.put(SHELL_FIELD, data[6]);
+ }
+ catch (Exception x)
+ {
+ if (x instanceof AuthenticationException)
+ {
+ throw (AuthenticationException) x;
+ }
+ else
+ {
+ throw new AuthenticationException("lookup()", x);
+ }
+ }
+ return result;
+ }
+
+ public void update(Map userCredentials) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("update()",
+ new IllegalStateException());
+ }
+ try
+ {
+ String userName = (String) userCredentials.get(Registry.SASL_USERNAME);
+ String password = (String) userCredentials.get(Registry.SASL_PASSWORD);
+ String uid = (String) userCredentials.get(UID_FIELD);
+ String gid = (String) userCredentials.get(GID_FIELD);
+ String gecos = (String) userCredentials.get(GECOS_FIELD);
+ String dir = (String) userCredentials.get(DIR_FIELD);
+ String shell = (String) userCredentials.get(SHELL_FIELD);
+ if (uid == null || gid == null || gecos == null || dir == null
+ || shell == null)
+ {
+ passwordFile.changePasswd(userName, password);
+ }
+ else
+ {
+ String[] attributes = new String[] { uid, gid, gecos, dir, shell };
+ passwordFile.add(userName, password, attributes);
+ }
+ }
+ catch (Exception x)
+ {
+ if (x instanceof AuthenticationException)
+ {
+ throw (AuthenticationException) x;
+ }
+ else
+ {
+ throw new AuthenticationException("update()", x);
+ }
+ }
+ }
+
+ public Map getConfiguration(String mode) throws AuthenticationException
+ {
+ throw new AuthenticationException("", new UnsupportedOperationException());
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/plain/PlainClient.java b/gnu/javax/crypto/sasl/plain/PlainClient.java
new file mode 100644
index 000000000..066db3770
--- /dev/null
+++ b/gnu/javax/crypto/sasl/plain/PlainClient.java
@@ -0,0 +1,193 @@
+/* PlainClient.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.plain;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.ClientMechanism;
+
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+
+/**
+ * <p>The PLAIN SASL client-side mechanism.</p>
+ */
+public class PlainClient extends ClientMechanism implements SaslClient
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public PlainClient()
+ {
+ super(Registry.SASL_PLAIN_MECHANISM);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods implementation -----------------------------------------
+
+ protected void initMechanism() throws SaslException
+ {
+ }
+
+ protected void resetMechanism() throws SaslException
+ {
+ }
+
+ // javax.security.sasl.SaslClient interface implementation -----------------
+
+ public boolean hasInitialResponse()
+ {
+ return true;
+ }
+
+ public byte[] evaluateChallenge(final byte[] challenge) throws SaslException
+ {
+ try
+ {
+ final String username;
+ final char[] password;
+ Callback[] callbacks;
+
+ if ((!properties.containsKey(Registry.SASL_USERNAME))
+ && (!properties.containsKey(Registry.SASL_PASSWORD)))
+ {
+ callbacks = new Callback[2];
+
+ final NameCallback nameCB;
+ final String defaultName = System.getProperty("user.name");
+ if (defaultName == null)
+ {
+ nameCB = new NameCallback("username: ");
+ }
+ else
+ {
+ nameCB = new NameCallback("username: ", defaultName);
+ }
+ final PasswordCallback pwdCB = new PasswordCallback("password: ",
+ false);
+ callbacks[0] = nameCB;
+ callbacks[1] = pwdCB;
+ this.handler.handle(callbacks);
+ username = nameCB.getName();
+ password = pwdCB.getPassword();
+ }
+ else
+ {
+ if (properties.containsKey(Registry.SASL_USERNAME))
+ {
+ username = (String) properties.get(Registry.SASL_USERNAME);
+ }
+ else
+ {
+ callbacks = new Callback[1];
+ final NameCallback nameCB;
+ final String defaultName = System.getProperty("user.name");
+ if (defaultName == null)
+ {
+ nameCB = new NameCallback("username: ");
+ }
+ else
+ {
+ nameCB = new NameCallback("username: ", defaultName);
+ }
+ callbacks[0] = nameCB;
+ this.handler.handle(callbacks);
+ username = nameCB.getName();
+ }
+
+ if (properties.containsKey(Registry.SASL_PASSWORD))
+ {
+ password = ((String) properties.get(Registry.SASL_PASSWORD)).toCharArray();
+ }
+ else
+ {
+ callbacks = new Callback[1];
+ final PasswordCallback pwdCB = new PasswordCallback(
+ "password: ",
+ false);
+ callbacks[0] = pwdCB;
+ this.handler.handle(callbacks);
+ password = pwdCB.getPassword();
+ }
+ }
+
+ if (password == null)
+ {
+ throw new SaslException("null password supplied");
+ }
+ final StringBuffer sb = new StringBuffer();
+ if (authorizationID != null)
+ {
+ sb.append(authorizationID);
+ }
+ sb.append('\0');
+ sb.append(username);
+ sb.append('\0');
+ sb.append(password);
+ this.complete = true;
+
+ final byte[] response = sb.toString().getBytes("UTF-8");
+ return response;
+ }
+ catch (Exception x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new SaslException("evaluateChallenge()", x);
+ }
+ }
+
+ protected String getNegotiatedQOP()
+ {
+ return Registry.QOP_AUTH;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/plain/PlainRegistry.java b/gnu/javax/crypto/sasl/plain/PlainRegistry.java
new file mode 100644
index 000000000..0b48c0ad3
--- /dev/null
+++ b/gnu/javax/crypto/sasl/plain/PlainRegistry.java
@@ -0,0 +1,67 @@
+/* PlainRegistry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.plain;
+
+public interface PlainRegistry
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** Name of PLAIN password file property. */
+ String PASSWORD_FILE = "gnu.crypto.sasl.plain.password.file";
+
+ /** Default fully qualified pathname of the PLAIN password file. */
+ String DEFAULT_PASSWORD_FILE = "/etc/tpasswd";
+
+ /** Name of the UID field in the plain password file. */
+ String UID_FIELD = "plain.uid";
+
+ /** Name of the GID field in the plain password file. */
+ String GID_FIELD = "plain.gid";
+
+ /** Name of the GECOS field in the plain password file. */
+ String GECOS_FIELD = "plain.gecos";
+
+ /** Name of the DIR field in the plain password file. */
+ String DIR_FIELD = "plain.dir";
+
+ /** Name of the SHELL field in the plain password file. */
+ String SHELL_FIELD = "plain.shell";
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/plain/PlainServer.java b/gnu/javax/crypto/sasl/plain/PlainServer.java
new file mode 100644
index 000000000..205688473
--- /dev/null
+++ b/gnu/javax/crypto/sasl/plain/PlainServer.java
@@ -0,0 +1,196 @@
+/* PlainServer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.plain;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.sasl.NoSuchUserException;
+import gnu.javax.crypto.sasl.ServerMechanism;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+/**
+ * <p>The PLAIN SASL server-side mechanism.</p>
+ */
+public class PlainServer extends ServerMechanism implements SaslServer
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public PlainServer()
+ {
+ super(Registry.SASL_PLAIN_MECHANISM);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods implementation -----------------------------------------
+
+ protected void initMechanism() throws SaslException
+ {
+ }
+
+ protected void resetMechanism() throws SaslException
+ {
+ }
+
+ // javax.security.sasl.SaslServer interface implementation -----------------
+
+ public byte[] evaluateResponse(final byte[] response) throws SaslException
+ {
+ if (response == null)
+ {
+ return null;
+ }
+ try
+ {
+ final String nullStr = new String("\0");
+ final StringTokenizer strtok = new StringTokenizer(
+ new String(response),
+ nullStr, true);
+
+ authorizationID = strtok.nextToken();
+ if (!authorizationID.equals(nullStr))
+ {
+ strtok.nextToken();
+ }
+ else
+ {
+ authorizationID = null;
+ }
+ final String id = strtok.nextToken();
+ if (id.equals(nullStr))
+ {
+ throw new SaslException("No identity given");
+ }
+ if (authorizationID == null)
+ {
+ authorizationID = id;
+ }
+ if ((!authorizationID.equals(nullStr)) && (!authorizationID.equals(id)))
+ {
+ throw new SaslException("Delegation not supported");
+ }
+ strtok.nextToken();
+ final byte[] pwd;
+ try
+ {
+ pwd = strtok.nextToken().getBytes("UTF-8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new SaslException("evaluateResponse()", x);
+ }
+ if (pwd == null)
+ {
+ throw new SaslException("No password given");
+ }
+ final byte[] password;
+ try
+ {
+ password = new String(lookupPassword(id)).getBytes("UTF-8");
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new SaslException("evaluateResponse()", x);
+ }
+ if (!Arrays.equals(pwd, password))
+ {
+ throw new SaslException("Password incorrect");
+ }
+ this.complete = true;
+ return null;
+ }
+ catch (NoSuchElementException x)
+ {
+ throw new SaslException("evaluateResponse()", x);
+ }
+ }
+
+ protected String getNegotiatedQOP()
+ {
+ return Registry.QOP_AUTH;
+ }
+
+ // other methods -----------------------------------------------------------
+
+ private char[] lookupPassword(final String userName) throws SaslException
+ {
+ try
+ {
+ if (!authenticator.contains(userName))
+ {
+ throw new NoSuchUserException(userName);
+ }
+ final Map userID = new HashMap();
+ userID.put(Registry.SASL_USERNAME, userName);
+ final Map credentials = authenticator.lookup(userID);
+ final String password = (String) credentials.get(Registry.SASL_PASSWORD);
+ if (password == null)
+ {
+ throw new SaslException("lookupPassword()", new InternalError());
+ }
+ return password.toCharArray();
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new SaslException("lookupPassword()", x);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/CALG.java b/gnu/javax/crypto/sasl/srp/CALG.java
new file mode 100644
index 000000000..6215783d6
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/CALG.java
@@ -0,0 +1,292 @@
+/* CALG.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.assembly.Assembly;
+import gnu.javax.crypto.assembly.Cascade;
+import gnu.javax.crypto.assembly.Direction;
+import gnu.javax.crypto.assembly.Stage;
+import gnu.javax.crypto.assembly.Transformer;
+import gnu.javax.crypto.assembly.TransformerException;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+import gnu.javax.crypto.pad.IPad;
+import gnu.javax.crypto.pad.PadFactory;
+import gnu.javax.crypto.sasl.ConfidentialityException;
+
+import java.util.HashMap;
+
+import javax.security.sasl.SaslException;
+
+/**
+ * <p>A Factory class that returns CALG (Confidentiality Algorithm) instances
+ * that operate as described in the draft-burdis-cat-sasl-srp-08.</p>
+ *
+ * <p>The designated CALG block cipher should be used in OFB (Output Feedback
+ * Block) mode in the ISO variant, as described in <i>The Handbook of Applied
+ * Cryptography</i>, algorithm 7.20.</p>
+ *
+ * <p>Let <code>k</code> be the block size of the chosen symmetric key block
+ * cipher algorithm; e.g. for AES this is <code>128</code> bits or <code>16</code>
+ * octets. The OFB mode used shall be of length/size <code>k</code>.</p>
+ *
+ * <p>It is recommended that block ciphers operating in OFB mode be used with an
+ * Initial Vector (the mode's IV). In such a mode of operation - OFB with key
+ * re-use - the IV need not be secret. For the mechanism in question the IVs
+ * shall be a random octet sequence of <code>k</code> bytes.</p>
+ *
+ * The input data to the confidentiality protection algorithm shall be
+ * a multiple of the symmetric cipher block size <code>k</code>. When the input
+ * length is not a multiple of <code>k</code> octets, the data shall be padded
+ * according to the following scheme:</p>
+ *
+ * <p>Assuming the length of the input is <code>l</code> octets,
+ * <code>(k - (l mod k))</code> octets, all having the value
+ * <code>(k - (l mod k))</code>, shall be appended to the original data. In
+ * other words, the input is padded at the trailing end with one of the
+ * following sequences:</p>
+ *
+ * <pre>
+ *
+ * 01 -- if l mod k = k-1
+ * 02 02 -- if l mod k = k-2
+ * ...
+ * ...
+ * ...
+ * k k ... k k -- if l mod k = 0
+ *</pre>
+ *
+ * <p>The padding can be removed unambiguously since all input is padded and no
+ * padding sequence is a suffix of another. This padding method is well-defined
+ * if and only if <code>k &lt; 256</code> octets, which is the case with
+ * symmetric key block ciphers today, and in the forseeable future.</p>
+ */
+public final class CALG
+{
+
+ // Constants and variables
+ // --------------------------------------------------------------------------
+
+ private Assembly assembly;
+
+ private Object modeNdx; // initialisation key of the cascade's attributes
+
+ private int blockSize; // the underlying cipher's blocksize == IV length
+
+ private int keySize; // the underlying cipher's key size (in bytes).
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /** Private constructor to enforce instantiation through Factory method. */
+ private CALG(final int blockSize, final int keySize, final Object modeNdx,
+ final Assembly assembly)
+ {
+ super();
+
+ this.blockSize = blockSize;
+ this.keySize = keySize;
+ this.modeNdx = modeNdx;
+ this.assembly = assembly;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a SASL-SRP CALG implementation.</p>
+ *
+ * @param algorithm the name of the symmetric cipher algorithm.
+ * @return an instance of this object.
+ */
+ static synchronized CALG getInstance(final String algorithm)
+ {
+ final IBlockCipher cipher = CipherFactory.getInstance(algorithm);
+ final int blockSize = cipher.defaultBlockSize();
+ final int keySize = cipher.defaultKeySize();
+ final Cascade ofbCipher = new Cascade();
+ final Object modeNdx = ofbCipher.append(Stage.getInstance(
+ ModeFactory.getInstance(
+ Registry.OFB_MODE,
+ cipher,
+ blockSize),
+ Direction.FORWARD));
+ final IPad pkcs7 = PadFactory.getInstance(Registry.PKCS7_PAD);
+ // the passed IV may be longer that what we need. ensure correct length
+ // byte[] realIV = null;
+ // if (iv.length == blockSize) {
+ // realIV = iv;
+ // } else {
+ // realIV = new byte[blockSize];
+ // if (iv.length > blockSize) {
+ // System.arraycopy(iv, 0, realIV, 0, blockSize);
+ // } else { // shouldnt happen
+ // System.arraycopy(iv, 0, realIV, 0, iv.length);
+ // }
+ // }
+
+ // HashMap modeAttributes = new HashMap();
+ // modeAttributes.put(IBlockCipher.KEY_MATERIAL, K.clone());
+ // modeAttributes.put(IMode.IV, realIV);
+
+ final Assembly asm = new Assembly();
+ asm.addPreTransformer(Transformer.getCascadeTransformer(ofbCipher));
+ asm.addPreTransformer(Transformer.getPaddingTransformer(pkcs7));
+
+ // HashMap attributes = new HashMap();
+ // attributes.put(Assembly.DIRECTION, dir);
+ // attributes.put(modeNdx, modeAttributes);
+ // try {
+ // asm.init(attributes);
+ // } catch (TransformerException x) {
+ // throw new SaslException("getInstance()", x);
+ // }
+
+ return new CALG(blockSize, keySize, modeNdx, asm);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Initialises a SASL-SRP CALG implementation.</p>
+ *
+ * @param kdf the key derivation function.
+ * @param iv the initial vector value to use.
+ * @param dir whether this CALG is used for encryption or decryption.
+ */
+ // public void init(byte[] K, byte[] iv, Direction dir) throws SaslException {
+ public void init(final KDF kdf, final byte[] iv, final Direction dir)
+ throws SaslException
+ {
+ // IBlockCipher cipher = CipherFactory.getInstance(algorithm);
+ // int blockSize = cipher.defaultBlockSize();
+ // Cascade ofbCipher = new Cascade();
+ // Object modeNdx = ofbCipher.append(
+ // Stage.getInstace(
+ // ModeFactory.getInstance(Registry.OFB_MODE, cipher, blockSize),
+ // Direction.FORWARD));
+ // IPad pkcs7 = PadFactory.getInstance(Registry.PKCS7_PAD);
+ // the passed IV may be longer that what we need. ensure correct length
+ final byte[] realIV;
+ if (iv.length == blockSize)
+ {
+ realIV = iv;
+ }
+ else
+ {
+ realIV = new byte[blockSize];
+ if (iv.length > blockSize)
+ {
+ System.arraycopy(iv, 0, realIV, 0, blockSize);
+ }
+ else
+ { // shouldnt happen
+ System.arraycopy(iv, 0, realIV, 0, iv.length);
+ }
+ }
+
+ final HashMap modeAttributes = new HashMap();
+ // modeAttributes.put(IBlockCipher.KEY_MATERIAL, K.clone());
+ final byte[] sk = kdf.derive(keySize);
+ modeAttributes.put(IBlockCipher.KEY_MATERIAL, sk);
+ //System.out.println("**** Initialised CALG with: "+gnu.crypto.util.Util.dumpString(sk));
+ modeAttributes.put(IMode.IV, realIV);
+
+ // Assembly asm = new Assembly();
+ // asm.addPreTransformer(Transformer.getCascadeTransformer(ofbCipher));
+ // asm.addPreTransformer(Transformer.getPaddingTransformer(pkcs7));
+
+ final HashMap attributes = new HashMap();
+ attributes.put(Assembly.DIRECTION, dir);
+ attributes.put(modeNdx, modeAttributes);
+ try
+ {
+ // asm.init(attributes);
+ assembly.init(attributes);
+ }
+ catch (TransformerException x)
+ {
+ throw new SaslException("getInstance()", x);
+ }
+
+ // return new CALG(asm);
+ }
+
+ /**
+ * <p>Encrypts or decrypts, depending on the mode already set, a designated
+ * array of bytes and returns the result.</p>
+ *
+ * @param data the data to encrypt/decrypt.
+ * @return the decrypted/encrypted result.
+ * @throws ConfidentialityException if an exception occurs duirng the process.
+ */
+ public byte[] doFinal(final byte[] data) throws ConfidentialityException
+ {
+ return doFinal(data, 0, data.length);
+ }
+
+ /**
+ * <p>Encrypts or decrypts, depending on the mode already set, a designated
+ * array of bytes and returns the result.</p>
+ *
+ * @param data the data to encrypt/decrypt.
+ * @param offset where to start in <code>data</code>.
+ * @param length how many bytes to consider in <code>data</code>.
+ * @return the decrypted/encrypted result.
+ * @throws ConfidentialityException if an exception occurs duirng the process.
+ */
+ public byte[] doFinal(final byte[] data, final int offset, final int length)
+ throws ConfidentialityException
+ {
+ final byte[] result;
+ try
+ {
+ result = assembly.lastUpdate(data, offset, length);
+ }
+ catch (TransformerException x)
+ {
+ throw new ConfidentialityException("doFinal()", x);
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/ClientStore.java b/gnu/javax/crypto/sasl/srp/ClientStore.java
new file mode 100644
index 000000000..ce16f4aa7
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/ClientStore.java
@@ -0,0 +1,173 @@
+/* ClientStore.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import java.util.HashMap;
+
+/**
+ * <p>The client-side implementation of the SRP security context store.</p>
+ */
+public class ClientStore
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The underlying singleton. */
+ private static ClientStore singleton = null;
+
+ /** The map of uid --> SASL Security Context record. */
+ private static final HashMap uid2ssc = new HashMap();
+
+ /** The map of sid --> Session timing record. */
+ private static final HashMap uid2ttl = new HashMap();
+
+ /** A synchronisation lock. */
+ private static final Object lock = new Object();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Private constructor to enforce Singleton pattern. */
+ private ClientStore()
+ {
+ super();
+
+ // TODO: add a cleaning timer thread
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the classloader Singleton.</p>
+ *
+ * @return the classloader Singleton instance.
+ */
+ static synchronized final ClientStore instance()
+ {
+ if (singleton == null)
+ {
+ singleton = new ClientStore();
+ }
+ return singleton;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns a boolean flag indicating if the designated client's session is
+ * still alive or not.</p>
+ *
+ * @param uid the identifier of the client whose session to check.
+ * @return <code>true</code> if the designated client's session is still
+ * alive. <code>false</code> otherwise.
+ */
+ boolean isAlive(final String uid)
+ {
+ final boolean result;
+ synchronized (lock)
+ {
+ final Object obj = uid2ssc.get(uid);
+ result = (obj != null);
+ if (result)
+ { // is it still alive?
+ final StoreEntry sto = (StoreEntry) uid2ttl.get(uid);
+ if (!sto.isAlive())
+ { // invalidate it
+ uid2ssc.remove(uid);
+ uid2ttl.remove(uid);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * <p>Records a mapping between a client's unique identifier and its security
+ * context.</p>
+ *
+ * @param uid the unique identifier of the SRP client for which the session
+ * is to be cached.
+ * @param ttl the session's Time-To-Live indicator (in seconds).
+ * @param ctx the client's security context.
+ */
+ void cacheSession(final String uid, final int ttl, final SecurityContext ctx)
+ {
+ synchronized (lock)
+ {
+ uid2ssc.put(uid, ctx);
+ uid2ttl.put(uid, new StoreEntry(ttl));
+ }
+ }
+
+ /**
+ * <p>Removes the mapping between the designated SRP client unique identifier
+ * and the its session security context (and other timing information).</p>
+ *
+ * @param uid the identifier of the client whose session is to invalidate.
+ */
+ void invalidateSession(final String uid)
+ {
+ synchronized (lock)
+ {
+ uid2ssc.remove(uid);
+ uid2ttl.remove(uid);
+ }
+ }
+
+ /**
+ * <p>Returns an SRP client's security context record mapped by that client's
+ * unique identifier.</p>
+ *
+ * @param uid the identifier of the client whose session is to restore.
+ * @return the SRP client's security context.
+ */
+ SecurityContext restoreSession(final String uid)
+ {
+ final SecurityContext result;
+ synchronized (lock)
+ {
+ result = (SecurityContext) uid2ssc.remove(uid);
+ uid2ttl.remove(uid);
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/IALG.java b/gnu/javax/crypto/sasl/srp/IALG.java
new file mode 100644
index 000000000..cfaf22b1e
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/IALG.java
@@ -0,0 +1,159 @@
+/* IALG.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+
+import javax.security.sasl.SaslException;
+
+/**
+ * <p>A Factory class that returns IALG (Integrity Algorithm) instances that
+ * operate as described in the draft-burdis-cat-sasl-srp-04 and later.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public final class IALG implements Cloneable
+{
+
+ // Constants and variables
+ // --------------------------------------------------------------------------
+
+ private IMac hmac;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /** Private constructor to enforce instantiation through Factory method. */
+ private IALG(final IMac hmac)
+ {
+ super();
+
+ this.hmac = hmac;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a SASL-SRP IALG implementation.</p>
+ *
+ * @param algorithm the name of the HMAC algorithm.
+ * @return an instance of this object.
+ */
+ static synchronized IALG getInstance(final String algorithm)
+ throws SaslException
+ {
+ final IMac hmac;
+ hmac = MacFactory.getInstance(algorithm);
+ if (hmac == null)
+ {
+ throw new SaslException("getInstance()",
+ new NoSuchAlgorithmException(algorithm));
+ }
+ // try {
+ // byte[] sk = (byte[]) K.clone();
+ // HashMap map = new HashMap();
+ // map.put(IMac.MAC_KEY_MATERIAL, sk);
+ // hmac.init(map);
+ // } catch (InvalidKeyException x) {
+ // throw new SaslException("getInstance()", x);
+ // }
+ return new IALG(hmac);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Cloneable interface implementation --------------------------------------
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ return new IALG((IMac) hmac.clone());
+ }
+
+ // other methdds -----------------------------------------------------------
+
+ // public void init(final byte[] K) throws SaslException {
+ public void init(final KDF kdf) throws SaslException
+ {
+ try
+ {
+ // final byte[] sk = (byte[]) K.clone();
+ final byte[] sk = kdf.derive(hmac.macSize());
+ final HashMap map = new HashMap();
+ map.put(IMac.MAC_KEY_MATERIAL, sk);
+ hmac.init(map);
+ //System.out.println("**** Initialised IALG with: "+gnu.crypto.util.Util.dumpString(sk));
+ }
+ catch (InvalidKeyException x)
+ {
+ throw new SaslException("getInstance()", x);
+ }
+ }
+
+ public void update(final byte[] data)
+ {
+ hmac.update(data, 0, data.length);
+ }
+
+ public void update(final byte[] data, final int offset, final int length)
+ {
+ hmac.update(data, offset, length);
+ }
+
+ public byte[] doFinal()
+ {
+ return hmac.digest();
+ }
+
+ /**
+ * <p>Returns the length (in bytes) of this SASL SRP Integrity Algorithm.</p>
+ *
+ * @return the length, in bytes, of this integrity protection algorithm.
+ */
+ public int length()
+ {
+ return hmac.macSize();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/KDF.java b/gnu/javax/crypto/sasl/srp/KDF.java
new file mode 100644
index 000000000..161ec78b6
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/KDF.java
@@ -0,0 +1,157 @@
+/* KDF.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.java.security.Registry;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.prng.UMacGenerator;
+
+import java.util.HashMap;
+import java.util.Random;
+
+/**
+ * <p>The SASL-SRP KDF implementation, which is also used, depending on how it
+ * was instantiated, as a secure Pseudo Random Number Generator.</p>
+ */
+public class KDF
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int AES_BLOCK_SIZE = 16; // default block size for the AES
+
+ private static final int AES_KEY_SIZE = 16; // default key size for the AES
+
+ /** The shared secret K to use. */
+ // private byte[] keyMaterial;
+ /** The underlying UMAC Generator instance. */
+ private UMacGenerator umac = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Constructs an instance of the <code>KDF</code> initialised with the
+ * designated shared secret bytes.</p>
+ *
+ * @param keyMaterial the SASL SRP shared secret (K) bytes.
+ */
+ private KDF(final byte[] keyMaterial, final int ndx)
+ {
+ super();
+
+ // if (ndx != 0) {
+ // this.keyMaterial = (byte[]) keyMaterial.clone();
+ // }
+ final HashMap map = new HashMap();
+ map.put(UMacGenerator.CIPHER, Registry.AES_CIPHER);
+ map.put(UMacGenerator.INDEX, new Integer(ndx));
+ map.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(AES_BLOCK_SIZE));
+ final byte[] key = new byte[AES_KEY_SIZE];
+ System.arraycopy(keyMaterial, 0, key, 0, AES_KEY_SIZE);
+ map.put(IBlockCipher.KEY_MATERIAL, key);
+
+ umac = new UMacGenerator();
+ umac.init(map);
+ //System.out.println("**** Initialised KDF with: "+gnu.crypto.util.Util.dumpString(key));
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A Factory mehod that returns an instance of a <code>KDF</code> based on
+ * supplied seed data.</p>
+ *
+ * @param K the SASL SRP shared secret for a <code>KDF</code> to be used for
+ * <i>CALG</i> and <i>IALG</i> setup. <code>null</code> otherwise.
+ * @return an instance of a <code>KDF</code>.
+ */
+ static final KDF getInstance(final byte[] K)
+ {
+ int ndx = -1;
+ final byte[] keyMaterial;
+ if (K != null)
+ {
+ keyMaterial = K;
+ ndx = 0;
+ }
+ else
+ {
+ keyMaterial = new byte[AES_BLOCK_SIZE];
+ ndx = new Random ().nextInt (256); // XXX does this need to be secure?
+ }
+ return new KDF(keyMaterial, ndx);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns a designated number of bytes suitable for use in the SASL SRP
+ * mechanism.</p>
+ *
+ * @param length the number of bytes needed.
+ * @return a byte array containing the generated/selected bytes.
+ */
+ public synchronized byte[] derive(final int length)
+ {
+ final byte[] result = new byte[length];
+ // if (keyMaterial == null || length > keyMaterial.length) {
+ try
+ {
+ umac.nextBytes(result, 0, length);
+ }
+ catch (IllegalStateException x)
+ { // should not happen
+ x.printStackTrace(System.err);
+ }
+ catch (LimitReachedException x)
+ { // idem
+ x.printStackTrace(System.err);
+ }
+ // } else {
+ // System.arraycopy(keyMaterial, 0, result, 0, length);
+ // }
+
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/PasswordFile.java b/gnu/javax/crypto/sasl/srp/PasswordFile.java
new file mode 100644
index 000000000..1628a4167
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/PasswordFile.java
@@ -0,0 +1,699 @@
+/* PasswordFile.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.key.srp6.SRPAlgorithm;
+import gnu.javax.crypto.sasl.NoSuchUserException;
+import gnu.javax.crypto.sasl.UserAlreadyExistsException;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * <p>The implementation of SRP password files.</p>
+ *
+ * <p>For SRP, there are three (3) files:
+ * <ol>
+ * <li>The password configuration file: tpasswd.conf. It contains the pairs
+ * &lt;N,g> indexed by a number for each pair used for a user. By default,
+ * this file's pathname is constructed from the base password file pathname
+ * by prepending it with the ".conf" suffix.</li>
+ *
+ * <li>The base password file: tpasswd. It contains the related password
+ * entries for all the users with values computed using SRP's default
+ * message digest algorithm: SHA-1 (with 160-bit output block size).</li>
+ *
+ * <li>The extended password file: tpasswd2. Its name, by default, is
+ * constructed by adding the suffix "2" to the fully qualified pathname of
+ * the base password file. It contains, in addition to the same fields as
+ * the base password file, albeit with a different verifier value, an extra
+ * field identifying the message digest algorithm used to compute this
+ * (verifier) value.</li>
+ * </ol></p>
+ *
+ * <p>This implementation assumes the following message digest algorithm codes:
+ * <ul>
+ * <li>0: the default hash algorithm, which is SHA-1 (or its alias SHA-160).</li>
+ * <li>1: MD5.</li>
+ * <li>2: RIPEMD-128.</li>
+ * <li>3: RIPEMD-160.</li>
+ * <li>4: SHA-256.</li>
+ * <li>5: SHA-384.</li>
+ * <li>6: SHA-512.</li>
+ * </ul></p>
+ *
+ * <p><b>IMPORTANT:</b> This method computes the verifiers as described in
+ * RFC-2945, which differs from the description given on the web page for
+ * SRP-6.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
+ * Thomas J. Wu.</li>
+ * </ol>
+ */
+public class PasswordFile
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // names of property keys used in this class
+ private static final String USER_FIELD = "user";
+
+ private static final String VERIFIERS_FIELD = "verifier";
+
+ private static final String SALT_FIELD = "salt";
+
+ private static final String CONFIG_FIELD = "config";
+
+ private static String DEFAULT_FILE;
+ static
+ {
+ DEFAULT_FILE = System.getProperty(SRPRegistry.PASSWORD_FILE,
+ SRPRegistry.DEFAULT_PASSWORD_FILE);
+ }
+
+ /** The SRP algorithm instances used by this object. */
+ private static final HashMap srps;
+ static
+ {
+ final HashMap map = new HashMap(SRPRegistry.SRP_ALGORITHMS.length);
+ // The first entry MUST exist. The others are optional.
+ map.put("0", SRP.instance(SRPRegistry.SRP_ALGORITHMS[0]));
+ for (int i = 1; i < SRPRegistry.SRP_ALGORITHMS.length; i++)
+ {
+ try
+ {
+ map.put(String.valueOf(i),
+ SRP.instance(SRPRegistry.SRP_ALGORITHMS[i]));
+ }
+ catch (Exception x)
+ {
+ System.err.println("Ignored: " + x);
+ x.printStackTrace(System.err);
+ }
+ }
+ srps = map;
+ }
+
+ private String confName, pwName, pw2Name;
+
+ private File configFile, passwdFile, passwd2File;
+
+ private long lastmodPasswdFile, lastmodPasswd2File;
+
+ private HashMap entries = new HashMap();
+
+ private HashMap configurations = new HashMap();
+
+ // default N values to use when creating a new password.conf file
+ private static final BigInteger[] Nsrp = new BigInteger[] {
+ SRPAlgorithm.N_2048,
+ SRPAlgorithm.N_1536,
+ SRPAlgorithm.N_1280,
+ SRPAlgorithm.N_1024,
+ SRPAlgorithm.N_768,
+ SRPAlgorithm.N_640,
+ SRPAlgorithm.N_512 };
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public PasswordFile() throws IOException
+ {
+ this(DEFAULT_FILE);
+ }
+
+ public PasswordFile(final File pwFile) throws IOException
+ {
+ this(pwFile.getAbsolutePath());
+ }
+
+ public PasswordFile(final String pwName) throws IOException
+ {
+ this(pwName, pwName + "2", pwName + ".conf");
+ }
+
+ public PasswordFile(final String pwName, final String confName)
+ throws IOException
+ {
+ this(pwName, pwName + "2", confName);
+ }
+
+ public PasswordFile(final String pwName, final String pw2Name,
+ final String confName) throws IOException
+ {
+ super();
+
+ this.pwName = pwName;
+ this.pw2Name = pw2Name;
+ this.confName = confName;
+
+ readOrCreateConf();
+ update();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns a string representing the decimal value of an integer
+ * identifying the message digest algorithm to use for the SRP computations.
+ * </p>
+ *
+ * @param mdName the canonical name of a message digest algorithm.
+ * @return a string representing the decimal value of an ID for that
+ * algorithm.
+ */
+ private static final String nameToID(final String mdName)
+ {
+ if (Registry.SHA_HASH.equalsIgnoreCase(mdName)
+ || Registry.SHA1_HASH.equalsIgnoreCase(mdName)
+ || Registry.SHA160_HASH.equalsIgnoreCase(mdName))
+ {
+ return "0";
+ }
+ else if (Registry.MD5_HASH.equalsIgnoreCase(mdName))
+ {
+ return "1";
+ }
+ else if (Registry.RIPEMD128_HASH.equalsIgnoreCase(mdName))
+ {
+ return "2";
+ }
+ else if (Registry.RIPEMD160_HASH.equalsIgnoreCase(mdName))
+ {
+ return "3";
+ }
+ else if (Registry.SHA256_HASH.equalsIgnoreCase(mdName))
+ {
+ return "4";
+ }
+ else if (Registry.SHA384_HASH.equalsIgnoreCase(mdName))
+ {
+ return "5";
+ }
+ else if (Registry.SHA512_HASH.equalsIgnoreCase(mdName))
+ {
+ return "6";
+ }
+ return "0";
+ }
+
+ // SRP password configuration file methods ---------------------------------
+
+ /**
+ * <p>Checks if the current configuration file contains the &lt;N, g> pair
+ * for the designated <code>index</code>.</p>
+ *
+ * @param index a string representing 1-digit identification of an &lt;N, g>
+ * pair used.
+ * @return <code>true</code> if the designated <code>index</code> is that of
+ * a known &lt;N, g> pair, and <code>false</code> otherwise.
+ * @throws IOException if an exception occurs during the process.
+ * @see SRPRegistry#N_2048_BITS
+ * @see SRPRegistry#N_1536_BITS
+ * @see SRPRegistry#N_1280_BITS
+ * @see SRPRegistry#N_1024_BITS
+ * @see SRPRegistry#N_768_BITS
+ * @see SRPRegistry#N_640_BITS
+ * @see SRPRegistry#N_512_BITS
+ */
+ public synchronized boolean containsConfig(final String index)
+ throws IOException
+ {
+ checkCurrent();
+ return configurations.containsKey(index);
+ }
+
+ /**
+ * <p>Returns a pair of strings representing the pair of <code>N</code> and
+ * <code>g</code> MPIs for the designated <code>index</code>.</p>
+ *
+ * @param index a string representing 1-digit identification of an &lt;N, g>
+ * pair to look up.
+ * @return a pair of strings, arranged in an array, where the first (at index
+ * position #0) is the repesentation of the MPI <code>N</code>, and the
+ * second (at index position #1) is the representation of the MPI
+ * <code>g</code>. If the <code>index</code> refers to an unknown pair, then
+ * an empty string array is returned.
+ * @throws IOException if an exception occurs during the process.
+ */
+ public synchronized String[] lookupConfig(final String index)
+ throws IOException
+ {
+ checkCurrent();
+ String[] result = null;
+ if (configurations.containsKey(index))
+ {
+ result = (String[]) configurations.get(index);
+ }
+ return result;
+ }
+
+ // SRP base and extended password configuration files methods --------------
+
+ public synchronized boolean contains(final String user) throws IOException
+ {
+ checkCurrent();
+ return entries.containsKey(user);
+ }
+
+ public synchronized void add(final String user, final String passwd,
+ final byte[] salt, final String index)
+ throws IOException
+ {
+ checkCurrent();
+ if (entries.containsKey(user))
+ {
+ throw new UserAlreadyExistsException(user);
+ }
+ final HashMap fields = new HashMap(4);
+ fields.put(USER_FIELD, user); // 0
+ fields.put(VERIFIERS_FIELD, newVerifiers(user, salt, passwd, index)); // 1
+ fields.put(SALT_FIELD, Util.toBase64(salt)); // 2
+ fields.put(CONFIG_FIELD, index); // 3
+ entries.put(user, fields);
+ savePasswd();
+ }
+
+ public synchronized void changePasswd(final String user, final String passwd)
+ throws IOException
+ {
+ checkCurrent();
+ if (!entries.containsKey(user))
+ {
+ throw new NoSuchUserException(user);
+ }
+ final HashMap fields = (HashMap) entries.get(user);
+ final byte[] salt;
+ try
+ {
+ salt = Util.fromBase64((String) fields.get(SALT_FIELD));
+ }
+ catch (NumberFormatException x)
+ {
+ throw new IOException("Password file corrupt");
+ }
+ final String index = (String) fields.get(CONFIG_FIELD);
+ fields.put(VERIFIERS_FIELD, newVerifiers(user, salt, passwd, index));
+ entries.put(user, fields);
+ savePasswd();
+ }
+
+ public synchronized void savePasswd() throws IOException
+ {
+ final FileOutputStream f1 = new FileOutputStream(passwdFile);
+ final FileOutputStream f2 = new FileOutputStream(passwd2File);
+ PrintWriter pw1 = null;
+ PrintWriter pw2 = null;
+ try
+ {
+ pw1 = new PrintWriter(f1, true);
+ pw2 = new PrintWriter(f2, true);
+ this.writePasswd(pw1, pw2);
+ }
+ finally
+ {
+ if (pw1 != null)
+ {
+ try
+ {
+ pw1.flush();
+ }
+ finally
+ {
+ pw1.close();
+ }
+ }
+ if (pw2 != null)
+ {
+ try
+ {
+ pw2.flush();
+ }
+ finally
+ {
+ pw2.close();
+ }
+ }
+ try
+ {
+ f1.close();
+ }
+ catch (IOException ignored)
+ {
+ }
+ try
+ {
+ f2.close();
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ lastmodPasswdFile = passwdFile.lastModified();
+ lastmodPasswd2File = passwd2File.lastModified();
+ }
+
+ /**
+ * <p>Returns the triplet: verifier, salt and configuration file index, of a
+ * designated user, and a designated message digest algorithm name, as an
+ * array of strings.</p>
+ *
+ * @param user the username.
+ * @param mdName the canonical name of the SRP's message digest algorithm.
+ * @return a string array containing, in this order, the BASE-64 encodings of
+ * the verifier, the salt and the index in the password configuration file of
+ * the MPIs N and g of the designated user.
+ */
+ public synchronized String[] lookup(final String user, final String mdName)
+ throws IOException
+ {
+ checkCurrent();
+ if (!entries.containsKey(user))
+ {
+ throw new NoSuchUserException(user);
+ }
+ final HashMap fields = (HashMap) entries.get(user);
+ final HashMap verifiers = (HashMap) fields.get(VERIFIERS_FIELD);
+ final String salt = (String) fields.get(SALT_FIELD);
+ final String index = (String) fields.get(CONFIG_FIELD);
+ final String verifier = (String) verifiers.get(nameToID(mdName));
+ return new String[] { verifier, salt, index };
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ private synchronized void readOrCreateConf() throws IOException
+ {
+ configurations.clear();
+ final FileInputStream fis;
+ configFile = new File(confName);
+ try
+ {
+ fis = new FileInputStream(configFile);
+ readConf(fis);
+ }
+ catch (FileNotFoundException x)
+ { // create a default one
+ final String g = Util.toBase64(Util.trim(new BigInteger("2")));
+ String index, N;
+ for (int i = 0; i < Nsrp.length; i++)
+ {
+ index = String.valueOf(i + 1);
+ N = Util.toBase64(Util.trim(Nsrp[i]));
+ configurations.put(index, new String[] { N, g });
+ }
+ FileOutputStream f0 = null;
+ PrintWriter pw0 = null;
+ try
+ {
+ f0 = new FileOutputStream(configFile);
+ pw0 = new PrintWriter(f0, true);
+ this.writeConf(pw0);
+ }
+ finally
+ {
+ if (pw0 != null)
+ {
+ pw0.close();
+ }
+ else if (f0 != null)
+ {
+ f0.close();
+ }
+ }
+ }
+ }
+
+ private void readConf(final InputStream in) throws IOException
+ {
+ final BufferedReader din = new BufferedReader(new InputStreamReader(in));
+ String line, index, N, g;
+ StringTokenizer st;
+ while ((line = din.readLine()) != null)
+ {
+ st = new StringTokenizer(line, ":");
+ try
+ {
+ index = st.nextToken();
+ N = st.nextToken();
+ g = st.nextToken();
+ }
+ catch (NoSuchElementException x)
+ {
+ throw new IOException("SRP password configuration file corrupt");
+ }
+ configurations.put(index, new String[] { N, g });
+ }
+ }
+
+ private void writeConf(final PrintWriter pw)
+ {
+ String ndx;
+ String[] mpi;
+ StringBuffer sb;
+ for (Iterator it = configurations.keySet().iterator(); it.hasNext();)
+ {
+ ndx = (String) it.next();
+ mpi = (String[]) configurations.get(ndx);
+ sb = new StringBuffer(ndx).append(":").append(mpi[0]).append(":").append(
+ mpi[1]);
+ pw.println(sb.toString());
+ }
+ }
+
+ /**
+ * <p>Compute the new verifiers for the designated username and password.</p>
+ *
+ * <p><b>IMPORTANT:</b> This method computes the verifiers as described in
+ * RFC-2945, which differs from the description given on the web page for
+ * SRP-6.</p>
+ *
+ * @param user the user's name.
+ * @param s the user's salt.
+ * @param password the user's password
+ * @param index the index of the &lt;N, g> pair to use for this user.
+ * @return a {@link java.util.Map} of user verifiers.
+ * @throws UnsupportedEncodingException if the US-ASCII decoder is not
+ * available on this platform.
+ */
+ private HashMap newVerifiers(final String user, final byte[] s,
+ final String password, final String index)
+ throws UnsupportedEncodingException
+ {
+ // to ensure inter-operability with non-java tools
+ final String[] mpi = (String[]) configurations.get(index);
+ final BigInteger N = new BigInteger(1, Util.fromBase64(mpi[0]));
+ final BigInteger g = new BigInteger(1, Util.fromBase64(mpi[1]));
+
+ final HashMap result = new HashMap(srps.size());
+ BigInteger x, v;
+ SRP srp;
+ for (int i = 0; i < srps.size(); i++)
+ {
+ final String digestID = String.valueOf(i);
+ srp = (SRP) srps.get(digestID);
+ x = new BigInteger(1, srp.computeX(s, user, password));
+ v = g.modPow(x, N);
+ final String verifier = Util.toBase64(v.toByteArray());
+
+ result.put(digestID, verifier);
+ }
+ return result;
+ }
+
+ private synchronized void update() throws IOException
+ {
+ entries.clear();
+
+ FileInputStream fis;
+ passwdFile = new File(pwName);
+ lastmodPasswdFile = passwdFile.lastModified();
+ try
+ {
+ fis = new FileInputStream(passwdFile);
+ readPasswd(fis);
+ }
+ catch (FileNotFoundException ignored)
+ {
+ }
+ passwd2File = new File(pw2Name);
+ lastmodPasswd2File = passwd2File.lastModified();
+ try
+ {
+ fis = new FileInputStream(passwd2File);
+ readPasswd2(fis);
+ }
+ catch (FileNotFoundException ignored)
+ {
+ }
+ }
+
+ private void checkCurrent() throws IOException
+ {
+ if (passwdFile.lastModified() > lastmodPasswdFile
+ || passwd2File.lastModified() > lastmodPasswd2File)
+ {
+ update();
+ }
+ }
+
+ private void readPasswd(final InputStream in) throws IOException
+ {
+ final BufferedReader din = new BufferedReader(new InputStreamReader(in));
+ String line, user, verifier, salt, index;
+ StringTokenizer st;
+ while ((line = din.readLine()) != null)
+ {
+ st = new StringTokenizer(line, ":");
+ try
+ {
+ user = st.nextToken();
+ verifier = st.nextToken();
+ salt = st.nextToken();
+ index = st.nextToken();
+ }
+ catch (NoSuchElementException x)
+ {
+ throw new IOException("SRP base password file corrupt");
+ }
+
+ final HashMap verifiers = new HashMap(6);
+ verifiers.put("0", verifier);
+
+ final HashMap fields = new HashMap(4);
+ fields.put(USER_FIELD, user);
+ fields.put(VERIFIERS_FIELD, verifiers);
+ fields.put(SALT_FIELD, salt);
+ fields.put(CONFIG_FIELD, index);
+
+ entries.put(user, fields);
+ }
+ }
+
+ private void readPasswd2(final InputStream in) throws IOException
+ {
+ final BufferedReader din = new BufferedReader(new InputStreamReader(in));
+ String line, digestID, user, verifier;
+ StringTokenizer st;
+ HashMap fields, verifiers;
+ while ((line = din.readLine()) != null)
+ {
+ st = new StringTokenizer(line, ":");
+ try
+ {
+ digestID = st.nextToken();
+ user = st.nextToken();
+ verifier = st.nextToken();
+ }
+ catch (NoSuchElementException x)
+ {
+ throw new IOException("SRP extended password file corrupt");
+ }
+
+ fields = (HashMap) entries.get(user);
+ if (fields != null)
+ {
+ verifiers = (HashMap) fields.get(VERIFIERS_FIELD);
+ verifiers.put(digestID, verifier);
+ }
+ }
+ }
+
+ private void writePasswd(final PrintWriter pw1, final PrintWriter pw2)
+ throws IOException
+ {
+ String user, digestID;
+ HashMap fields, verifiers;
+ StringBuffer sb1, sb2;
+ Iterator j;
+ final Iterator i = entries.keySet().iterator();
+ while (i.hasNext())
+ {
+ user = (String) i.next();
+ fields = (HashMap) entries.get(user);
+ if (!user.equals(fields.get(USER_FIELD)))
+ {
+ throw new IOException("Inconsistent SRP password data");
+ }
+ verifiers = (HashMap) fields.get(VERIFIERS_FIELD);
+ sb1 = new StringBuffer().append(user).append(":").append(
+ (String) verifiers.get("0")).append(
+ ":").append(
+ (String) fields.get(SALT_FIELD)).append(
+ ":").append(
+ (String) fields.get(CONFIG_FIELD));
+ pw1.println(sb1.toString());
+ // write extended information
+ j = verifiers.keySet().iterator();
+ while (j.hasNext())
+ {
+ digestID = (String) j.next();
+ if (!"0".equals(digestID))
+ {
+ // #0 is the default digest, already present in tpasswd!
+ sb2 = new StringBuffer().append(digestID).append(":").append(
+ user).append(
+ ":").append(
+ (String) verifiers.get(digestID));
+ pw2.println(sb2.toString());
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/SRP.java b/gnu/javax/crypto/sasl/srp/SRP.java
new file mode 100644
index 000000000..d3eb596d4
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/SRP.java
@@ -0,0 +1,285 @@
+/* SRP.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.util.HashMap;
+
+/**
+ * <p>A Factory class that returns SRP Singletons that know all SRP-related
+ * mathematical computations and protocol-related operations for both the
+ * client- and server-sides.</p>
+ */
+public final class SRP
+{
+
+ // Constants and variables
+ // --------------------------------------------------------------------------
+
+ /** The map of already instantiated SRP algorithm instances. */
+ private static final HashMap algorithms = new HashMap();
+
+ private static final byte COLON = (byte) 0x3A;
+
+ /** The underlying message digest algorithm used for all SRP calculations. */
+ private IMessageDigest mda;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /** Trivial private constructor to enforce Singleton pattern. */
+ private SRP(final IMessageDigest mda)
+ {
+ super();
+
+ this.mda = mda;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of this object that uses the designated message
+ * digest algorithm as its digest function.</p>
+ *
+ * @return an instance of this object for the designated digest name.
+ */
+ public static synchronized SRP instance(String mdName)
+ {
+ if (mdName != null)
+ {
+ mdName = mdName.trim().toLowerCase();
+ }
+ if (mdName == null || mdName.equals(""))
+ {
+ mdName = SRPRegistry.SRP_DEFAULT_DIGEST_NAME;
+ }
+ SRP result = (SRP) algorithms.get(mdName);
+ if (result == null)
+ {
+ final IMessageDigest mda = HashFactory.getInstance(mdName);
+ result = new SRP(mda);
+ algorithms.put(mdName, result);
+ }
+ return result;
+ }
+
+ private static final byte[] xor(final byte[] b1, final byte[] b2,
+ final int length)
+ {
+ final byte[] result = new byte[length];
+ for (int i = 0; i < length; ++i)
+ {
+ result[i] = (byte) (b1[i] ^ b2[i]);
+ }
+ return result;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /** @return the message digest algorithm name used by this instance. */
+ public String getAlgorithm()
+ {
+ return mda.name();
+ }
+
+ // Message Digest algorithm related methods --------------------------------
+
+ /**
+ * <p>Returns a new instance of the SRP message digest algorithm --which is
+ * SHA-160 by default, but could be anything else provided the proper
+ * conditions as specified in the SRP specifications.</p>
+ *
+ * @return a new instance of the underlying SRP message digest algorithm.
+ * @throws RuntimeException if the implementation of the message digest
+ * algorithm does not support cloning.
+ */
+ public IMessageDigest newDigest()
+ {
+ return (IMessageDigest) mda.clone();
+ }
+
+ /**
+ * <p>Convenience method to return the result of digesting the designated
+ * input with a new instance of the SRP message digest algorithm.</p>
+ *
+ * @param src some bytes to digest.
+ * @return the bytes constituting the result of digesting the designated
+ * input with a new instance of the SRP message digest algorithm.
+ */
+ public byte[] digest(final byte[] src)
+ {
+ final IMessageDigest hash = (IMessageDigest) mda.clone();
+ hash.update(src, 0, src.length);
+ return hash.digest();
+ }
+
+ /**
+ * <p>Convenience method to return the result of digesting the designated
+ * input with a new instance of the SRP message digest algorithm.</p>
+ *
+ * @param src a String whose bytes (using US-ASCII encoding) are to be
+ * digested.
+ * @return the bytes constituting the result of digesting the designated
+ * input with a new instance of the SRP message digest algorithm.
+ * @throws UnsupportedEncodingException if US-ASCII charset is not found.
+ */
+ public byte[] digest(final String src) throws UnsupportedEncodingException
+ {
+ return digest(src.getBytes("US-ASCII"));
+ }
+
+ // Other methods -----------------------------------------------------------
+
+ /**
+ * <p>Convenience method to XOR N bytes from two arrays; N being the output
+ * size of the SRP message digest algorithm.</p>
+ *
+ * @param a the first byte array.
+ * @param b the second one.
+ * @return N bytes which are the result of the XOR operations on the first N
+ * bytes from the designated arrays. N is the size of the SRP message digest
+ * algorithm; eg. 20 for SHA-160.
+ */
+ public byte[] xor(final byte[] a, final byte[] b)
+ {
+ return xor(a, b, mda.hashSize());
+ }
+
+ public byte[] generateM1(final BigInteger N, final BigInteger g,
+ final String U, final byte[] s, final BigInteger A,
+ final BigInteger B, final byte[] K, final String I,
+ final String L, final byte[] cn, final byte[] cCB)
+ throws UnsupportedEncodingException
+ {
+ final IMessageDigest hash = (IMessageDigest) mda.clone();
+ byte[] b;
+ b = xor(digest(Util.trim(N)), digest(Util.trim(g)));
+ hash.update(b, 0, b.length);
+ b = digest(U);
+ hash.update(b, 0, b.length);
+ hash.update(s, 0, s.length);
+ b = Util.trim(A);
+ hash.update(b, 0, b.length);
+ b = Util.trim(B);
+ hash.update(b, 0, b.length);
+ hash.update(K, 0, K.length);
+ b = digest(I);
+ hash.update(b, 0, b.length);
+ b = digest(L);
+ hash.update(b, 0, b.length);
+ hash.update(cn, 0, cn.length);
+ hash.update(cCB, 0, cCB.length);
+
+ return hash.digest();
+ }
+
+ public byte[] generateM2(final BigInteger A, final byte[] M1, final byte[] K,
+ final String U, final String I, final String o,
+ final byte[] sid, final int ttl, final byte[] cIV,
+ final byte[] sIV, final byte[] sCB)
+ throws UnsupportedEncodingException
+ {
+ final IMessageDigest hash = (IMessageDigest) mda.clone();
+ byte[] b;
+ b = Util.trim(A);
+ hash.update(b, 0, b.length);
+ hash.update(M1, 0, M1.length);
+ hash.update(K, 0, K.length);
+ b = digest(U);
+ hash.update(b, 0, b.length);
+ b = digest(I);
+ hash.update(b, 0, b.length);
+ b = digest(o);
+ hash.update(b, 0, b.length);
+ hash.update(sid, 0, sid.length);
+ hash.update((byte) (ttl >>> 24));
+ hash.update((byte) (ttl >>> 16));
+ hash.update((byte) (ttl >>> 8));
+ hash.update((byte) ttl);
+ hash.update(cIV, 0, cIV.length);
+ hash.update(sIV, 0, sIV.length);
+ hash.update(sCB, 0, sCB.length);
+
+ return hash.digest();
+ }
+
+ public byte[] generateKn(final byte[] K, final byte[] cn, final byte[] sn)
+ {
+ final IMessageDigest hash = (IMessageDigest) mda.clone();
+ hash.update(K, 0, K.length);
+ hash.update(cn, 0, cn.length);
+ hash.update(sn, 0, sn.length);
+
+ return hash.digest();
+ }
+
+ public byte[] computeX(final byte[] s, final String user,
+ final String password)
+ throws UnsupportedEncodingException
+ {
+ return computeX(s, user.getBytes("US-ASCII"), password.getBytes("US-ASCII"));
+ }
+
+ public byte[] computeX(final byte[] s, final String user, final byte[] p)
+ throws UnsupportedEncodingException
+ {
+ return computeX(s, user.getBytes("US-ASCII"), p);
+ }
+
+ private byte[] computeX(final byte[] s, final byte[] user, final byte[] p)
+ {
+ final IMessageDigest hash = (IMessageDigest) mda.clone();
+ hash.update(user, 0, user.length);
+ hash.update(COLON);
+ hash.update(p, 0, p.length);
+ final byte[] up = hash.digest();
+
+ hash.update(s, 0, s.length);
+ hash.update(up, 0, up.length);
+
+ return hash.digest();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java b/gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java
new file mode 100644
index 000000000..9ea21efb6
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java
@@ -0,0 +1,218 @@
+/* SRPAuthInfoProvider.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+import gnu.javax.crypto.sasl.IAuthInfoProvider;
+import gnu.javax.crypto.sasl.NoSuchUserException;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.sasl.AuthenticationException;
+
+/**
+ * <p>The SRP mechanism authentication information provider implementation.</p>
+ */
+public class SRPAuthInfoProvider implements IAuthInfoProvider
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private PasswordFile passwordFile = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-args constrcutor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IAuthInfoProvider interface implementation ------------------------------
+
+ public void activate(Map context) throws AuthenticationException
+ {
+ try
+ {
+ if (context == null)
+ {
+ passwordFile = new PasswordFile();
+ }
+ else
+ {
+ passwordFile = (PasswordFile) context.get(SRPRegistry.PASSWORD_DB);
+ if (passwordFile == null)
+ {
+ String pfn = (String) context.get(SRPRegistry.PASSWORD_FILE);
+ if (pfn == null)
+ {
+ passwordFile = new PasswordFile();
+ }
+ else
+ {
+ passwordFile = new PasswordFile(pfn);
+ }
+ }
+ }
+ }
+ catch (IOException x)
+ {
+ throw new AuthenticationException("activate()", x);
+ }
+ }
+
+ public void passivate() throws AuthenticationException
+ {
+ passwordFile = null;
+ }
+
+ public boolean contains(String userName) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("contains()",
+ new IllegalStateException());
+ }
+ boolean result = false;
+ try
+ {
+ result = passwordFile.contains(userName);
+ }
+ catch (IOException x)
+ {
+ throw new AuthenticationException("contains()", x);
+ }
+ return result;
+ }
+
+ public Map lookup(Map userID) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("lookup()",
+ new IllegalStateException());
+ }
+ Map result = new HashMap();
+ try
+ {
+ String userName = (String) userID.get(Registry.SASL_USERNAME);
+ if (userName == null)
+ {
+ throw new NoSuchUserException("");
+ }
+ String mdName = (String) userID.get(SRPRegistry.MD_NAME_FIELD);
+
+ String[] data = passwordFile.lookup(userName, mdName);
+ result.put(SRPRegistry.USER_VERIFIER_FIELD, data[0]);
+ result.put(SRPRegistry.SALT_FIELD, data[1]);
+ result.put(SRPRegistry.CONFIG_NDX_FIELD, data[2]);
+ }
+ catch (Exception x)
+ {
+ if (x instanceof AuthenticationException)
+ {
+ throw (AuthenticationException) x;
+ }
+ throw new AuthenticationException("lookup()", x);
+ }
+ return result;
+ }
+
+ public void update(Map userCredentials) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ throw new AuthenticationException("update()", new IllegalStateException());
+
+ try
+ {
+ String userName = (String) userCredentials.get(Registry.SASL_USERNAME);
+ String password = (String) userCredentials.get(Registry.SASL_PASSWORD);
+ String salt = (String) userCredentials.get(SRPRegistry.SALT_FIELD);
+ String config = (String) userCredentials.get(SRPRegistry.CONFIG_NDX_FIELD);
+ if (salt == null || config == null)
+ {
+ passwordFile.changePasswd(userName, password);
+ }
+ else
+ {
+ passwordFile.add(userName, password, Util.fromBase64(salt), config);
+ }
+ }
+ catch (Exception x)
+ {
+ if (x instanceof AuthenticationException)
+ {
+ throw (AuthenticationException) x;
+ }
+ throw new AuthenticationException("update()", x);
+ }
+ }
+
+ public Map getConfiguration(String mode) throws AuthenticationException
+ {
+ if (passwordFile == null)
+ {
+ throw new AuthenticationException("getConfiguration()",
+ new IllegalStateException());
+ }
+ Map result = new HashMap();
+ try
+ {
+ String[] data = passwordFile.lookupConfig(mode);
+ result.put(SRPRegistry.SHARED_MODULUS, data[0]);
+ result.put(SRPRegistry.FIELD_GENERATOR, data[1]);
+ }
+ catch (Exception x)
+ {
+ if (x instanceof AuthenticationException)
+ {
+ throw (AuthenticationException) x;
+ }
+ throw new AuthenticationException("getConfiguration()", x);
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/SRPClient.java b/gnu/javax/crypto/sasl/srp/SRPClient.java
new file mode 100644
index 000000000..26a9e8aaf
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/SRPClient.java
@@ -0,0 +1,1199 @@
+/* SRPClient.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.MD5;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.key.IKeyAgreementParty;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.KeyAgreementFactory;
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.OutgoingMessage;
+import gnu.javax.crypto.key.srp6.SRP6KeyAgreement;
+import gnu.javax.crypto.assembly.Direction;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.sasl.ClientMechanism;
+import gnu.javax.crypto.sasl.IllegalMechanismStateException;
+import gnu.javax.crypto.sasl.InputBuffer;
+import gnu.javax.crypto.sasl.IntegrityException;
+import gnu.javax.crypto.sasl.OutputBuffer;
+
+import gnu.javax.security.auth.Password;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.DestroyFailedException;
+import javax.security.sasl.AuthenticationException;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+/**
+ * <p>The SASL-SRP client-side mechanism.</p>
+ */
+public class SRPClient extends ClientMechanism implements SaslClient
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "SRPClient";
+
+ // private static final String ERROR = "ERROR";
+ // private static final String WARN = " WARN";
+ private static final String INFO = " INFO";
+
+ private static final String TRACE = "DEBUG";
+
+ private static final boolean DEBUG = true;
+
+ private static final int debuglevel = 3;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(final String level, final Object obj)
+ {
+ err.println("[" + level + "] " + NAME + ": " + String.valueOf(obj));
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // private static final HashMap uid2ctx = new HashMap();
+
+ private String uid; // the unique key for this type of client
+
+ private String U; // the authentication identity
+
+ BigInteger N, g, A, B;
+
+ private Password password; // the authentication credentials
+
+ private byte[] s; // the user's salt
+
+ private byte[] cIV, sIV; // client+server IVs, when confidentiality is on
+
+ private byte[] M1, M2; // client+server evidences
+
+ private byte[] cn, sn; // client's and server's nonce
+
+ private SRP srp; // SRP algorithm instance used by this client
+
+ private byte[] sid; // session ID when re-used
+
+ private int ttl; // session time-to-live in seconds
+
+ private byte[] sCB; // the peer's channel binding data
+
+ private String L; // available options
+
+ private String o;
+
+ private String chosenIntegrityAlgorithm;
+
+ private String chosenConfidentialityAlgorithm;
+
+ private int rawSendSize = Registry.SASL_BUFFER_MAX_LIMIT;
+
+ private byte[] K; // shared session key
+
+ private boolean replayDetection = true; // whether Replay Detection is on
+
+ private int inCounter = 0; // messages sequence numbers
+
+ private int outCounter = 0;
+
+ private IALG inMac, outMac; // if !null, use for integrity
+
+ private CALG inCipher, outCipher; // if !null, use for confidentiality
+
+ private IKeyAgreementParty clientHandler = KeyAgreementFactory.getPartyAInstance(Registry.SRP_SASL_KA);
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public SRPClient()
+ {
+ super(Registry.SASL_SRP_MECHANISM);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods implementation -----------------------------------------
+
+ protected void initMechanism() throws SaslException
+ {
+ // we shall keep track of the sid (and the security context of this
+ // SRP client) based on the initialisation parameters of an SRP session.
+ // we shall compute a unique key for those parameters and key the sid
+ // (and the security context) accordingly.
+ // 1. compute the mapping key. use MD5 (the fastest) for this purpose
+ final MD5 md = new MD5();
+ byte[] b;
+ b = authorizationID.getBytes();
+ md.update(b, 0, b.length);
+ b = serverName.getBytes();
+ md.update(b, 0, b.length);
+ b = protocol.getBytes();
+ md.update(b, 0, b.length);
+ if (channelBinding.length > 0)
+ {
+ md.update(channelBinding, 0, channelBinding.length);
+ }
+ uid = Util.toBase64(md.digest());
+ if (ClientStore.instance().isAlive(uid))
+ {
+ final SecurityContext ctx = ClientStore.instance().restoreSession(uid);
+ srp = SRP.instance(ctx.getMdName());
+ sid = ctx.getSID();
+ K = ctx.getK();
+ cIV = ctx.getClientIV();
+ sIV = ctx.getServerIV();
+ replayDetection = ctx.hasReplayDetection();
+ inCounter = ctx.getInCounter();
+ outCounter = ctx.getOutCounter();
+ inMac = ctx.getInMac();
+ outMac = ctx.getOutMac();
+ inCipher = ctx.getInCipher();
+ outCipher = ctx.getOutCipher();
+ }
+ else
+ {
+ sid = new byte[0];
+ ttl = 0;
+ K = null;
+ cIV = null;
+ sIV = null;
+ cn = null;
+ sn = null;
+ }
+ }
+
+ protected void resetMechanism() throws SaslException
+ {
+ try
+ {
+ password.destroy();
+ }
+ catch (DestroyFailedException dfe)
+ {
+ SaslException se = new SaslException("resetMechanism()");
+ se.initCause(dfe);
+ throw se;
+ }
+ password = null;
+ M1 = null;
+ K = null;
+ cIV = null;
+ sIV = null;
+ inMac = outMac = null;
+ inCipher = outCipher = null;
+
+ sid = null;
+ ttl = 0;
+ cn = null;
+ sn = null;
+ }
+
+ // javax.security.sasl.SaslClient interface implementation -----------------
+
+ public boolean hasInitialResponse()
+ {
+ return true;
+ }
+
+ public byte[] evaluateChallenge(final byte[] challenge) throws SaslException
+ {
+ switch (state)
+ {
+ case 0:
+ state++;
+ return sendIdentities();
+ case 1:
+ state++;
+ final byte[] result = sendPublicKey(challenge);
+ try
+ {
+ password.destroy(); //don't need further this session
+ }
+ catch (DestroyFailedException x)
+ {
+ SaslException se = new SaslException("sendPublicKey()");
+ se.initCause(se);
+ throw se;
+ }
+ return result;
+ case 2: // should only occur if session re-use was rejected
+ if (!complete)
+ {
+ state++;
+ return receiveEvidence(challenge);
+ }
+ // else fall through
+ default:
+ throw new IllegalMechanismStateException("evaluateChallenge()");
+ }
+ }
+
+ protected byte[] engineUnwrap(final byte[] incoming, final int offset,
+ final int len) throws SaslException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> engineUnwrap()");
+
+ if (inMac == null && inCipher == null)
+ {
+ throw new IllegalStateException("connection is not protected");
+ }
+
+ // at this point one, or both, of confidentiality and integrity protection
+ // services are active.
+
+ final byte[] result;
+ try
+ {
+ // final InputBuffer frameIn = InputBuffer.getInstance(incoming, offset, len);
+ // result = frameIn.getEOS();
+ if (inMac != null)
+ { // integrity bytes are at the end of the stream
+ final int macBytesCount = inMac.length();
+ final int payloadLength = len - macBytesCount;
+ // final byte[] received_mac = frameIn.getOS();
+ final byte[] received_mac = new byte[macBytesCount];
+ System.arraycopy(incoming, offset + payloadLength, received_mac, 0,
+ macBytesCount);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got C (received MAC): "
+ + Util.dumpString(received_mac));
+ // inMac.update(result);
+ inMac.update(incoming, offset, payloadLength);
+ if (replayDetection)
+ {
+ inCounter++;
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "inCounter=" + String.valueOf(inCounter));
+ inMac.update(new byte[] { (byte) (inCounter >>> 24),
+ (byte) (inCounter >>> 16),
+ (byte) (inCounter >>> 8),
+ (byte) inCounter });
+ }
+
+ final byte[] computed_mac = inMac.doFinal();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Computed MAC: " + Util.dumpString(computed_mac));
+ if (!Arrays.equals(received_mac, computed_mac))
+ {
+ throw new IntegrityException("engineUnwrap()");
+ }
+
+ // deal with the payload, which can be either plain or encrypted
+ if (inCipher != null)
+ {
+ result = inCipher.doFinal(incoming, offset, payloadLength);
+ }
+ else
+ {
+ result = new byte[len - macBytesCount];
+ System.arraycopy(incoming, offset, result, 0, result.length);
+ }
+ }
+ else
+ { // no integrity protection; just confidentiality
+ // if (inCipher != null) {
+ result = inCipher.doFinal(incoming, offset, len);
+ // } else {
+ // result = new byte[len];
+ // System.arraycopy(incoming, offset, result, 0, len);
+ // }
+ }
+ // if (inCipher != null) {
+ // result = inCipher.doFinal(result);
+ // }
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new SaslException("engineUnwrap()", x);
+ }
+
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== engineUnwrap()");
+ return result;
+ }
+
+ protected byte[] engineWrap(final byte[] outgoing, final int offset,
+ final int len) throws SaslException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> engineWrap()");
+
+ if (outMac == null && outCipher == null)
+ {
+ throw new IllegalStateException("connection is not protected");
+ }
+
+ // at this point one, or both, of confidentiality and integrity protection
+ // services are active.
+
+ // byte[] data = new byte[len];
+ // System.arraycopy(outgoing, offset, data, 0, len);
+ byte[] result;
+ try
+ {
+ // OutputBuffer frameOut = new OutputBuffer();
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ // Process the data
+ if (outCipher != null)
+ {
+ // data = outCipher.doFinal(data);
+ result = outCipher.doFinal(outgoing, offset, len);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding c (encrypted plaintext): "
+ + Util.dumpString(result));
+
+ // frameOut.setEOS(data);
+ out.write(result);
+
+ if (outMac != null)
+ {
+ outMac.update(result);
+ if (replayDetection)
+ {
+ outCounter++;
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "outCounter=" + String.valueOf(outCounter));
+ outMac.update(new byte[] { (byte) (outCounter >>> 24),
+ (byte) (outCounter >>> 16),
+ (byte) (outCounter >>> 8),
+ (byte) outCounter });
+ }
+ final byte[] C = outMac.doFinal();
+ // frameOut.setOS(C);
+ out.write(C);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding C (integrity checksum): "
+ + Util.dumpString(C));
+ } // else confidentiality only; do nothing
+ }
+ else
+ { // no confidentiality; just integrity [+ replay detection]
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Encoding p (plaintext): "+Util.dumpString(data));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding p (plaintext): "
+ + Util.dumpString(outgoing, offset, len));
+
+ // frameOut.setEOS(data);
+ out.write(outgoing, offset, len);
+
+ // if (outMac != null) {
+ // outMac.update(data);
+ outMac.update(outgoing, offset, len);
+ if (replayDetection)
+ {
+ outCounter++;
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "outCounter=" + String.valueOf(outCounter));
+ outMac.update(new byte[] { (byte) (outCounter >>> 24),
+ (byte) (outCounter >>> 16),
+ (byte) (outCounter >>> 8),
+ (byte) outCounter });
+ }
+ final byte[] C = outMac.doFinal();
+ // frameOut.setOS(C);
+ out.write(C);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding C (integrity checksum): "
+ + Util.dumpString(C));
+ // }
+ }
+
+ // frameOut.setEOS(data);
+ //
+ // if (outMac != null) {
+ // outMac.update(data);
+ // if (replayDetection) {
+ // outCounter++;
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "outCounter="+String.valueOf(outCounter));
+ // outMac.update(new byte[] {
+ // (byte)(outCounter >>> 24),
+ // (byte)(outCounter >>> 16),
+ // (byte)(outCounter >>> 8),
+ // (byte) outCounter });
+ // }
+ // byte[] C = outMac.doFinal();
+ // frameOut.setOS(C);
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Encoding C (integrity checksum): "+Util.dumpString(C));
+ // }
+
+ // result = frameOut.wrap();
+ result = out.toByteArray();
+
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new SaslException("engineWrap()", x);
+ }
+
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== engineWrap()");
+ return result;
+ }
+
+ protected String getNegotiatedQOP()
+ {
+ if (inMac != null)
+ {
+ if (inCipher != null)
+ {
+ return Registry.QOP_AUTH_CONF;
+ }
+ else
+ {
+ return Registry.QOP_AUTH_INT;
+ }
+ }
+ return Registry.QOP_AUTH;
+ }
+
+ protected String getNegotiatedStrength()
+ {
+ if (inMac != null)
+ {
+ if (inCipher != null)
+ {
+ return Registry.STRENGTH_HIGH;
+ }
+ else
+ {
+ return Registry.STRENGTH_MEDIUM;
+ }
+ }
+ return Registry.STRENGTH_LOW;
+ }
+
+ protected String getNegotiatedRawSendSize()
+ {
+ return String.valueOf(rawSendSize);
+ }
+
+ protected String getReuse()
+ {
+ return Registry.REUSE_TRUE;
+ }
+
+ // other methods -----------------------------------------------------------
+
+ private byte[] sendIdentities() throws SaslException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> sendIdentities()");
+
+ // If necessary, prompt the client for the username and password
+ getUsernameAndPassword();
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Password: \"" + new String(password.getPassword()) + "\"");
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding U (username): \"" + U + "\"");
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding I (userid): \"" + authorizationID + "\"");
+
+ // if session re-use generate new 16-byte nonce
+ if (sid.length != 0)
+ {
+ cn = new SecureRandom ().generateSeed (16);
+ }
+ else
+ {
+ cn = new byte[0];
+ }
+
+ final OutputBuffer frameOut = new OutputBuffer();
+ try
+ {
+ frameOut.setText(U);
+ frameOut.setText(authorizationID);
+ frameOut.setEOS(sid); // session ID to re-use
+ frameOut.setOS(cn); // client nonce
+ frameOut.setEOS(channelBinding);
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("sendIdentities()", x);
+ }
+ final byte[] result = frameOut.encode();
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== sendIdentities()");
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "C: " + Util.dumpString(result));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " U = " + U);
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " I = " + authorizationID);
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "sid = " + new String(sid));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " cn = " + Util.dumpString(cn));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "cCB = " + Util.dumpString(channelBinding));
+ return result;
+ }
+
+ private byte[] sendPublicKey(final byte[] input) throws SaslException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> sendPublicKey()");
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "S: " + Util.dumpString(input));
+
+ // Server sends [00], N, g, s, B, L
+ // or [FF], sn, sCB
+ final InputBuffer frameIn = new InputBuffer(input);
+ final int ack;
+ try
+ {
+ ack = (int) frameIn.getScalar(1);
+ if (ack == 0x00)
+ { // new session
+ N = frameIn.getMPI();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got N (modulus): " + Util.dump(N));
+ g = frameIn.getMPI();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got g (generator): " + Util.dump(g));
+ s = frameIn.getOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got s (salt): " + Util.dumpString(s));
+ B = frameIn.getMPI();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got B (server ephermeral public key): "
+ + Util.dump(B));
+ L = frameIn.getText();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got L (available options): \"" + L + "\"");
+ }
+ else if (ack == 0xFF)
+ { // session re-use
+ sn = frameIn.getOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got sn (server nonce): " + Util.dumpString(sn));
+ sCB = frameIn.getEOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got sCB (server channel binding): "
+ + Util.dumpString(sCB));
+ }
+ else
+ { // unexpected scalar
+ throw new SaslException("sendPublicKey(): Invalid scalar (" + ack
+ + ") in server's request");
+ }
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new SaslException("sendPublicKey()", x);
+ }
+
+ if (ack == 0x00)
+ { // new session ---------------------------------------
+ o = createO(L.toLowerCase()); // do this first to initialise the SRP hash
+
+ final byte[] pBytes; // use ASCII encoding to inter-operate w/ non-java
+ pBytes = password.getBytes();
+
+ // ----------------------------------------------------------------------
+ final HashMap mapA = new HashMap();
+ // mapA.put(SRP6KeyAgreement.HASH_FUNCTION, srp.newDigest());
+ mapA.put(SRP6KeyAgreement.HASH_FUNCTION, srp.getAlgorithm());
+ mapA.put(SRP6KeyAgreement.USER_IDENTITY, U);
+ mapA.put(SRP6KeyAgreement.USER_PASSWORD, pBytes);
+ try
+ {
+ clientHandler.init(mapA);
+ clientHandler.processMessage(null);
+ }
+ catch (KeyAgreementException x)
+ {
+ throw new SaslException("sendPublicKey()", x);
+ }
+
+ // ----------------------------------------------------------------------
+
+ // -------------------------------------------------------------------
+ try
+ {
+ OutgoingMessage out = new OutgoingMessage();
+ out.writeMPI(N);
+ out.writeMPI(g);
+ out.writeMPI(new BigInteger(1, s));
+ out.writeMPI(B);
+ IncomingMessage in = new IncomingMessage(out.toByteArray());
+ out = clientHandler.processMessage(in);
+
+ in = new IncomingMessage(out.toByteArray());
+ A = in.readMPI();
+ K = clientHandler.getSharedSecret();
+ }
+ catch (KeyAgreementException x)
+ {
+ throw new SaslException("sendPublicKey()", x);
+ }
+ // -------------------------------------------------------------------
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "K: " + Util.dumpString(K));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding A (client ephemeral public key): "
+ + Util.dump(A));
+
+ try
+ {
+ M1 = srp.generateM1(N, g, U, s, A, B, K, authorizationID, L, cn,
+ channelBinding);
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new AuthenticationException("sendPublicKey()", x);
+ }
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding o (client chosen options): \"" + o + "\"");
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding cIV (client IV): \"" + Util.dumpString(cIV)
+ + "\"");
+
+ final OutputBuffer frameOut = new OutputBuffer();
+ try
+ {
+ frameOut.setMPI(A);
+ frameOut.setOS(M1);
+ frameOut.setText(o);
+ frameOut.setOS(cIV);
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("sendPublicKey()", x);
+ }
+ final byte[] result = frameOut.encode();
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== sendPublicKey()");
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "New session, or session re-use rejected...");
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "C: " + Util.dumpString(result));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " A = 0x" + A.toString(16));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " M1 = " + Util.dumpString(M1));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " o = " + o);
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "cIV = " + Util.dumpString(cIV));
+
+ return result;
+ }
+ else
+ { // session re-use accepted -------------------------------------
+ setupSecurityServices(true);
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== sendPublicKey()");
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "Session re-use accepted...");
+ return null;
+ }
+ }
+
+ private byte[] receiveEvidence(byte[] input) throws SaslException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> receiveEvidence()");
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "S: " + Util.dumpString(input));
+
+ // Server send M2, sIV, sCB, sid, ttl
+ final InputBuffer frameIn = new InputBuffer(input);
+ try
+ {
+ M2 = frameIn.getOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got M2 (server evidence): " + Util.dumpString(M2));
+ sIV = frameIn.getOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got sIV (server IV): " + Util.dumpString(sIV));
+ sid = frameIn.getEOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got sid (session ID): " + new String(sid));
+ ttl = (int) frameIn.getScalar(4);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got ttl (session time-to-live): " + ttl + "sec.");
+ sCB = frameIn.getEOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got sCB (server channel binding): "
+ + Util.dumpString(sCB));
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("receiveEvidence()", x);
+ }
+
+ final byte[] expected;
+ try
+ {
+ expected = srp.generateM2(A, M1, K, U, authorizationID, o, sid, ttl,
+ cIV, sIV, sCB);
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new AuthenticationException("receiveEvidence()", x);
+ }
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Expected: " + Util.dumpString(expected));
+ if (!Arrays.equals(M2, expected))
+ {
+ throw new AuthenticationException("M2 mismatch");
+ }
+
+ setupSecurityServices(false);
+
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== receiveEvidence()");
+ return null;
+ }
+
+ private void getUsernameAndPassword() throws AuthenticationException
+ {
+ try
+ {
+ if ((!properties.containsKey(Registry.SASL_USERNAME))
+ && (!properties.containsKey(Registry.SASL_PASSWORD)))
+ {
+ final NameCallback nameCB;
+ final String defaultName = System.getProperty("user.name");
+ if (defaultName == null)
+ {
+ nameCB = new NameCallback("username: ");
+ }
+ else
+ {
+ nameCB = new NameCallback("username: ", defaultName);
+ }
+ final PasswordCallback pwdCB = new PasswordCallback("password: ",
+ false);
+ handler.handle(new Callback[] { nameCB, pwdCB });
+ U = nameCB.getName();
+ password = new Password(pwdCB.getPassword());
+ }
+ else
+ {
+ if (properties.containsKey(Registry.SASL_USERNAME))
+ {
+ this.U = (String) properties.get(Registry.SASL_USERNAME);
+ }
+ else
+ {
+ final NameCallback nameCB;
+ final String defaultName = System.getProperty("user.name");
+ if (defaultName == null)
+ {
+ nameCB = new NameCallback("username: ");
+ }
+ else
+ {
+ nameCB = new NameCallback("username: ", defaultName);
+ }
+ this.handler.handle(new Callback[] { nameCB });
+ this.U = nameCB.getName();
+ }
+
+ if (properties.containsKey(Registry.SASL_PASSWORD))
+ {
+ Object pw = properties.get(Registry.SASL_PASSWORD);
+ if (pw instanceof char[])
+ password = new Password((char[]) pw);
+ else if (pw instanceof Password)
+ password = (Password) pw;
+ else if (pw instanceof String)
+ password = new Password(((String) pw).toCharArray());
+ else
+ throw new IllegalArgumentException(
+ pw.getClass().getName()
+ + "is not a valid password class");
+ }
+ else
+ {
+ final PasswordCallback pwdCB = new PasswordCallback(
+ "password: ",
+ false);
+ this.handler.handle(new Callback[] { pwdCB });
+ password = new Password(pwdCB.getPassword());
+ }
+ }
+
+ if (U == null)
+ {
+ throw new AuthenticationException("null username supplied");
+ }
+ if (password == null)
+ {
+ throw new AuthenticationException("null password supplied");
+ }
+ }
+ catch (UnsupportedCallbackException x)
+ {
+ throw new AuthenticationException("getUsernameAndPassword()", x);
+ }
+ catch (IOException x)
+ {
+ throw new AuthenticationException("getUsernameAndPassword()", x);
+ }
+ }
+
+ // We go through the list of available services and for each available one
+ // we decide whether or not we want it enabled, based on properties passed
+ // to us by the client.
+ private String createO(final String aol) throws AuthenticationException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> createO(\"" + aol + "\")");
+
+ boolean replaydetectionAvailable = false;
+ boolean integrityAvailable = false;
+ boolean confidentialityAvailable = false;
+ String option, mandatory = SRPRegistry.DEFAULT_MANDATORY;
+ int i;
+
+ String mdName = SRPRegistry.SRP_DEFAULT_DIGEST_NAME;
+
+ final StringTokenizer st = new StringTokenizer(aol, ",");
+ while (st.hasMoreTokens())
+ {
+ option = st.nextToken();
+ if (option.startsWith(SRPRegistry.OPTION_SRP_DIGEST + "="))
+ {
+ option = option.substring(option.indexOf('=') + 1);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "mda: <" + option + ">");
+ for (i = 0; i < SRPRegistry.INTEGRITY_ALGORITHMS.length; i++)
+ {
+ if (SRPRegistry.SRP_ALGORITHMS[i].equals(option))
+ {
+ mdName = option;
+ break;
+ }
+ }
+ }
+ else if (option.equals(SRPRegistry.OPTION_REPLAY_DETECTION))
+ {
+ replaydetectionAvailable = true;
+ }
+ else if (option.startsWith(SRPRegistry.OPTION_INTEGRITY + "="))
+ {
+ option = option.substring(option.indexOf('=') + 1);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "ialg: <" + option + ">");
+ for (i = 0; i < SRPRegistry.INTEGRITY_ALGORITHMS.length; i++)
+ {
+ if (SRPRegistry.INTEGRITY_ALGORITHMS[i].equals(option))
+ {
+ chosenIntegrityAlgorithm = option;
+ integrityAvailable = true;
+ break;
+ }
+ }
+ }
+ else if (option.startsWith(SRPRegistry.OPTION_CONFIDENTIALITY + "="))
+ {
+ option = option.substring(option.indexOf('=') + 1);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "calg: <" + option + ">");
+ for (i = 0; i < SRPRegistry.CONFIDENTIALITY_ALGORITHMS.length; i++)
+ {
+ if (SRPRegistry.CONFIDENTIALITY_ALGORITHMS[i].equals(option))
+ {
+ chosenConfidentialityAlgorithm = option;
+ confidentialityAvailable = true;
+ break;
+ }
+ }
+ }
+ else if (option.startsWith(SRPRegistry.OPTION_MANDATORY + "="))
+ {
+ mandatory = option.substring(option.indexOf('=') + 1);
+ }
+ else if (option.startsWith(SRPRegistry.OPTION_MAX_BUFFER_SIZE + "="))
+ {
+ final String maxBufferSize = option.substring(option.indexOf('=') + 1);
+ try
+ {
+ rawSendSize = Integer.parseInt(maxBufferSize);
+ if (rawSendSize > Registry.SASL_BUFFER_MAX_LIMIT
+ || rawSendSize < 1)
+ {
+ throw new AuthenticationException(
+ "Illegal value for 'maxbuffersize' option");
+ }
+ }
+ catch (NumberFormatException x)
+ {
+ throw new AuthenticationException(
+ SRPRegistry.OPTION_MAX_BUFFER_SIZE
+ + "="
+ + String.valueOf(maxBufferSize),
+ x);
+ }
+ }
+ }
+
+ replayDetection = replaydetectionAvailable
+ && Boolean.valueOf(
+ (String) properties.get(SRPRegistry.SRP_REPLAY_DETECTION)).booleanValue();
+ boolean integrity = integrityAvailable
+ && Boolean.valueOf(
+ (String) properties.get(SRPRegistry.SRP_INTEGRITY_PROTECTION)).booleanValue();
+ boolean confidentiality = confidentialityAvailable
+ && Boolean.valueOf(
+ (String) properties.get(SRPRegistry.SRP_CONFIDENTIALITY)).booleanValue();
+
+ // make sure we do the right thing
+ if (SRPRegistry.OPTION_REPLAY_DETECTION.equals(mandatory))
+ {
+ replayDetection = true;
+ integrity = true;
+ }
+ else if (SRPRegistry.OPTION_INTEGRITY.equals(mandatory))
+ {
+ integrity = true;
+ }
+ else if (SRPRegistry.OPTION_CONFIDENTIALITY.equals(mandatory))
+ {
+ confidentiality = true;
+ }
+ if (replayDetection)
+ {
+ if (chosenIntegrityAlgorithm == null)
+ {
+ throw new AuthenticationException(
+ "Replay detection is required but no "
+ + "integrity protection algorithm was chosen");
+ }
+ }
+ if (integrity)
+ {
+ if (chosenIntegrityAlgorithm == null)
+ {
+ throw new AuthenticationException(
+ "Integrity protection is required but no "
+ + "algorithm was chosen");
+ }
+ }
+ if (confidentiality)
+ {
+ if (chosenConfidentialityAlgorithm == null)
+ {
+ throw new AuthenticationException(
+ "Confidentiality protection is required "
+ + "but no algorithm was chosen");
+ }
+ }
+
+ // 1. check if we'll be using confidentiality; if not set IV to 0-byte
+ if (chosenConfidentialityAlgorithm == null)
+ {
+ cIV = new byte[0];
+ }
+ else
+ {
+ // 2. get the block size of the cipher
+ final IBlockCipher cipher = CipherFactory.getInstance(chosenConfidentialityAlgorithm);
+ if (cipher == null)
+ {
+ throw new AuthenticationException("createO()",
+ new NoSuchAlgorithmException());
+ }
+ final int blockSize = cipher.defaultBlockSize();
+ // 3. generate random iv
+ cIV = new byte[blockSize];
+ new SecureRandom ().nextBytes(cIV);
+ }
+
+ srp = SRP.instance(mdName);
+
+ // Now create the options list specifying which of the available options
+ // we have chosen.
+
+ // For now we just select the defaults. Later we need to add support for
+ // properties (perhaps in a file) where a user can specify the list of
+ // algorithms they would prefer to use.
+
+ final StringBuffer sb = new StringBuffer();
+ sb.append(SRPRegistry.OPTION_SRP_DIGEST).append("=").append(mdName).append(
+ ",");
+ if (replayDetection)
+ {
+ sb.append(SRPRegistry.OPTION_REPLAY_DETECTION).append(",");
+ }
+ if (integrity)
+ {
+ sb.append(SRPRegistry.OPTION_INTEGRITY).append("=").append(
+ chosenIntegrityAlgorithm).append(
+ ",");
+ }
+ if (confidentiality)
+ {
+ sb.append(SRPRegistry.OPTION_CONFIDENTIALITY).append("=").append(
+ chosenConfidentialityAlgorithm).append(
+ ",");
+ }
+ final String result = sb.append(SRPRegistry.OPTION_MAX_BUFFER_SIZE).append(
+ "=").append(
+ Registry.SASL_BUFFER_MAX_LIMIT).toString();
+
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== createO() --> " + result);
+ return result;
+ }
+
+ private void setupSecurityServices(final boolean sessionReUse)
+ throws SaslException
+ {
+ complete = true; // signal end of authentication phase
+ if (!sessionReUse)
+ {
+ outCounter = inCounter = 0;
+ // instantiate cipher if confidentiality protection filter is active
+ if (chosenConfidentialityAlgorithm != null)
+ {
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "Activating confidentiality protection filter");
+ inCipher = CALG.getInstance(chosenConfidentialityAlgorithm);
+ outCipher = CALG.getInstance(chosenConfidentialityAlgorithm);
+ }
+ // instantiate hmacs if integrity protection filter is active
+ if (chosenIntegrityAlgorithm != null)
+ {
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "Activating integrity protection filter");
+ inMac = IALG.getInstance(chosenIntegrityAlgorithm);
+ outMac = IALG.getInstance(chosenIntegrityAlgorithm);
+ }
+ }
+ else
+ { // same session new Keys
+ K = srp.generateKn(K, cn, sn);
+ }
+
+ final KDF kdf = KDF.getInstance(K);
+
+ // initialise in/out ciphers if confidentiality protection is used
+ if (inCipher != null)
+ {
+ inCipher.init(kdf, sIV, Direction.REVERSED);
+ outCipher.init(kdf, cIV, Direction.FORWARD);
+ }
+ // initialise in/out macs if integrity protection is used
+ if (inMac != null)
+ {
+ inMac.init(kdf);
+ outMac.init(kdf);
+ }
+
+ if (sid != null && sid.length != 0)
+ { // update the security context and save in map
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "Updating security context for UID = " + uid);
+ ClientStore.instance().cacheSession(
+ uid,
+ ttl,
+ new SecurityContext(
+ srp.getAlgorithm(),
+ sid,
+ K,
+ cIV,
+ sIV,
+ replayDetection,
+ inCounter,
+ outCounter,
+ inMac, outMac,
+ inCipher,
+ outCipher));
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/SRPRegistry.java b/gnu/javax/crypto/sasl/srp/SRPRegistry.java
new file mode 100644
index 000000000..262cbcba3
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/SRPRegistry.java
@@ -0,0 +1,219 @@
+/* SRPRegistry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>A list of key names designating the values exchanged between the server
+ * and client in an SRP communication authentication phase.</p>
+ */
+public interface SRPRegistry
+{
+
+ /** Indices of (N, g) parameter values for SRP (.conf) password database. */
+ String N_2048_BITS = "1";
+
+ String N_1536_BITS = "2";
+
+ String N_1280_BITS = "3";
+
+ String N_1024_BITS = "4";
+
+ String N_768_BITS = "5";
+
+ String N_640_BITS = "6";
+
+ String N_512_BITS = "7";
+
+ /** Available hash algorithms for all SRP calculations. */
+ String[] SRP_ALGORITHMS = { Registry.SHA160_HASH, // the default one
+ Registry.MD5_HASH, Registry.RIPEMD128_HASH,
+ Registry.RIPEMD160_HASH,
+
+ Registry.SHA256_HASH, Registry.SHA384_HASH,
+ Registry.SHA512_HASH };
+
+ /**
+ * The name of the default message digest algorithm to use when no name is
+ * explicitely given. In this implementation it is the <b>first</b> among
+ * those supported; i.e. the algorithm at index position #0: SHA with
+ * 160-bit output.
+ */
+ String SRP_DEFAULT_DIGEST_NAME = SRP_ALGORITHMS[0];
+
+ /**
+ * The property name of the message digest algorithm name to use in a given
+ * SRP incarnation.
+ */
+ String SRP_DIGEST_NAME = "srp.digest.name";
+
+ /** The public shared modulus: n. */
+ String SHARED_MODULUS = "srp.N";
+
+ /** The GF generator used: g. */
+ String FIELD_GENERATOR = "srp.g";
+
+ /** The list of server's available security options. */
+ String AVAILABLE_OPTIONS = "srp.L";
+
+ /** The client's chosen security options. */
+ String CHOSEN_OPTIONS = "srp.o";
+
+ /** The client's username. */
+ String USER_NAME = "srp.U";
+
+ /** The client's authorization ID. */
+ String USER_ROLE = "srp.I";
+
+ /** The user's salt. */
+ String USER_SALT = "srp.s";
+
+ /** The user's password verifier. */
+ String PASSWORD_VERIFIER = "srp.v";
+
+ /** The client's public ephemeral exponent: A. */
+ String CLIENT_PUBLIC_KEY = "srp.A";
+
+ /** The server's public ephemeral exponent: B. */
+ String SERVER_PUBLIC_KEY = "srp.B";
+
+ /** The client's evidence: M1. */
+ String CLIENT_EVIDENCE = "srp.M1";
+
+ /** The server's evidence: M2. */
+ String SERVER_EVIDENCE = "srp.M2";
+
+ /** Name of underlying hash algorithm for use with all SRP calculations. */
+ String SRP_HASH = "gnu.crypto.sasl.srp.hash";
+
+ /** Name of SRP mandatory service property. */
+ String SRP_MANDATORY = "gnu.crypto.sasl.srp.mandatory";
+
+ /** Name of SRP replay detection property. */
+ String SRP_REPLAY_DETECTION = "gnu.crypto.sasl.srp.replay.detection";
+
+ /** Name of SRP integrity protection property. */
+ String SRP_INTEGRITY_PROTECTION = "gnu.crypto.sasl.srp.integrity";
+
+ /** Name of SRP confidentiality protection property. */
+ String SRP_CONFIDENTIALITY = "gnu.crypto.sasl.srp.confidentiality";
+
+ /** Name of the main SRP password file pathname property. */
+ String PASSWORD_FILE = "gnu.crypto.sasl.srp.password.file";
+
+ /**
+ * Name of the SRP password database property --a reference to
+ * {@link gnu.crypto.sasl.srp.PasswordFile} object.
+ */
+ String PASSWORD_DB = "gnu.crypto.sasl.srp.password.db";
+
+ /** Default fully qualified pathname of the SRP password file. */
+ String DEFAULT_PASSWORD_FILE = "/etc/tpasswd";
+
+ /** Default value for replay detection security service. */
+ boolean DEFAULT_REPLAY_DETECTION = true;
+
+ /** Default value for integrity protection security service. */
+ boolean DEFAULT_INTEGRITY = true; // implied by the previous option
+
+ /** Default value for confidentiality protection security service. */
+ boolean DEFAULT_CONFIDENTIALITY = false;
+
+ // constants defining HMAC names
+ String HMAC_SHA1 = "hmac-sha1";
+
+ String HMAC_MD5 = "hmac-md5";
+
+ String HMAC_RIPEMD_160 = "hmac-ripemd-160";
+
+ /** Available HMAC algorithms for integrity protection. */
+ String[] INTEGRITY_ALGORITHMS = { HMAC_SHA1, HMAC_MD5, HMAC_RIPEMD_160 };
+
+ // constants defining Cipher names
+ String AES = "aes";
+
+ String BLOWFISH = "blowfish";
+
+ /** Available Cipher algorithms for confidentiality protection. */
+ String[] CONFIDENTIALITY_ALGORITHMS = { AES, BLOWFISH };
+
+ /** String for mandatory replay detection. */
+ String OPTION_MANDATORY = "mandatory";
+
+ /** String for mda: the SRP digest algorithm name. */
+ String OPTION_SRP_DIGEST = "mda";
+
+ /** String for mandatory replay detection. */
+ String OPTION_REPLAY_DETECTION = "replay_detection";
+
+ /** String for mandatory integrity protection. */
+ String OPTION_INTEGRITY = "integrity";
+
+ /** String for mandatory confidentiality protection. */
+ String OPTION_CONFIDENTIALITY = "confidentiality";
+
+ /** String for mandatory replay detection. */
+ String OPTION_MAX_BUFFER_SIZE = "maxbuffersize";
+
+ /** String for no mandatory security service. */
+ String MANDATORY_NONE = "none";
+
+ /** Default mandatory security service required. */
+ // String DEFAULT_MANDATORY = MANDATORY_NONE;
+ String DEFAULT_MANDATORY = OPTION_REPLAY_DETECTION;
+
+ // String DEFAULT_MANDATORY = OPTION_INTEGRITY;
+ // String DEFAULT_MANDATORY = OPTION_CONFIDENTIALITY;
+
+ /** Name of the UID field in the plain password file. */
+ String MD_NAME_FIELD = "srp.md.name";
+
+ /** Name of the GID field in the plain password file. */
+ String USER_VERIFIER_FIELD = "srp.user.verifier";
+
+ /** Name of the GECOS field in the plain password file. */
+ String SALT_FIELD = "srp.salt";
+
+ /** Name of the SHELL field in the plain password file. */
+ String CONFIG_NDX_FIELD = "srp.config.ndx";
+
+ /** Minimum bitlength of the SRP public modulus. */
+ int MINIMUM_MODULUS_BITLENGTH = 512;
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/SRPServer.java b/gnu/javax/crypto/sasl/srp/SRPServer.java
new file mode 100644
index 000000000..421da6e1b
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/SRPServer.java
@@ -0,0 +1,1147 @@
+/* SRPServer.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import gnu.javax.crypto.assembly.Direction;
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.key.IKeyAgreementParty;
+import gnu.javax.crypto.key.KeyAgreementFactory;
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.OutgoingMessage;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.srp6.SRP6KeyAgreement;
+import gnu.javax.crypto.sasl.IllegalMechanismStateException;
+import gnu.javax.crypto.sasl.InputBuffer;
+import gnu.javax.crypto.sasl.IntegrityException;
+import gnu.javax.crypto.sasl.OutputBuffer;
+import gnu.javax.crypto.sasl.ServerMechanism;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import javax.security.sasl.AuthenticationException;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+/**
+ * <p>The SASL-SRP server-side mechanism.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class SRPServer extends ServerMechanism implements SaslServer
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "SRPServer";
+
+ // private static final String ERROR = "ERROR";
+ private static final String WARN = " WARN";
+
+ private static final String INFO = " INFO";
+
+ private static final String TRACE = "DEBUG";
+
+ private static final boolean DEBUG = true;
+
+ private static final int debuglevel = 3;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(final String level, final Object obj)
+ {
+ err.println("[" + level + "] " + NAME + ": " + String.valueOf(obj));
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private String U = null; // client's username
+
+ private BigInteger N, g, A, B;
+
+ private byte[] s; // salt
+
+ private byte[] cIV, sIV; // client+server IVs, when confidentiality is on
+
+ private byte[] cn, sn; // client's and server's nonce
+
+ private SRP srp; // SRP algorithm instance used by this server
+
+ private byte[] sid; // session ID when re-used
+
+ private int ttl = 360; // session time-to-live in seconds
+
+ private byte[] cCB; // peer's channel binding'
+
+ private String mandatory; // List of available options
+
+ private String L = null;
+
+ private String o;
+
+ private String chosenIntegrityAlgorithm;
+
+ private String chosenConfidentialityAlgorithm;
+
+ private int rawSendSize = Registry.SASL_BUFFER_MAX_LIMIT;
+
+ private byte[] K; // shared session key
+
+ private boolean replayDetection = true; // whether Replay Detection is on
+
+ private int inCounter = 0; // messages sequence numbers
+
+ private int outCounter = 0;
+
+ private IALG inMac, outMac; // if !null, use for integrity
+
+ private CALG inCipher, outCipher; // if !null, use for confidentiality
+
+ private IKeyAgreementParty serverHandler = KeyAgreementFactory.getPartyBInstance(Registry.SRP_SASL_KA);
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public SRPServer()
+ {
+ super(Registry.SASL_SRP_MECHANISM);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // abstract methods implementation -----------------------------------------
+
+ protected void initMechanism() throws SaslException
+ {
+ // TODO:
+ // we must have a means to map a given username to a preferred
+ // SRP hash algorithm; otherwise we end up using _always_ SHA.
+ // for the time being get it from the mechanism properties map
+ // and apply it for all users.
+ final String mda = (String) properties.get(SRPRegistry.SRP_HASH);
+ srp = SRP.instance(mda == null ? SRPRegistry.SRP_DEFAULT_DIGEST_NAME : mda);
+ }
+
+ protected void resetMechanism() throws SaslException
+ {
+ s = null;
+ A = B = null;
+ K = null;
+ inMac = outMac = null;
+ inCipher = outCipher = null;
+
+ sid = null;
+ }
+
+ // javax.security.sasl.SaslServer interface implementation -----------------
+
+ public byte[] evaluateResponse(final byte[] response) throws SaslException
+ {
+ switch (state)
+ {
+ case 0:
+ if (response == null)
+ {
+ return null;
+ }
+ state++;
+ return sendProtocolElements(response);
+ case 1:
+ if (!complete)
+ {
+ state++;
+ return sendEvidence(response);
+ }
+ // else fall through
+ default:
+ throw new IllegalMechanismStateException("evaluateResponse()");
+ }
+ }
+
+ protected byte[] engineUnwrap(final byte[] incoming, final int offset,
+ final int len) throws SaslException
+ {
+ // if (DEBUG && debuglevel > 8) debug(TRACE, "==> engineUnwrap()");
+ //
+ // if (inMac == null && inCipher == null) {
+ // throw new IllegalStateException("connection is not protected");
+ // }
+ //
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Incoming buffer (before security): "+Util.dumpString(incoming, offset, len));
+ //
+ // byte[] data = null;
+ // try {
+ // InputBuffer frameIn = InputBuffer.getInstance(incoming, offset, len);
+ // data = frameIn.getEOS();
+ // if (inMac != null) {
+ // byte[] received_mac = frameIn.getOS();
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Got C (received MAC): "+Util.dumpString(received_mac));
+ // inMac.update(data);
+ // if (replayDetection) {
+ // inCounter++;
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "inCounter="+String.valueOf(inCounter));
+ // inMac.update(new byte[] {
+ // (byte)(inCounter >>> 24),
+ // (byte)(inCounter >>> 16),
+ // (byte)(inCounter >>> 8),
+ // (byte) inCounter });
+ // }
+ // final byte[] computed_mac = inMac.doFinal();
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Computed MAC: "+Util.dumpString(computed_mac));
+ // if (!Arrays.equals(received_mac, computed_mac))
+ // throw new IntegrityException("engineUnwrap()");
+ // }
+ // if (inCipher != null) {
+ // data = inCipher.doFinal(data);
+ // }
+ // } catch (IOException x) {
+ // if (x instanceof SaslException) {
+ // throw (SaslException) x;
+ // }
+ // throw new SaslException("engineUnwrap()", x);
+ // }
+ //
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Incoming buffer (after security): "+Util.dumpString(data));
+ // if (DEBUG && debuglevel > 8) debug(TRACE, "<== engineUnwrap()");
+ // return data;
+
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> engineUnwrap()");
+
+ if (inMac == null && inCipher == null)
+ {
+ throw new IllegalStateException("connection is not protected");
+ }
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Incoming buffer (before security): "
+ + Util.dumpString(incoming, offset, len));
+
+ // at this point one, or both, of confidentiality and integrity protection
+ // services are active.
+
+ final byte[] result;
+ try
+ {
+ if (inMac != null)
+ { // integrity bytes are at the end of the stream
+ final int macBytesCount = inMac.length();
+ final int payloadLength = len - macBytesCount;
+ final byte[] received_mac = new byte[macBytesCount];
+ System.arraycopy(incoming, offset + payloadLength, received_mac, 0,
+ macBytesCount);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got C (received MAC): "
+ + Util.dumpString(received_mac));
+ inMac.update(incoming, offset, payloadLength);
+ if (replayDetection)
+ {
+ inCounter++;
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "inCounter=" + String.valueOf(inCounter));
+ inMac.update(new byte[] { (byte) (inCounter >>> 24),
+ (byte) (inCounter >>> 16),
+ (byte) (inCounter >>> 8),
+ (byte) inCounter });
+ }
+
+ final byte[] computed_mac = inMac.doFinal();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Computed MAC: " + Util.dumpString(computed_mac));
+ if (!Arrays.equals(received_mac, computed_mac))
+ {
+ throw new IntegrityException("engineUnwrap()");
+ }
+
+ // deal with the payload, which can be either plain or encrypted
+ if (inCipher != null)
+ {
+ result = inCipher.doFinal(incoming, offset, payloadLength);
+ }
+ else
+ {
+ result = new byte[payloadLength];
+ System.arraycopy(incoming, offset, result, 0, result.length);
+ }
+ }
+ else
+ { // no integrity protection; just confidentiality
+ // if (inCipher != null) {
+ result = inCipher.doFinal(incoming, offset, len);
+ // } else {
+ // result = new byte[len];
+ // System.arraycopy(incoming, offset, result, 0, len);
+ // }
+ }
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new SaslException("engineUnwrap()", x);
+ }
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Incoming buffer (after security): "
+ + Util.dumpString(result));
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== engineUnwrap()");
+ return result;
+ }
+
+ protected byte[] engineWrap(final byte[] outgoing, final int offset,
+ final int len) throws SaslException
+ {
+ // if (DEBUG && debuglevel > 8) debug(TRACE, "==> engineWrap()");
+ //
+ // if (outMac == null && outCipher == null) {
+ // throw new IllegalStateException("connection is not protected");
+ // }
+ //
+ // byte[] data = new byte[len];
+ // System.arraycopy(outgoing, offset, data, 0, len);
+ //
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Outgoing buffer (before security) (hex): "+Util.dumpString(data));
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Outgoing buffer (before security) (str): \""+new String(data)+"\"");
+ //
+ // final byte[] result;
+ // try {
+ // OutputBuffer frameOut = new OutputBuffer();
+ // // Process the data
+ // if (outCipher != null) {
+ // data = outCipher.doFinal(data);
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Encoding c (encrypted plaintext): "+Util.dumpString(data));
+ // } else {
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Encoding p (plaintext): "+Util.dumpString(data));
+ // }
+ // frameOut.setEOS(data);
+ // if (outMac != null) {
+ // outMac.update(data);
+ // if (replayDetection) {
+ // outCounter++;
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "outCounter="+String.valueOf(outCounter));
+ // outMac.update(new byte[] {
+ // (byte)(outCounter >>> 24),
+ // (byte)(outCounter >>> 16),
+ // (byte)(outCounter >>> 8),
+ // (byte) outCounter});
+ // }
+ // byte[] C = outMac.doFinal();
+ // frameOut.setOS(C);
+ // if (DEBUG && debuglevel > 6) debug(TRACE, "Encoding C (integrity checksum): "+Util.dumpString(C));
+ // }
+ // result = frameOut.wrap();
+ //
+ // } catch (IOException x) {
+ // if (x instanceof SaslException) {
+ // throw (SaslException) x;
+ // }
+ // throw new SaslException("engineWrap()", x);
+ // }
+ //
+ // if (DEBUG && debuglevel > 8) debug(TRACE, "<== engineWrap()");
+ // return result;
+
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> engineWrap()");
+
+ if (outMac == null && outCipher == null)
+ {
+ throw new IllegalStateException("connection is not protected");
+ }
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Outgoing buffer (before security) (hex): "
+ + Util.dumpString(outgoing, offset, len));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Outgoing buffer (before security) (str): \""
+ + new String(outgoing, offset, len) + "\"");
+
+ // at this point one, or both, of confidentiality and integrity protection
+ // services are active.
+
+ byte[] result;
+ try
+ {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ if (outCipher != null)
+ {
+ result = outCipher.doFinal(outgoing, offset, len);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding c (encrypted plaintext): "
+ + Util.dumpString(result));
+
+ out.write(result);
+
+ if (outMac != null)
+ {
+ outMac.update(result);
+ if (replayDetection)
+ {
+ outCounter++;
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "outCounter=" + String.valueOf(outCounter));
+ outMac.update(new byte[] { (byte) (outCounter >>> 24),
+ (byte) (outCounter >>> 16),
+ (byte) (outCounter >>> 8),
+ (byte) outCounter });
+ }
+ final byte[] C = outMac.doFinal();
+ out.write(C);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding C (integrity checksum): "
+ + Util.dumpString(C));
+ } // else ciphertext only; do nothing
+ }
+ else
+ { // no confidentiality; just integrity [+ replay detection]
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding p (plaintext): "
+ + Util.dumpString(outgoing, offset, len));
+
+ out.write(outgoing, offset, len);
+
+ // if (outMac != null) {
+ outMac.update(outgoing, offset, len);
+ if (replayDetection)
+ {
+ outCounter++;
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "outCounter=" + String.valueOf(outCounter));
+ outMac.update(new byte[] { (byte) (outCounter >>> 24),
+ (byte) (outCounter >>> 16),
+ (byte) (outCounter >>> 8),
+ (byte) outCounter });
+ }
+ final byte[] C = outMac.doFinal();
+ out.write(C);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding C (integrity checksum): "
+ + Util.dumpString(C));
+ // } // else plaintext only; do nothing
+ }
+
+ result = out.toByteArray();
+
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new SaslException("engineWrap()", x);
+ }
+
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== engineWrap()");
+ return result;
+ }
+
+ protected String getNegotiatedQOP()
+ {
+ if (inMac != null)
+ {
+ if (inCipher != null)
+ {
+ return Registry.QOP_AUTH_CONF;
+ }
+ else
+ {
+ return Registry.QOP_AUTH_INT;
+ }
+ }
+ return Registry.QOP_AUTH;
+ }
+
+ protected String getNegotiatedStrength()
+ {
+ if (inMac != null)
+ {
+ if (inCipher != null)
+ {
+ return Registry.STRENGTH_HIGH;
+ }
+ else
+ {
+ return Registry.STRENGTH_MEDIUM;
+ }
+ }
+ return Registry.STRENGTH_LOW;
+ }
+
+ protected String getNegotiatedRawSendSize()
+ {
+ return String.valueOf(rawSendSize);
+ }
+
+ protected String getReuse()
+ {
+ return Registry.REUSE_TRUE;
+ }
+
+ // other methods -----------------------------------------------------------
+
+ private byte[] sendProtocolElements(final byte[] input) throws SaslException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> sendProtocolElements()");
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "C: " + Util.dumpString(input));
+
+ // Client send U, I, sid, cn
+ final InputBuffer frameIn = new InputBuffer(input);
+ try
+ {
+ U = frameIn.getText(); // Extract username
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got U (username): \"" + U + "\"");
+ authorizationID = frameIn.getText(); // Extract authorisation ID
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got I (userid): \"" + authorizationID + "\"");
+ sid = frameIn.getEOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got sid (session ID): " + new String(sid));
+ cn = frameIn.getOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got cn (client nonce): " + Util.dumpString(cn));
+ cCB = frameIn.getEOS();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got cCB (client channel binding): "
+ + Util.dumpString(cCB));
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("sendProtocolElements()", x);
+ }
+
+ // do/can we re-use?
+ if (ServerStore.instance().isAlive(sid))
+ {
+ final SecurityContext ctx = ServerStore.instance().restoreSession(sid);
+ srp = SRP.instance(ctx.getMdName());
+ K = ctx.getK();
+ cIV = ctx.getClientIV();
+ sIV = ctx.getServerIV();
+ replayDetection = ctx.hasReplayDetection();
+ inCounter = ctx.getInCounter();
+ outCounter = ctx.getOutCounter();
+ inMac = ctx.getInMac();
+ outMac = ctx.getOutMac();
+ inCipher = ctx.getInCipher();
+ outCipher = ctx.getOutCipher();
+
+ if (sn == null || sn.length != 16)
+ {
+ sn = new byte[16];
+ }
+ new SecureRandom ().nextBytes(sn);
+
+ setupSecurityServices(false);
+
+ final OutputBuffer frameOut = new OutputBuffer();
+ try
+ {
+ frameOut.setScalar(1, 0xFF);
+ frameOut.setOS(sn);
+ frameOut.setEOS(channelBinding);
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("sendProtocolElements()", x);
+ }
+ final byte[] result = frameOut.encode();
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== sendProtocolElements()");
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "Old session...");
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "S: " + Util.dumpString(result));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " sn = " + Util.dumpString(sn));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " sCB = " + Util.dumpString(channelBinding));
+ return result;
+ }
+ else
+ { // new session
+ authenticator.activate(properties);
+
+ // -------------------------------------------------------------------
+ final HashMap mapB = new HashMap();
+ // mapB.put(SRP6KeyAgreement.HASH_FUNCTION, srp.newDigest());
+ mapB.put(SRP6KeyAgreement.HASH_FUNCTION, srp.getAlgorithm());
+ mapB.put(SRP6KeyAgreement.HOST_PASSWORD_DB, authenticator);
+
+ try
+ {
+ serverHandler.init(mapB);
+ OutgoingMessage out = new OutgoingMessage();
+ out.writeString(U);
+ IncomingMessage in = new IncomingMessage(out.toByteArray());
+ out = serverHandler.processMessage(in);
+
+ in = new IncomingMessage(out.toByteArray());
+ N = in.readMPI();
+ g = in.readMPI();
+ s = in.readMPI().toByteArray();
+ B = in.readMPI();
+ }
+ catch (KeyAgreementException x)
+ {
+ throw new SaslException("sendProtocolElements()", x);
+ }
+ // -------------------------------------------------------------------
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding N (modulus): " + Util.dump(N));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding g (generator): " + Util.dump(g));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding s (client's salt): " + Util.dumpString(s));
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding B (server ephemeral public key): "
+ + Util.dump(B));
+
+ // The server creates an options list (L), which consists of a
+ // comma-separated list of option strings that specify the security
+ // service options the server supports.
+ L = createL();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding L (available options): \"" + L + "\"");
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Encoding sIV (server IV): " + Util.dumpString(sIV));
+
+ final OutputBuffer frameOut = new OutputBuffer();
+ try
+ {
+ frameOut.setScalar(1, 0x00);
+ frameOut.setMPI(N);
+ frameOut.setMPI(g);
+ frameOut.setOS(s);
+ frameOut.setMPI(B);
+ frameOut.setText(L);
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("sendProtocolElements()", x);
+ }
+ final byte[] result = frameOut.encode();
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== sendProtocolElements()");
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "New session...");
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "S: " + Util.dumpString(result));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " N = 0x" + N.toString(16));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " g = 0x" + g.toString(16));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " s = " + Util.dumpString(s));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " B = 0x" + B.toString(16));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " L = " + L);
+ return result;
+ }
+ }
+
+ private byte[] sendEvidence(final byte[] input) throws SaslException
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> sendEvidence()");
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "C: " + Util.dumpString(input));
+
+ // Client send A, M1, o, cIV
+ final InputBuffer frameIn = new InputBuffer(input);
+ final byte[] M1;
+ try
+ {
+ A = frameIn.getMPI(); // Extract client's ephemeral public key
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got A (client ephemeral public key): " + Util.dump(A));
+ M1 = frameIn.getOS(); // Extract evidence
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got M1 (client evidence): " + Util.dumpString(M1));
+ o = frameIn.getText(); // Extract client's options list
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got o (client chosen options): \"" + o + "\"");
+ cIV = frameIn.getOS(); // Extract client's IV
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "Got cIV (client IV): " + Util.dumpString(cIV));
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("sendEvidence()", x);
+ }
+
+ // Parse client's options and set security layer variables
+ parseO(o);
+
+ // ----------------------------------------------------------------------
+ try
+ {
+ final OutgoingMessage out = new OutgoingMessage();
+ out.writeMPI(A);
+ final IncomingMessage in = new IncomingMessage(out.toByteArray());
+ serverHandler.processMessage(in);
+ K = serverHandler.getSharedSecret();
+ }
+ catch (KeyAgreementException x)
+ {
+ throw new SaslException("sendEvidence()", x);
+ }
+ // ----------------------------------------------------------------------
+
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "K: " + Util.dumpString(K));
+
+ final byte[] expected;
+ try
+ {
+ expected = srp.generateM1(N, g, U, s, A, B, K, authorizationID, L, cn,
+ cCB);
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new AuthenticationException("sendEvidence()", x);
+ }
+
+ // Verify client evidence
+ if (!Arrays.equals(M1, expected))
+ {
+ throw new AuthenticationException("M1 mismatch");
+ }
+
+ setupSecurityServices(true);
+
+ final byte[] M2;
+ try
+ {
+ M2 = srp.generateM2(A, M1, K, U, authorizationID, o, sid, ttl, cIV,
+ sIV, channelBinding);
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new AuthenticationException("sendEvidence()", x);
+ }
+
+ final OutputBuffer frameOut = new OutputBuffer();
+ try
+ {
+ frameOut.setOS(M2);
+ frameOut.setOS(sIV);
+ frameOut.setEOS(sid);
+ frameOut.setScalar(4, ttl);
+ frameOut.setEOS(channelBinding);
+ }
+ catch (IOException x)
+ {
+ if (x instanceof SaslException)
+ {
+ throw (SaslException) x;
+ }
+ throw new AuthenticationException("sendEvidence()", x);
+ }
+ final byte[] result = frameOut.encode();
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "S: " + Util.dumpString(result));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " M2 = " + Util.dumpString(M2));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " sIV = " + Util.dumpString(sIV));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " sid = " + new String(sid));
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " ttl = " + ttl);
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, " sCB = " + Util.dumpString(channelBinding));
+
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== sendEvidence()");
+ return result;
+ }
+
+ private String createL()
+ {
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "==> createL()");
+
+ String s = (String) properties.get(SRPRegistry.SRP_MANDATORY);
+ if (s == null)
+ {
+ s = SRPRegistry.DEFAULT_MANDATORY;
+ }
+ if (!SRPRegistry.MANDATORY_NONE.equals(s)
+ && !SRPRegistry.OPTION_REPLAY_DETECTION.equals(s)
+ && !SRPRegistry.OPTION_INTEGRITY.equals(s)
+ && !SRPRegistry.OPTION_CONFIDENTIALITY.equals(s))
+ {
+ if (DEBUG && debuglevel > 4)
+ debug(WARN, "Unrecognised mandatory option (" + s
+ + "). Using default...");
+ s = SRPRegistry.DEFAULT_MANDATORY;
+ }
+
+ mandatory = s;
+
+ s = (String) properties.get(SRPRegistry.SRP_CONFIDENTIALITY);
+ final boolean confidentiality = (s == null ? SRPRegistry.DEFAULT_CONFIDENTIALITY
+ : Boolean.valueOf(s).booleanValue());
+
+ s = (String) properties.get(SRPRegistry.SRP_INTEGRITY_PROTECTION);
+ boolean integrity = (s == null ? SRPRegistry.DEFAULT_INTEGRITY
+ : Boolean.valueOf(s).booleanValue());
+
+ s = (String) properties.get(SRPRegistry.SRP_REPLAY_DETECTION);
+ final boolean replayDetection = (s == null ? SRPRegistry.DEFAULT_REPLAY_DETECTION
+ : Boolean.valueOf(s).booleanValue());
+
+ final StringBuffer sb = new StringBuffer();
+ sb.append(SRPRegistry.OPTION_SRP_DIGEST).append("=").append(
+ srp.getAlgorithm()).append(
+ ",");
+
+ if (!SRPRegistry.MANDATORY_NONE.equals(mandatory))
+ {
+ sb.append(SRPRegistry.OPTION_MANDATORY).append("=").append(mandatory).append(
+ ",");
+ }
+ if (replayDetection)
+ {
+ sb.append(SRPRegistry.OPTION_REPLAY_DETECTION).append(",");
+ // if replay detection is on then force integrity protection
+ integrity = true;
+ }
+
+ int i;
+ if (integrity)
+ {
+ for (i = 0; i < SRPRegistry.INTEGRITY_ALGORITHMS.length; i++)
+ {
+ sb.append(SRPRegistry.OPTION_INTEGRITY).append("=").append(
+ SRPRegistry.INTEGRITY_ALGORITHMS[i]).append(
+ ",");
+ }
+ }
+
+ if (confidentiality)
+ {
+ IBlockCipher cipher;
+ for (i = 0; i < SRPRegistry.CONFIDENTIALITY_ALGORITHMS.length; i++)
+ {
+ cipher = CipherFactory.getInstance(SRPRegistry.CONFIDENTIALITY_ALGORITHMS[i]);
+ if (cipher != null)
+ {
+ sb.append(SRPRegistry.OPTION_CONFIDENTIALITY).append("=").append(
+ SRPRegistry.CONFIDENTIALITY_ALGORITHMS[i]).append(
+ ",");
+ }
+ }
+ }
+
+ final String result = sb.append(SRPRegistry.OPTION_MAX_BUFFER_SIZE).append(
+ "=").append(
+ Registry.SASL_BUFFER_MAX_LIMIT).toString();
+ if (DEBUG && debuglevel > 8)
+ debug(TRACE, "<== createL()");
+ return result;
+ }
+
+ // Parse client's options and set security layer variables
+ private void parseO(final String o) throws AuthenticationException
+ {
+ this.replayDetection = false;
+ boolean integrity = false;
+ boolean confidentiality = false;
+ String option;
+ int i;
+
+ final StringTokenizer st = new StringTokenizer(o.toLowerCase(), ",");
+ while (st.hasMoreTokens())
+ {
+ option = st.nextToken();
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "option: <" + option + ">");
+ if (option.equals(SRPRegistry.OPTION_REPLAY_DETECTION))
+ {
+ replayDetection = true;
+ }
+ else if (option.startsWith(SRPRegistry.OPTION_INTEGRITY + "="))
+ {
+ if (integrity)
+ {
+ throw new AuthenticationException(
+ "Only one integrity algorithm may be chosen");
+ }
+ else
+ {
+ option = option.substring(option.indexOf('=') + 1);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "algorithm: <" + option + ">");
+ for (i = 0; i < SRPRegistry.INTEGRITY_ALGORITHMS.length; i++)
+ {
+ if (SRPRegistry.INTEGRITY_ALGORITHMS[i].equals(option))
+ {
+ chosenIntegrityAlgorithm = option;
+ integrity = true;
+ break;
+ }
+ }
+ if (!integrity)
+ {
+ throw new AuthenticationException(
+ "Unknown integrity algorithm: "
+ + option);
+ }
+ }
+ }
+ else if (option.startsWith(SRPRegistry.OPTION_CONFIDENTIALITY + "="))
+ {
+ if (confidentiality)
+ {
+ throw new AuthenticationException(
+ "Only one confidentiality algorithm may be chosen");
+ }
+ else
+ {
+ option = option.substring(option.indexOf('=') + 1);
+ if (DEBUG && debuglevel > 6)
+ debug(TRACE, "algorithm: <" + option + ">");
+ for (i = 0; i < SRPRegistry.CONFIDENTIALITY_ALGORITHMS.length; i++)
+ {
+ if (SRPRegistry.CONFIDENTIALITY_ALGORITHMS[i].equals(option))
+ {
+ chosenConfidentialityAlgorithm = option;
+ confidentiality = true;
+ break;
+ }
+ }
+ if (!confidentiality)
+ {
+ throw new AuthenticationException(
+ "Unknown confidentiality algorithm: "
+ + option);
+ }
+ }
+ }
+ else if (option.startsWith(SRPRegistry.OPTION_MAX_BUFFER_SIZE + "="))
+ {
+ final String maxBufferSize = option.substring(option.indexOf('=') + 1);
+ try
+ {
+ rawSendSize = Integer.parseInt(maxBufferSize);
+ if (rawSendSize > Registry.SASL_BUFFER_MAX_LIMIT
+ || rawSendSize < 1)
+ throw new AuthenticationException(
+ "Illegal value for 'maxbuffersize' option");
+ }
+ catch (NumberFormatException x)
+ {
+ throw new AuthenticationException(
+ SRPRegistry.OPTION_MAX_BUFFER_SIZE
+ + "="
+ + String.valueOf(maxBufferSize),
+ x);
+ }
+ }
+ }
+
+ // check if client did the right thing
+ if (replayDetection)
+ {
+ if (!integrity)
+ {
+ throw new AuthenticationException(
+ "Missing integrity protection algorithm "
+ + "but replay detection is chosen");
+ }
+ }
+ if (mandatory.equals(SRPRegistry.OPTION_REPLAY_DETECTION))
+ {
+ if (!replayDetection)
+ {
+ throw new AuthenticationException(
+ "Replay detection is mandatory but was not chosen");
+ }
+ }
+ if (mandatory.equals(SRPRegistry.OPTION_INTEGRITY))
+ {
+ if (!integrity)
+ {
+ throw new AuthenticationException(
+ "Integrity protection is mandatory but was not chosen");
+ }
+ }
+ if (mandatory.equals(SRPRegistry.OPTION_CONFIDENTIALITY))
+ {
+ if (!confidentiality)
+ {
+ throw new AuthenticationException(
+ "Confidentiality is mandatory but was not chosen");
+ }
+ }
+
+ int blockSize = 0;
+ if (chosenConfidentialityAlgorithm != null)
+ {
+ final IBlockCipher cipher = CipherFactory.getInstance(chosenConfidentialityAlgorithm);
+ if (cipher != null)
+ {
+ blockSize = cipher.defaultBlockSize();
+ }
+ else
+ { // should not happen
+ throw new AuthenticationException("Confidentiality algorithm ("
+ + chosenConfidentialityAlgorithm
+ + ") not available");
+ }
+ }
+
+ sIV = new byte[blockSize];
+ if (blockSize > 0)
+ {
+ new SecureRandom ().nextBytes(sIV);
+ }
+ }
+
+ private void setupSecurityServices(final boolean newSession)
+ throws SaslException
+ {
+ complete = true; // signal end of authentication phase
+ if (newSession)
+ {
+ outCounter = inCounter = 0;
+ // instantiate cipher if confidentiality protection filter is active
+ if (chosenConfidentialityAlgorithm != null)
+ {
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "Activating confidentiality protection filter");
+ inCipher = CALG.getInstance(chosenConfidentialityAlgorithm);
+ outCipher = CALG.getInstance(chosenConfidentialityAlgorithm);
+ }
+ // instantiate hmacs if integrity protection filter is active
+ if (chosenIntegrityAlgorithm != null)
+ {
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "Activating integrity protection filter");
+ inMac = IALG.getInstance(chosenIntegrityAlgorithm);
+ outMac = IALG.getInstance(chosenIntegrityAlgorithm);
+ }
+
+ // generate a new sid if at least integrity is used
+ sid = (inMac != null ? ServerStore.getNewSessionID() : new byte[0]);
+ }
+ else
+ { // same session new keys
+ K = srp.generateKn(K, cn, sn);
+ }
+
+ final KDF kdf = KDF.getInstance(K);
+
+ // initialise in/out ciphers if confidentaility protection is used
+ if (inCipher != null)
+ {
+ outCipher.init(kdf, sIV, Direction.FORWARD);
+ inCipher.init(kdf, cIV, Direction.REVERSED);
+ }
+ // initialise in/out macs if integrity protection is used
+ if (inMac != null)
+ {
+ outMac.init(kdf);
+ inMac.init(kdf);
+ }
+
+ if (sid != null && sid.length != 0)
+ { // update the security context and save in map
+ if (DEBUG && debuglevel > 2)
+ debug(INFO, "Updating security context for sid = " + new String(sid));
+ ServerStore.instance().cacheSession(
+ ttl,
+ new SecurityContext(
+ srp.getAlgorithm(),
+ sid,
+ K,
+ cIV,
+ sIV,
+ replayDetection,
+ inCounter,
+ outCounter,
+ inMac, outMac,
+ inCipher,
+ outCipher));
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/SecurityContext.java b/gnu/javax/crypto/sasl/srp/SecurityContext.java
new file mode 100644
index 000000000..feca25cad
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/SecurityContext.java
@@ -0,0 +1,164 @@
+/* SecurityContext.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+/**
+ * <p>A package-private placeholder for an SRP security context.</p>
+ */
+class SecurityContext
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private String mdName;
+
+ private byte[] sid;
+
+ private byte[] K;
+
+ private byte[] cIV;
+
+ private byte[] sIV;
+
+ private boolean replayDetection;
+
+ private int inCounter;
+
+ private int outCounter;
+
+ private IALG inMac;
+
+ private IALG outMac;
+
+ private CALG inCipher;
+
+ private CALG outCipher;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ SecurityContext(final String mdName, final byte[] sid, final byte[] K,
+ final byte[] cIV, final byte[] sIV,
+ final boolean replayDetection, final int inCounter,
+ final int outCounter, final IALG inMac, final IALG outMac,
+ final CALG inCipher, final CALG outCipher)
+ {
+ super();
+
+ this.mdName = mdName;
+ this.sid = sid;
+ this.K = K;
+ this.cIV = cIV;
+ this.sIV = sIV;
+ this.replayDetection = replayDetection;
+ this.inCounter = inCounter;
+ this.outCounter = outCounter;
+ this.inMac = inMac;
+ this.outMac = outMac;
+ this.inCipher = inCipher;
+ this.outCipher = outCipher;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ String getMdName()
+ {
+ return mdName;
+ }
+
+ byte[] getSID()
+ {
+ return sid;
+ }
+
+ byte[] getK()
+ {
+ return K;
+ }
+
+ byte[] getClientIV()
+ {
+ return cIV;
+ }
+
+ byte[] getServerIV()
+ {
+ return sIV;
+ }
+
+ boolean hasReplayDetection()
+ {
+ return replayDetection;
+ }
+
+ int getInCounter()
+ {
+ return inCounter;
+ }
+
+ int getOutCounter()
+ {
+ return outCounter;
+ }
+
+ IALG getInMac()
+ {
+ return inMac;
+ }
+
+ IALG getOutMac()
+ {
+ return outMac;
+ }
+
+ CALG getInCipher()
+ {
+ return inCipher;
+ }
+
+ CALG getOutCipher()
+ {
+ return outCipher;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/ServerStore.java b/gnu/javax/crypto/sasl/srp/ServerStore.java
new file mode 100644
index 000000000..99bf96a94
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/ServerStore.java
@@ -0,0 +1,196 @@
+/* ServerStore.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+import java.util.HashMap;
+
+/**
+ * <p>The server-side implementation of the SRP security context store.</p>
+ */
+public class ServerStore
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The underlying singleton. */
+ private static ServerStore singleton = null;
+
+ /** The map of sid --> Security Context record. */
+ private static final HashMap sid2ssc = new HashMap();
+
+ /** The map of sid --> Session timing record. */
+ private static final HashMap sid2ttl = new HashMap();
+
+ /** A synchronisation lock. */
+ private static final Object lock = new Object();
+
+ /** A counter to generate legible SIDs. */
+ private static int counter = 0;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Private constructor to enforce Singleton pattern. */
+ private ServerStore()
+ {
+ super();
+
+ // TODO: add a cleaning timer thread
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the classloader Singleton.</p>
+ *
+ * @return the classloader Singleton instance.
+ */
+ static synchronized final ServerStore instance()
+ {
+ if (singleton == null)
+ {
+ singleton = new ServerStore();
+ }
+ return singleton;
+ }
+
+ /**
+ * <p>Returns a legible new session identifier.</p>
+ *
+ * @return a new session identifier.
+ */
+ static synchronized final byte[] getNewSessionID()
+ {
+ final String sid = String.valueOf(++counter);
+ return new StringBuffer("SID-").append(
+ "0000000000".substring(
+ 0,
+ 10 - sid.length())).append(
+ sid).toString().getBytes();
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns a boolean flag indicating if the designated session is still
+ * alive or not.</p>
+ *
+ * @param sid the identifier of the session to check.
+ * @return <code>true</code> if the designated session is still alive.
+ * <code>false</code> otherwise.
+ */
+ boolean isAlive(final byte[] sid)
+ {
+ boolean result = false;
+ if (sid != null && sid.length != 0)
+ {
+ synchronized (lock)
+ {
+ final String key = new String(sid);
+ final StoreEntry ctx = (StoreEntry) sid2ttl.get(key);
+ if (ctx != null)
+ {
+ result = ctx.isAlive();
+ if (!result)
+ { // invalidate it en-passant
+ sid2ssc.remove(key);
+ sid2ttl.remove(key);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * <p>Records a mapping between a session identifier and the Security Context
+ * of the designated SRP server mechanism instance.</p>
+ *
+ * @param ttl the session's Time-To-Live indicator (in seconds).
+ * @param ctx the server's security context.
+ */
+ void cacheSession(final int ttl, final SecurityContext ctx)
+ {
+ synchronized (lock)
+ {
+ final String key = new String(ctx.getSID());
+ sid2ssc.put(key, ctx);
+ sid2ttl.put(key, new StoreEntry(ttl));
+ }
+ }
+
+ /**
+ * <p>Updates the mapping between the designated session identifier and the
+ * designated server's SASL Security Context. In the process, computes
+ * and return the underlying mechanism server's evidence that shall be
+ * returned to the client in a session re-use exchange.</p>
+ *
+ * @param sid the identifier of the session to restore.
+ * @return an SRP server's security context.
+ */
+ SecurityContext restoreSession(final byte[] sid)
+ {
+ final String key = new String(sid);
+ final SecurityContext result;
+ synchronized (lock)
+ {
+ result = (SecurityContext) sid2ssc.remove(key);
+ sid2ttl.remove(key);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Removes all information related to the designated session ID.</p>
+ *
+ * @param sid the identifier of the seesion to invalidate.
+ */
+ void invalidateSession(final byte[] sid)
+ {
+ final String key = new String(sid);
+ synchronized (lock)
+ {
+ sid2ssc.remove(key);
+ sid2ttl.remove(key);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/crypto/sasl/srp/StoreEntry.java b/gnu/javax/crypto/sasl/srp/StoreEntry.java
new file mode 100644
index 000000000..c5041fa4b
--- /dev/null
+++ b/gnu/javax/crypto/sasl/srp/StoreEntry.java
@@ -0,0 +1,89 @@
+/* StoreEntry.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.sasl.srp;
+
+/**
+ * <p>A simple timing-related object for use by SRP re-use code.</p>
+ */
+class StoreEntry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private boolean perenial;
+
+ private long timeToDie;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ StoreEntry(int ttl)
+ {
+ super();
+
+ if (ttl == 0)
+ {
+ perenial = true;
+ timeToDie = 0L;
+ }
+ else
+ {
+ perenial = false;
+ timeToDie = System.currentTimeMillis() + (ttl & 0xFFFFFFFFL) * 1000L;
+ }
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns <code>true</code> if the Time-To_live period has not elapsed.</p>
+ *
+ * @return <code>true</code> if the Time-To-Live period (in seconds) has not
+ * elapsed yet; <code>false</code> otherwise.
+ */
+ boolean isAlive()
+ {
+ return (perenial ? true : (System.currentTimeMillis() < timeToDie));
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/Base64.java b/gnu/javax/net/ssl/Base64.java
new file mode 100644
index 000000000..52989da69
--- /dev/null
+++ b/gnu/javax/net/ssl/Base64.java
@@ -0,0 +1,311 @@
+/* Base64.java -- Base64 encoding and decoding.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+
+--
+Base64 encoding derived from ISC's DHCP. Copyright notices from DHCP
+follow. See http://www.isc.org/products/DHCP/.
+
+Copyright (c) 1996 by Internet Software Consortium.
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+--
+Portions Copyright (c) 1995 by International Business Machines, Inc.
+
+International Business Machines, Inc. (hereinafter called IBM) grants
+permission under its copyrights to use, copy, modify, and distribute
+this Software with or without fee, provided that the above copyright
+notice and all paragraphs of this notice appear in all copies, and
+that the name of IBM not be used in connection with the marketing of
+any product incorporating the Software or modifications thereof,
+without specific, written prior permission.
+
+To the extent it has a right to do so, IBM grants an immunity from
+suit under its patents, if any, for the use, sale or manufacture of
+products to the extent that such products are used for performing
+Domain Name System dynamic updates in TCP/IP networks by means of the
+Software. No immunity is granted for any product per se or for any
+other function of any product.
+
+THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE, EVEN IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH
+DAMAGES. */
+
+
+package gnu.javax.net.ssl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public final class Base64
+{
+
+ // No constructor.
+ private Base64() { }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /** Base-64 characters. */
+ private static final String BASE_64 =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ /** Base-64 padding character. */
+ private static final char BASE_64_PAD = '=';
+
+ /**
+ * Base64 encode a byte array, returning the returning string.
+ *
+ * @param buf The byte array to encode.
+ * @param tw The total length of any line, 0 for unlimited.
+ * @return <tt>buf</tt> encoded in Base64.
+ */
+ public static String encode(byte[] buf, int tw)
+ {
+ int srcLength = buf.length;
+ byte[] input = new byte[3];
+ int[] output = new int[4];
+ StringBuffer out = new StringBuffer();
+ int i = 0;
+ int chars = 0;
+
+ while (srcLength > 2)
+ {
+ input[0] = buf[i++];
+ input[1] = buf[i++];
+ input[2] = buf[i++];
+ srcLength -= 3;
+
+ output[0] = (input[0] & 0xff) >>> 2;
+ output[1] = ((input[0] & 0x03) << 4) + ((input[1] & 0xff) >>> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + ((input[2] & 0xff) >>> 6);
+ output[3] = input[2] & 0x3f;
+
+ out.append(BASE_64.charAt(output[0]));
+ if (tw > 0 && ++chars % tw == 0)
+ {
+ out.append("\n");
+ }
+ out.append(BASE_64.charAt(output[1]));
+ if (tw > 0 && ++chars % tw == 0)
+ {
+ out.append("\n");
+ }
+ out.append(BASE_64.charAt(output[2]));
+ if (tw > 0 && ++chars % tw == 0)
+ {
+ out.append("\n");
+ }
+ out.append(BASE_64.charAt(output[3]));
+ if (tw > 0 && ++chars % tw == 0)
+ {
+ out.append("\n");
+ }
+ }
+
+ if (srcLength != 0)
+ {
+ input[0] = input[1] = input[2] = 0;
+ for (int j = 0; j < srcLength; j++)
+ {
+ input[j] = buf[i+j];
+ }
+ output[0] = (input[0] & 0xff) >>> 2;
+ output[1] = ((input[0] & 0x03) << 4) + ((input[1] & 0xff) >>> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + ((input[2] & 0xff) >>> 6);
+
+ out.append(BASE_64.charAt(output[0]));
+ if (tw > 0 && ++chars % tw == 0)
+ {
+ out.append("\n");
+ }
+ out.append(BASE_64.charAt(output[1]));
+ if (tw > 0 && ++chars % tw == 0)
+ {
+ out.append("\n");
+ }
+ if (srcLength == 1)
+ {
+ out.append(BASE_64_PAD);
+ }
+ else
+ {
+ out.append(BASE_64.charAt(output[2]));
+ }
+ if (tw > 0 && ++chars % tw == 0)
+ {
+ out.append("\n");
+ }
+ out.append(BASE_64_PAD);
+ if (tw > 0 && ++chars % tw == 0)
+ {
+ out.append("\n");
+ }
+ }
+ if (tw > 0)
+ {
+ out.append("\n");
+ }
+
+ return out.toString();
+ }
+
+ /**
+ * Decode a Base-64 string into a byte array.
+ *
+ * @param b64 The Base-64 encoded string.
+ * @return The decoded bytes.
+ * @throws java.io.IOException If the argument is not a valid Base-64
+ * encoding.
+ */
+ public static byte[] decode(String b64) throws IOException
+ {
+ ByteArrayOutputStream result = new ByteArrayOutputStream(b64.length() / 3);
+ int state = 0, i;
+ byte temp = 0;
+
+ for (i = 0; i < b64.length(); i++)
+ {
+ if (Character.isWhitespace(b64.charAt(i)))
+ {
+ continue;
+ }
+ if (b64.charAt(i) == BASE_64_PAD)
+ {
+ break;
+ }
+
+ int pos = BASE_64.indexOf(b64.charAt(i));
+ if (pos < 0)
+ {
+ throw new IOException("non-Base64 character " + b64.charAt(i));
+ }
+ switch (state)
+ {
+ case 0:
+ temp = (byte) (pos - BASE_64.indexOf('A') << 2);
+ state = 1;
+ break;
+
+ case 1:
+ temp |= (byte) (pos - BASE_64.indexOf('A') >>> 4);
+ result.write(temp);
+ temp = (byte) ((pos - BASE_64.indexOf('A') & 0x0f) << 4);
+ state = 2;
+ break;
+
+ case 2:
+ temp |= (byte) ((pos - BASE_64.indexOf('A') & 0x7f) >>> 2);
+ result.write(temp);
+ temp = (byte) ((pos - BASE_64.indexOf('A') & 0x03) << 6);
+ state = 3;
+ break;
+
+ case 3:
+ temp |= (byte) (pos - BASE_64.indexOf('A') & 0xff);
+ result.write(temp);
+ state = 0;
+ break;
+
+ default:
+ throw new Error("this statement should be unreachable");
+ }
+ }
+
+ if (i < b64.length() && b64.charAt(i) == BASE_64_PAD)
+ {
+ switch (state)
+ {
+ case 0:
+ case 1:
+ throw new IOException("malformed Base64 sequence");
+
+ case 2:
+ for ( ; i < b64.length(); i++)
+ {
+ if (!Character.isWhitespace(b64.charAt(i)))
+ {
+ break;
+ }
+ }
+ // We must see a second pad character here.
+ if (b64.charAt(i) != BASE_64_PAD)
+ {
+ throw new IOException("malformed Base64 sequence");
+ }
+ i++;
+ // Fall-through.
+
+ case 3:
+ i++;
+ for ( ; i < b64.length(); i++)
+ {
+ // We should only see whitespace after this.
+ if (!Character.isWhitespace(b64.charAt(i)))
+ {
+ System.err.println(b64.charAt(i));
+ throw new IOException("malformed Base64 sequence");
+ }
+ }
+ }
+ }
+ else
+ {
+ if (state != 0)
+ {
+ throw new IOException("malformed Base64 sequence");
+ }
+ }
+
+ return result.toByteArray();
+ }
+}
diff --git a/gnu/javax/net/ssl/EntropySource.java b/gnu/javax/net/ssl/EntropySource.java
new file mode 100644
index 000000000..be840e5d6
--- /dev/null
+++ b/gnu/javax/net/ssl/EntropySource.java
@@ -0,0 +1,62 @@
+/* EntropySource.java -- a source of random bits.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+/**
+ * A generic interface for adding random bytes to an entropy pool.
+ */
+public interface EntropySource
+{
+
+ /**
+ * Returns the estimated quality of this source. This value should be
+ * between 0 and 100 (the running quality is computed as a percentage,
+ * 100 percent being perfect-quality).
+ *
+ * @return The quality.
+ */
+ double quality();
+
+ /**
+ * Returns a new buffer with the next random bytes to add.
+ *
+ * @return The next random bytes.
+ */
+ byte[] nextBytes();
+}
diff --git a/gnu/javax/net/ssl/NullManagerParameters.java b/gnu/javax/net/ssl/NullManagerParameters.java
new file mode 100644
index 000000000..0e9337932
--- /dev/null
+++ b/gnu/javax/net/ssl/NullManagerParameters.java
@@ -0,0 +1,56 @@
+/* NullManagerParameters.java -- parameters for empty managers.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import javax.net.ssl.ManagerFactoryParameters;
+
+/**
+ * This empty class can be used to initialize {@link
+ * javax.net.ssl.KeyManagerFactory} and {@link
+ * javax.net.ssl.TrustManagerFactory} instances for the ``JessieX509''
+ * algorithm, for cases when no keys or trusted certificates are
+ * desired or needed.
+ *
+ * <p>This is the default manager parameters object used in {@link
+ * javax.net.ssl.KeyManagerFactory} instances if no key stores are
+ * specified through security properties.
+ */
+public final class NullManagerParameters implements ManagerFactoryParameters
+{
+}
diff --git a/gnu/javax/net/ssl/PrivateCredentials.java b/gnu/javax/net/ssl/PrivateCredentials.java
new file mode 100644
index 000000000..f602f98ae
--- /dev/null
+++ b/gnu/javax/net/ssl/PrivateCredentials.java
@@ -0,0 +1,360 @@
+/* PrivateCredentials.java -- private key/certificate pairs.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+
+import java.math.BigInteger;
+
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.RSAPrivateCrtKeySpec;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.net.ssl.ManagerFactoryParameters;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import gnu.javax.security.auth.callback.ConsoleCallbackHandler;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+import gnu.javax.crypto.pad.WrongPaddingException;
+
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+
+/**
+ * An instance of a manager factory parameters for holding a single
+ * certificate/private key pair, encoded in PEM format.
+ */
+public class PrivateCredentials implements ManagerFactoryParameters
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ public static final String BEGIN_DSA = "-----BEGIN DSA PRIVATE KEY";
+ public static final String END_DSA = "-----END DSA PRIVATE KEY";
+ public static final String BEGIN_RSA = "-----BEGIN RSA PRIVATE KEY";
+ public static final String END_RSA = "-----END RSA PRIVATE KEY";
+
+ private List privateKeys;
+ private List certChains;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public PrivateCredentials()
+ {
+ privateKeys = new LinkedList();
+ certChains = new LinkedList();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void add(InputStream certChain, InputStream privateKey)
+ throws CertificateException, InvalidKeyException, InvalidKeySpecException,
+ IOException, NoSuchAlgorithmException, WrongPaddingException
+ {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ Collection certs = cf.generateCertificates(certChain);
+ X509Certificate[] chain = (X509Certificate[]) certs.toArray(new X509Certificate[0]);
+
+ String alg = null;
+ String line = readLine(privateKey);
+ String finalLine = null;
+ if (line.startsWith(BEGIN_DSA))
+ {
+ alg = "DSA";
+ finalLine = END_DSA;
+ }
+ else if (line.startsWith(BEGIN_RSA))
+ {
+ alg = "RSA";
+ finalLine = END_RSA;
+ }
+ else
+ throw new IOException("Unknown private key type.");
+
+ boolean encrypted = false;
+ String cipher = null;
+ String salt = null;
+ StringBuffer base64 = new StringBuffer();
+ while (true)
+ {
+ line = readLine(privateKey);
+ if (line == null)
+ throw new EOFException("premature end-of-file");
+ else if (line.startsWith("Proc-Type: 4,ENCRYPTED"))
+ encrypted = true;
+ else if (line.startsWith("DEK-Info: "))
+ {
+ int i = line.indexOf(',');
+ if (i < 0)
+ cipher = line.substring(10).trim();
+ else
+ {
+ cipher = line.substring(10, i).trim();
+ salt = line.substring(i + 1).trim();
+ }
+ }
+ else if (line.startsWith(finalLine))
+ break;
+ else if (line.length() > 0)
+ {
+ base64.append(line);
+ base64.append(System.getProperty("line.separator"));
+ }
+ }
+
+ byte[] enckey = Base64.decode(base64.toString());
+ if (encrypted)
+ {
+ enckey = decryptKey(enckey, cipher, toByteArray(salt));
+ }
+
+ DERReader der = new DERReader(enckey);
+ if (der.read().getTag() != DER.SEQUENCE)
+ throw new IOException("malformed DER sequence");
+ der.read(); // version
+
+ KeyFactory kf = KeyFactory.getInstance(alg);
+ KeySpec spec = null;
+ if (alg.equals("DSA"))
+ {
+ BigInteger p = (BigInteger) der.read().getValue();
+ BigInteger q = (BigInteger) der.read().getValue();
+ BigInteger g = (BigInteger) der.read().getValue();
+ der.read(); // y
+ BigInteger x = (BigInteger) der.read().getValue();
+ spec = new DSAPrivateKeySpec(x, p, q, g);
+ }
+ else
+ {
+ spec = new RSAPrivateCrtKeySpec(
+ (BigInteger) der.read().getValue(), // modulus
+ (BigInteger) der.read().getValue(), // pub exponent
+ (BigInteger) der.read().getValue(), // priv expenent
+ (BigInteger) der.read().getValue(), // prime p
+ (BigInteger) der.read().getValue(), // prime q
+ (BigInteger) der.read().getValue(), // d mod (p-1)
+ (BigInteger) der.read().getValue(), // d mod (q-1)
+ (BigInteger) der.read().getValue()); // coefficient
+ }
+ privateKeys.add(kf.generatePrivate(spec));
+ certChains.add(chain);
+ }
+
+ public List getPrivateKeys()
+ {
+ if (isDestroyed())
+ {
+ throw new IllegalStateException("this object is destroyed");
+ }
+ return privateKeys;
+ }
+
+ public List getCertChains()
+ {
+ return certChains;
+ }
+
+ public void destroy()
+ {
+ privateKeys.clear();
+ privateKeys = null;
+ }
+
+ public boolean isDestroyed()
+ {
+ return (privateKeys == null);
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private String readLine(InputStream in) throws IOException
+ {
+ boolean eol_is_cr = System.getProperty("line.separator").equals("\r");
+ StringBuffer str = new StringBuffer();
+ while (true)
+ {
+ int i = in.read();
+ if (i == -1)
+ {
+ if (str.length() > 0)
+ break;
+ else
+ return null;
+ }
+ else if (i == '\r')
+ {
+ if (eol_is_cr)
+ break;
+ }
+ else if (i == '\n')
+ break;
+ else
+ str.append((char) i);
+ }
+ return str.toString();
+ }
+
+ private byte[] decryptKey(byte[] ct, String cipher, byte[] salt)
+ throws IOException, InvalidKeyException, WrongPaddingException
+ {
+ byte[] pt = new byte[ct.length];
+ IMode mode = null;
+ if (cipher.equals("DES-EDE3-CBC"))
+ {
+ mode = ModeFactory.getInstance("CBC", "TripleDES", 8);
+ HashMap attr = new HashMap();
+ attr.put(IMode.KEY_MATERIAL, deriveKey(salt, 24));
+ attr.put(IMode.IV, salt);
+ attr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
+ mode.init(attr);
+ }
+ else if (cipher.equals("DES-CBC"))
+ {
+ mode = ModeFactory.getInstance("CBC", "DES", 8);
+ HashMap attr = new HashMap();
+ attr.put(IMode.KEY_MATERIAL, deriveKey(salt, 8));
+ attr.put(IMode.IV, salt);
+ attr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
+ mode.init(attr);
+ }
+ else
+ throw new IllegalArgumentException("unknown cipher: " + cipher);
+
+ for (int i = 0; i < ct.length; i += 8)
+ mode.update(ct, i, pt, i);
+
+ int pad = pt[pt.length-1];
+ if (pad < 1 || pad > 8)
+ throw new WrongPaddingException();
+ for (int i = pt.length - pad; i < pt.length; i++)
+ {
+ if (pt[i] != pad)
+ throw new WrongPaddingException();
+ }
+
+ byte[] result = new byte[pt.length - pad];
+ System.arraycopy(pt, 0, result, 0, result.length);
+ return result;
+ }
+
+ private byte[] deriveKey(byte[] salt, int keylen)
+ throws IOException
+ {
+ CallbackHandler passwordHandler = new ConsoleCallbackHandler();
+ try
+ {
+ Class c = Class.forName(Security.getProperty("jessie.password.handler"));
+ passwordHandler = (CallbackHandler) c.newInstance();
+ }
+ catch (Exception x) { }
+
+ PasswordCallback passwdCallback =
+ new PasswordCallback("Enter PEM passphrase: ", false);
+ try
+ {
+ passwordHandler.handle(new Callback[] { passwdCallback });
+ }
+ catch (UnsupportedCallbackException uce)
+ {
+ throw new IOException("specified handler cannot handle passwords");
+ }
+ char[] passwd = passwdCallback.getPassword();
+
+ IMessageDigest md5 = HashFactory.getInstance("MD5");
+ byte[] key = new byte[keylen];
+ int count = 0;
+ while (count < keylen)
+ {
+ for (int i = 0; i < passwd.length; i++)
+ md5.update((byte) passwd[i]);
+ md5.update(salt, 0, salt.length);
+ byte[] digest = md5.digest();
+ int len = Math.min(digest.length, keylen - count);
+ System.arraycopy(digest, 0, key, count, len);
+ count += len;
+ if (count >= keylen)
+ break;
+ md5.reset();
+ md5.update(digest, 0, digest.length);
+ }
+ passwdCallback.clearPassword();
+ return key;
+ }
+
+ private byte[] toByteArray(String hex)
+ {
+ hex = hex.toLowerCase();
+ byte[] buf = new byte[hex.length() / 2];
+ int j = 0;
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = (byte) ((Character.digit(hex.charAt(j++), 16) << 4) |
+ Character.digit(hex.charAt(j++), 16));
+ }
+ return buf;
+ }
+}
diff --git a/gnu/javax/net/ssl/SRPManagerParameters.java b/gnu/javax/net/ssl/SRPManagerParameters.java
new file mode 100644
index 000000000..a2a745e1b
--- /dev/null
+++ b/gnu/javax/net/ssl/SRPManagerParameters.java
@@ -0,0 +1,81 @@
+/* SRPManagerParameters.java -- Wrapper for SRP PasswordFile.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import javax.net.ssl.ManagerFactoryParameters;
+import gnu.javax.crypto.sasl.srp.PasswordFile;
+
+/**
+ * Instances of this class are used to initialize {@link
+ * javax.net.ssl.TrustManagerFactory} instances for the ``SRP'' algorithm.
+ */
+public class SRPManagerParameters implements ManagerFactoryParameters
+{
+
+ // Field.
+ // -------------------------------------------------------------------------
+
+ private final PasswordFile file;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Initializes these parameters with the specified SRP password file.
+ *
+ * @param file The SRP password file object.
+ * @throws NullPointerException if <i>file</i> is <code>null</code>.
+ */
+ public SRPManagerParameters(PasswordFile file)
+ {
+ if (file == null)
+ {
+ throw new NullPointerException();
+ }
+ this.file = file;
+ }
+
+ // Instance method.
+ // -------------------------------------------------------------------------
+
+ public PasswordFile getPasswordFile()
+ {
+ return file;
+ }
+}
diff --git a/gnu/javax/net/ssl/SRPTrustManager.java b/gnu/javax/net/ssl/SRPTrustManager.java
new file mode 100644
index 000000000..664fa4cab
--- /dev/null
+++ b/gnu/javax/net/ssl/SRPTrustManager.java
@@ -0,0 +1,99 @@
+/* SRPTrustManager.java -- interface to SRP trust managers.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import gnu.javax.crypto.sasl.srp.PasswordFile;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import javax.net.ssl.TrustManager;
+
+/**
+ * A trust manager for secure remote password (SRP) key exchange cipher
+ * suites. This is a read-only interface to the {@link
+ * gnu.crypto.sasl.srp.PasswordFile} class, with convenience methods to
+ * generate session key pairs.
+ */
+public interface SRPTrustManager extends TrustManager
+{
+
+ // Methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Tests if the configured password file contains the specified user name.
+ *
+ * @param user The user name.
+ * @return True if the password file has an entry for <i>user</i>
+ */
+ boolean contains(String user);
+
+ /**
+ * Create and return a session SRP key pair for the given user name.
+ *
+ * @param user The user name to generate the key pair for.
+ * @return The session key pair, or <code>null</code> if there is no
+ * entry for <i>user</i>.
+ */
+ KeyPair getKeyPair(String user);
+
+ /**
+ * Returns the salt value for the given user.
+ *
+ * @param user The user name.
+ * @return The salt for <i>user</i>'s entry, or <code>null</code>.
+ */
+ byte[] getSalt(String user);
+
+ /**
+ * Returns the password verifier for the given user.
+ *
+ * @param user The user name.
+ * @return <i>user</i>'s password verifier, or <code>null</code>.
+ */
+ BigInteger getVerifier(String user);
+
+ /**
+ * Returns a reference to the SRP {@link PasswordFile} used by this
+ * {@link TrustManager}.
+ *
+ * @return a reference to the SRP password file in use.
+ */
+ PasswordFile getPasswordFile();
+}
diff --git a/gnu/javax/net/ssl/StaticTrustAnchors.java b/gnu/javax/net/ssl/StaticTrustAnchors.java
new file mode 100644
index 000000000..0c2c3cca8
--- /dev/null
+++ b/gnu/javax/net/ssl/StaticTrustAnchors.java
@@ -0,0 +1,1942 @@
+/* StaticTrustAnchors.java -- static list of CA certificates.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import java.util.LinkedList;
+
+import javax.net.ssl.ManagerFactoryParameters;
+
+/**
+ * This class implements a simple set of trust anchors suitable for
+ * initializing a TrustManagerFactory for the "JessieX509" algorithm.
+ *
+ * <p>The important field of this class is the {@link #CA_CERTS}
+ * constant, which contains an array of commonly accepted CA
+ * certificates.
+ */
+public class StaticTrustAnchors implements ManagerFactoryParameters
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private X509Certificate[] certs;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public StaticTrustAnchors(X509Certificate[] certs)
+ {
+ this.certs = (X509Certificate[]) certs.clone();
+ }
+
+ // Class method.
+ // -------------------------------------------------------------------------
+
+ public static X509Certificate generate(CertificateFactory factory,
+ String encoded)
+ {
+ try
+ {
+ ByteArrayInputStream in =
+ new ByteArrayInputStream(encoded.getBytes("UTF-8"));
+ return (X509Certificate) factory.generateCertificate(in);
+ }
+ catch (Exception x)
+ {
+ return null;
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public X509Certificate[] getCertificates()
+ {
+ return (X509Certificate[]) certs.clone();
+ }
+
+ // Constant.
+ // -------------------------------------------------------------------------
+
+ /**
+ * A list of known certificate authority certificates. This set of
+ * certificates is the same as the default CA certificates used by
+ * Mozilla.
+ */
+ public static final StaticTrustAnchors CA_CERTS;
+
+ // Static initializer.
+ // -------------------------------------------------------------------------
+
+ static
+ {
+ LinkedList certs = new LinkedList();
+ CertificateFactory factory = null;
+
+ try
+ {
+ factory = CertificateFactory.getInstance("X.509");
+ }
+ catch (CertificateException ce)
+ {
+ throw new Error(ce.toString());
+ }
+
+ X509Certificate cert = generate(factory,
+ // ABAecom_=sub.__Am._Bankers_Assn.=_Root_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDtTCCAp2gAwIBAgIRANAeQJAAAEZSAAAAAQAAAAQwDQYJKoZIhvcNAQEF\n" +
+ "BQAwgYkxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJEQzETMBEGA1UEBxMKV2Fz\n" +
+ "aGluZ3RvbjEXMBUGA1UEChMOQUJBLkVDT00sIElOQy4xGTAXBgNVBAMTEEFC\n" +
+ "QS5FQ09NIFJvb3QgQ0ExJDAiBgkqhkiG9w0BCQEWFWFkbWluQGRpZ3NpZ3Ry\n" +
+ "dXN0LmNvbTAeFw05OTA3MTIxNzMzNTNaFw0wOTA3MDkxNzMzNTNaMIGJMQsw\n" +
+ "CQYDVQQGEwJVUzELMAkGA1UECBMCREMxEzARBgNVBAcTCldhc2hpbmd0b24x\n" +
+ "FzAVBgNVBAoTDkFCQS5FQ09NLCBJTkMuMRkwFwYDVQQDExBBQkEuRUNPTSBS\n" +
+ "b290IENBMSQwIgYJKoZIhvcNAQkBFhVhZG1pbkBkaWdzaWd0cnVzdC5jb20w\n" +
+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx0xHgeVVDBwhMywVC\n" +
+ "AOINg0Y95JO6tgbTDVm9PsHOQ2cBiiGo77zM0KLMsFWWU4RmBQDaREmA2FQK\n" +
+ "pSWGlO1jVv9wbKOhGdJ4vmgqRF4vz8wYXke8OrFGPR7wuSw0X4x8TAgpnUBV\n" +
+ "6zx9g9618PeKgw6hTLQ6pbNfWiKX7BmbwQVo/ea3qZGULOR4SCQaJRk665Wc\n" +
+ "OQqKz0Ky8BzVX/tr7WhWezkscjiw7pOp03t3POtxA6k4ShZsiSrK2jMTecJV\n" +
+ "jO2cu/LLWxD4LmE1xilMKtAqY9FlWbT4zfn0AIS2V0KFnTKo+SpU+/94Qby9\n" +
+ "cSj0u5C8/5Y0BONFnqFGKECBAgMBAAGjFjAUMBIGA1UdEwEB/wQIMAYBAf8C\n" +
+ "AQgwDQYJKoZIhvcNAQEFBQADggEBAARvJYbk5pYntNlCwNDJALF/VD6Hsm0k\n" +
+ "qS8Kfv2kRLD4VAe9G52dyntQJHsRW0mjpr8SdNWJt7cvmGQlFLdh6X9ggGvT\n" +
+ "ZOirvRrWUfrAtF13Gn9kCF55xgVM8XrdTX3O5kh7VNJhkoHWG9YA8A6eKHeg\n" +
+ "TYjHInYZw8eeG6Z3ePhfm1bR8PIXrI6dWeYf/le22V7hXZ9F7GFoGUHhsiAm\n" +
+ "/lowdiT/QHI8eZ98IkirRs3bs4Ysj78FQdPB4xTjQRcm0HyncUwZ6EoPclgx\n" +
+ "fexgeqMiKL0ZJGA/O4dzwGvky663qyVDslUte6sGDnVdNOVdc22esnVApVnJ\n" +
+ "TzFxiNmIf1Q=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // AOL_Time_Warner_Root_Certification_Authority_1.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMC\n" +
+ "VVMxHTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNB\n" +
+ "bWVyaWNhIE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIg\n" +
+ "Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyOTA2MDAw\n" +
+ "MFoXDTM3MTEyMDE1MDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRB\n" +
+ "T0wgVGltZSBXYXJuZXIgSW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUg\n" +
+ "SW5jLjE3MDUGA1UEAxMuQU9MIFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNh\n" +
+ "dGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
+ "ggEBAJnej8Mlo2k06AX3dLm/WpcZuS+U0pPlLYnKhHw/EEMbjIt8hFj4JHxI\n" +
+ "zyr9wBXZGH6EGhfT257XyuTZ16pYUYfw8ItITuLCxFlpMGK2MKKMCxGZYTVt\n" +
+ "fu/FsRkGIBKOQuHfD5YQUqjPnF+VFNivO3ULMSAfRC+iYkGzuxgh28pxPIzs\n" +
+ "trkNn+9R7017EvILDOGsQI93f7DKeHEMXRZxcKLXwjqFzQ6axOAAsNUl6twr\n" +
+ "5JQtOJyJQVdkKGUZHLZEtMgxa44Be3ZZJX8VHIQIfHNlIAqhBC4aMqiaILGc\n" +
+ "LCFZ5/vP7nAtCMpjPiybkxlqpMKX/7eGV4iFbJ4VFitNLLMCAwEAAaNjMGEw\n" +
+ "DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoTYwFsuGkABFgFOxj8jYPXy+\n" +
+ "XxIwHwYDVR0jBBgwFoAUoTYwFsuGkABFgFOxj8jYPXy+XxIwDgYDVR0PAQH/\n" +
+ "BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQCKIBilvrMvtKaEAEAwKfq0FHNM\n" +
+ "eUWn9nDg6H5kHgqVfGphwu9OH77/yZkfB2FK4V1Mza3u0FIy2VkyvNp5ctZ7\n" +
+ "CegCgTXTCt8RHcl5oIBN/lrXVtbtDyqvpxh1MwzqwWEFT2qaifKNuZ8u77Bf\n" +
+ "WgDrvq2g+EQFZ7zLBO+eZMXpyD8Fv8YvBxzDNnGGyjhmSs3WuEvGbKeXO/oT\n" +
+ "LW4jYYehY0KswsuXn2Fozy1MBJ3XJU8KDk2QixhWqJNIV9xvrr2eZ1d3iVCz\n" +
+ "vhGbRWeDhhmH05i9CBoWH1iCC+GWaQVLjuyDUTEH1dSf/1l7qG6Fz9NLqUmw\n" +
+ "X7A5KGgOc90lmt4S\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // AOL_Time_Warner_Root_Certification_Authority_2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMC\n" +
+ "VVMxHTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNB\n" +
+ "bWVyaWNhIE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIg\n" +
+ "Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAw\n" +
+ "MFoXDTM3MDkyODIzNDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRB\n" +
+ "T0wgVGltZSBXYXJuZXIgSW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUg\n" +
+ "SW5jLjE3MDUGA1UEAxMuQU9MIFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNh\n" +
+ "dGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\n" +
+ "ggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ7ouZzU9AhqS2TcnZsdw8TQ2FTBVs\n" +
+ "RotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilbm2BPJoPRYxJWSXakFsKlnUWs\n" +
+ "i4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOYxFSMFkpBd4aVdQxHAWZg\n" +
+ "/BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZYYCLqJV+FNwSbKTQ\n" +
+ "2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbqJS5Gr42whTg0\n" +
+ "ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fxI2rSAG2X\n" +
+ "+Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETzkxml\n" +
+ "J85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh\n" +
+ "EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNo\n" +
+ "Kk/SBtc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJ\n" +
+ "Kg71ZDIMgtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1Ex\n" +
+ "MVCgyhwn2RAurda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMB\n" +
+ "Af8wHQYDVR0OBBYEFE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaA\n" +
+ "FE9pbQN+nZ8HGEO8txBO1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG\n" +
+ "9w0BAQUFAAOCAgEAO/Ouyuguh4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0\n" +
+ "cnAxa8cZmIDJgt43d15Ui47y6mdPyXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRF\n" +
+ "ASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q7C+qPBR7V8F+GBRn7iTGvboVsNIY\n" +
+ "vbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKTRuidDV29rs4prWPVVRaAMCf/\n" +
+ "drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ClTluUI8JPu3B5wwn3la\n" +
+ "5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyBM5kYJRF3p+v9WAks\n" +
+ "mWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQmy8YJPamTQr5\n" +
+ "O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xOAU++CrYD\n" +
+ "062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT9Y41\n" +
+ "xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H\n" +
+ "hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOL\n" +
+ "Z8/5fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // AddTrust_External_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJT\n" +
+ "RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4\n" +
+ "dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5h\n" +
+ "bCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzEL\n" +
+ "MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1B\n" +
+ "ZGRUcnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1\n" +
+ "c3QgRXh0ZXJuYWwgQ0EgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n" +
+ "AQoCggEBALf3GjPm8gAELTngTlvtH7xsD821+iO2zt6bETOXpClMfZOfvUq8\n" +
+ "k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfwTz/oMp50\n" +
+ "ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504\n" +
+ "B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDez\n" +
+ "eWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5\n" +
+ "aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0WicCAwEAAaOB\n" +
+ "3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0PBAQD\n" +
+ "AgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6\n" +
+ "xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU\n" +
+ "cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdv\n" +
+ "cmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJ\n" +
+ "KoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl\n" +
+ "j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5R\n" +
+ "xNKWt9x+Tu5w/Rw56wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjT\n" +
+ "K3rMUUKhemPR5ruhxSvCNr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1\n" +
+ "n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHx\n" +
+ "REzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49O\n" +
+ "hgQ=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // AddTrust_Low-Value_Services_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJT\n" +
+ "RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRU\n" +
+ "UCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3Qw\n" +
+ "HhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJT\n" +
+ "RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRU\n" +
+ "UCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3Qw\n" +
+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwze\n" +
+ "xODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY654eyNAbFvAWlA3yCyykQruGI\n" +
+ "gb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWroulpOj0O\n" +
+ "M3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1Lc\n" +
+ "sRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5\n" +
+ "mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG\n" +
+ "9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0OBBYEFJWxtPCU\n" +
+ "tr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTADAQH/\n" +
+ "MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQsw\n" +
+ "CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk\n" +
+ "ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAx\n" +
+ "IENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0\n" +
+ "MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph\n" +
+ "iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9\n" +
+ "tTEv2dB8Xfjea4MYeDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL\n" +
+ "/bscVjby/rK25Xa71SJlpz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlV\n" +
+ "g3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6\n" +
+ "tkD9xOQ14R0WHNC8K47Wcdk=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // AddTrust_Public_Services_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJT\n" +
+ "RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRU\n" +
+ "UCBOZXR3b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAe\n" +
+ "Fw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNF\n" +
+ "MRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ\n" +
+ "IE5ldHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIB\n" +
+ "IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+\n" +
+ "A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c\n" +
+ "+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1id9NEHif2\n" +
+ "P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKX\n" +
+ "C1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8R\n" +
+ "s3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9\n" +
+ "BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQWBBSBPjfYkrAf\n" +
+ "d59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zCB\n" +
+ "jgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkG\n" +
+ "A1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU\n" +
+ "cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENB\n" +
+ "IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmu\n" +
+ "G7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL\n" +
+ "+YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbj\n" +
+ "PGsye/Kf8Lb93/AoGEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bY\n" +
+ "GozH7ZxOmuASu7VqTITh4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6\n" +
+ "NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9HEufOX1362Kqx\n" +
+ "My3ZdvJOOjMMK7MtkAY=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // AddTrust_Qualified_Certificates_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJT\n" +
+ "RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRU\n" +
+ "UCBOZXR3b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9v\n" +
+ "dDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYT\n" +
+ "AlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3Qg\n" +
+ "VFRQIE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBS\n" +
+ "b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoek\n" +
+ "n0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKk\n" +
+ "IhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3KP0q6p6z\n" +
+ "sLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1t\n" +
+ "UvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R\n" +
+ "+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvES\n" +
+ "a0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0GA1UdDgQWBBQ5\n" +
+ "lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw\n" +
+ "AwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkw\n" +
+ "ZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL\n" +
+ "ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVh\n" +
+ "bGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2Vh\n" +
+ "lRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG\n" +
+ "GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx9\n" +
+ "5dr6h+sNNVJn0J6XdgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKF\n" +
+ "Yqa0p9m9N5xotS1WfbC3P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVA\n" +
+ "wRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQw\n" +
+ "dOUeqN48Jzd/g66ed8/wMLH/S5noxqE=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // America_Online_Root_Certification_Authority_1.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJV\n" +
+ "UzEcMBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1l\n" +
+ "cmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4X\n" +
+ "DTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMx\n" +
+ "HDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJp\n" +
+ "Y2EgT25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw\n" +
+ "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCa\n" +
+ "xlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CGv2BlnEtUiMJIxUo5vxTjWVXl\n" +
+ "GbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44zDyL9Hy7n\n" +
+ "BzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145Lcx\n" +
+ "VR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiE\n" +
+ "mf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCu\n" +
+ "JKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNV\n" +
+ "HQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Zo/Z5\n" +
+ "9m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUA\n" +
+ "A4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF\n" +
+ "Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOM\n" +
+ "IOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTI\n" +
+ "dGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g\n" +
+ "Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j\n" +
+ "8uB9Gr784N/Xx6dssPmuujz9dLQR6FgNgLzTqIA6me11zEZ7\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // America_Online_Root_Certification_Authority_2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJV\n" +
+ "UzEcMBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1l\n" +
+ "cmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4X\n" +
+ "DTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMx\n" +
+ "HDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJp\n" +
+ "Y2EgT25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw\n" +
+ "DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssN\n" +
+ "t79Hc9PwVU3dxgz6sWYFas14tNwC206B89enfHG8dWOgXeMHDEjsJcQDIPT/\n" +
+ "DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8f3SkWq7x\n" +
+ "uhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE\n" +
+ "18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxr\n" +
+ "kJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMD\n" +
+ "bi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8BPeraunzgWGcX\n" +
+ "uVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn6KVu\n" +
+ "Y8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9\n" +
+ "W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ\n" +
+ "o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48\n" +
+ "ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124Hhn\n" +
+ "AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op\n" +
+ "aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNee\n" +
+ "MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypL\n" +
+ "M7PmG2tZTiLMubekJcmnxPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qf\n" +
+ "tIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjR\n" +
+ "Ywu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R\n" +
+ "+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr\n" +
+ "+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVM\n" +
+ "nNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMADjMSW7yV5TKQqLPGbIOt\n" +
+ "d+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh1NolNscI\n" +
+ "WC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZ\n" +
+ "ZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y\n" +
+ "3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz\n" +
+ "2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw\n" +
+ "RY8mkaKO/qk=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Baltimore_CyberTrust_Code_Signing_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDpjCCAo6gAwIBAgIEAgAAvzANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQG\n" +
+ "EwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0\n" +
+ "MS8wLQYDVQQDEyZCYWx0aW1vcmUgQ3liZXJUcnVzdCBDb2RlIFNpZ25pbmcg\n" +
+ "Um9vdDAeFw0wMDA1MTcxNDAxMDBaFw0yNTA1MTcyMzU5MDBaMGcxCzAJBgNV\n" +
+ "BAYTAklFMRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1\n" +
+ "c3QxLzAtBgNVBAMTJkJhbHRpbW9yZSBDeWJlclRydXN0IENvZGUgU2lnbmlu\n" +
+ "ZyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHGaGBKO\n" +
+ "etv5mvxBr9jy9AmOrT/+Zzc82skmULGxPsvoTnMA8rLc88VG+wnvGJbOp+Cc\n" +
+ "hF0gDnqgqjaL+ii2eC6z7OhH8wTwkCO06q/lU7gF90ddK4bxp6TGOzW20g1S\n" +
+ "Qdf0knXhogpQVoe+lwt7M4UQuSgY7jPqSBHXW5FHdiLU7s9d56hOHJ2Wkd2c\n" +
+ "vXQJqHJhqrAhOvE9LANWCdLB3MO1x1Q3q+YmorJGcXPKEYjuvOdk99ARGnNA\n" +
+ "WshJLA+375B/aIAEOAsbDzvU9aCzwo7hNLSAmW2edtSSKUCxldI3pGcSf+Bi\n" +
+ "u641xZk2gkS45ngYM2Fxk1stjZ94lYLrbQIDAQABo1owWDATBgNVHSUEDDAK\n" +
+ "BggrBgEFBQcDAzAdBgNVHQ4EFgQUyEE0XBUVBOVA8tGrmm8kknqHQlowEgYD\n" +
+ "VR0TAQH/BAgwBgEB/wIBAzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEF\n" +
+ "BQADggEBAFJ0qpVLIozHPZak/l36L7W86/AL6VY4HdFtDaG8aIvwxYClJDT9\n" +
+ "8pYYEYahNvU351RA1WQfw19wQmstOceeUgXO52py0o1yP0dQg6vHjSXJsOOn\n" +
+ "UxaVpmpT6hidj3ipd3ca+bSXR1mIJyi1yuEu1z4Oog24IkQD49FjsEE6ofWk\n" +
+ "Lfd2HgRUmXgyQNcrfE26ppyweW4Hvozs7tc4aVvBDFZon/7r0eHIiPnyzX++\n" +
+ "hbREZwBQPvQmA2Tqd33oXj4cN0fI1uqk8zY8l8I5cgWUGSXD1zdBD8Efh4r9\n" +
+ "qr7psWRX5NuSoc/hSeg7H5ETWsOP2SVYSYBHD8YDrqzjv7fAqio=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Baltimore_CyberTrust_Mobile_Commerce_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICfTCCAeagAwIBAgIEAgAAuDANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG\n" +
+ "EwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0\n" +
+ "MSkwJwYDVQQDEyBCYWx0aW1vcmUgQ3liZXJUcnVzdCBNb2JpbGUgUm9vdDAe\n" +
+ "Fw0wMDA1MTIxODIwMDBaFw0yMDA1MTIyMzU5MDBaMGExCzAJBgNVBAYTAklF\n" +
+ "MRIwEAYDVQQKEwlCYWx0aW1vcmUxEzARBgNVBAsTCkN5YmVyVHJ1c3QxKTAn\n" +
+ "BgNVBAMTIEJhbHRpbW9yZSBDeWJlclRydXN0IE1vYmlsZSBSb290MIGfMA0G\n" +
+ "CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjbbE4Vqz8tVYh3sCQXSZHgsZ9jx+g\n" +
+ "hY8vu9ThHB3yJB8osC+5pKVvoiIgZP6ERzx+K2xparjUwJaOjFINzW9B1L8E\n" +
+ "rqeBLy2YSNLBlKO1GV1dUWT0jkGwm8AtIqBexthaEmO8EUpeJhId4iYF5g9f\n" +
+ "Ih96X3aUrs9aKA6rRdoiMQIDAQABo0IwQDAdBgNVHQ4EFgQUyeKPwAImWrbA\n" +
+ "B+N/lAcY2y6lmnAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw\n" +
+ "DQYJKoZIhvcNAQEFBQADgYEAUwgLJgl4QnPU7Hp3Rw3jCzNx764zFE37+v0a\n" +
+ "t1H15JkcBnHXKRnX5hUgUVFGbU/eGEmY0Ph4u3HojQEG1ddkj5TfR/6ghWk2\n" +
+ "qS9CemhKEtaLC3BECqQE7yaIwTVxOF0bW0hC8OeUHHCVNKir9avieK318FL9\n" +
+ "m+pCDOjYVL5TZvU=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Baltimore_CyberTrust_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQG\n" +
+ "EwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0\n" +
+ "MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUx\n" +
+ "MjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNV\n" +
+ "BAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZ\n" +
+ "QmFsdGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQAD\n" +
+ "ggEPADCCAQoCggEBAKMEuyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+h\n" +
+ "Xe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gR\n" +
+ "QKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/CG9VwcPCP\n" +
+ "wBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1\n" +
+ "pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNT\n" +
+ "Px8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkC\n" +
+ "AwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1BE3wMBIGA1Ud\n" +
+ "EwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUA\n" +
+ "A4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkT\n" +
+ "I7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\n" +
+ "jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/\n" +
+ "oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67\n" +
+ "G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H\n" +
+ "RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Digital_Signature_Trust_Co._Global_CA_1.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQG\n" +
+ "EwJVUzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREw\n" +
+ "DwYDVQQLEwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQw\n" +
+ "MjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVy\n" +
+ "ZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEB\n" +
+ "AQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlR\n" +
+ "EmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+Lth\n" +
+ "zfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0\n" +
+ "dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBoBgNVHR8E\n" +
+ "YTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwg\n" +
+ "U2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNV\n" +
+ "BAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIx\n" +
+ "MDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5fpFpRhgTCgJ3\n" +
+ "pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAMBgNV\n" +
+ "HRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3\n" +
+ "DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN\n" +
+ "QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomA\n" +
+ "sH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6\n" +
+ "w4pl\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Digital_Signature_Trust_Co._Global_CA_2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIID2DCCAsACEQDQHkCLAAACfAAAAAIAAAABMA0GCSqGSIb3DQEBBQUAMIGp\n" +
+ "MQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBM\n" +
+ "YWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENv\n" +
+ "LjERMA8GA1UECxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDEx\n" +
+ "ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODEyMDEx\n" +
+ "ODE4NTVaFw0wODExMjgxODE4NTVaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UE\n" +
+ "CBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0Rp\n" +
+ "Z2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgWDEx\n" +
+ "FjAUBgNVBAMTDURTVCBSb290Q0EgWDExITAfBgkqhkiG9w0BCQEWEmNhQGRp\n" +
+ "Z3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" +
+ "ANLGJrbnpT3BxGjVUG9TxW9JEwm4ryxIjRRqoxdfWvnTLnUv2Chi0ZMv/E3U\n" +
+ "q4flCMeZ55I/db3rJbQVwZsZPdJEjdd0IG03Ao9pk1uKxBmd9LIO/BZsubEF\n" +
+ "koPRhSxglD5FVaDZqwgh5mDoO3TymVBRaNADLbGAvqPYUrBEzUNKcI5YhZXh\n" +
+ "TizWLUFv1oTnyJhEykfbLCSlaSbPa7gnYsP0yXqSI+0TZ4KuRS5F5X5yP4Wd\n" +
+ "lGIQ5jyRoa13AOAV7POEgHJ6jm5gl8ckWRA0g1vhpaRptlc1HHhZxtMvOnNn\n" +
+ "7pTKBBMFYgZwI7P0fO5F2WQLW0mqpEPOJsREEmy43XkCAwEAATANBgkqhkiG\n" +
+ "9w0BAQUFAAOCAQEAojeyP2n714Z5VEkxlTMr89EJFEliYIalsBHiUMIdBlc+\n" +
+ "LegzZL6bqq1fG03UmZWii5rJYnK1aerZWKs17RWiQ9a2vAd5ZWRzfdd5ynvV\n" +
+ "WlHG4VMElo04z6MXrDlxawHDi1M8Y+nuecDkvpIyZHqzH5eUYr3qsiAVlfuX\n" +
+ "8ngvYzZAOONGDx3drJXK50uQe7FLqdTF65raqtWjlBRGjS0f8zrWkzr2Pnn8\n" +
+ "6Oawde3uPclwx12qgUtGJRzHbBXjlU4PqjI3lAoXJJIThFjSY28r9+ZbYgsT\n" +
+ "F7ANUkz+/m9c4pFuHf2kYtdo+o56T9II2pPc8JIRetDccpMMc5NihWjQ9A==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Digital_Signature_Trust_Co._Global_CA_3.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQG\n" +
+ "EwJVUzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREw\n" +
+ "DwYDVQQLEwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3\n" +
+ "MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVy\n" +
+ "ZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEB\n" +
+ "AQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fB\n" +
+ "w18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87e\n" +
+ "ZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd\n" +
+ "55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBoBgNVHR8E\n" +
+ "YTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwg\n" +
+ "U2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNV\n" +
+ "BAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIw\n" +
+ "OTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6CTShlgDzJQW6s\n" +
+ "NS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAMBgNV\n" +
+ "HRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3\n" +
+ "DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR\n" +
+ "xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLb\n" +
+ "dHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlih\n" +
+ "w6ID\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Digital_Signature_Trust_Co._Global_CA_4.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIID2DCCAsACEQDQHkCLAAB3bQAAAAEAAAAEMA0GCSqGSIb3DQEBBQUAMIGp\n" +
+ "MQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBM\n" +
+ "YWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENv\n" +
+ "LjERMA8GA1UECxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIx\n" +
+ "ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODExMzAy\n" +
+ "MjQ2MTZaFw0wODExMjcyMjQ2MTZaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UE\n" +
+ "CBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0Rp\n" +
+ "Z2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgWDIx\n" +
+ "FjAUBgNVBAMTDURTVCBSb290Q0EgWDIxITAfBgkqhkiG9w0BCQEWEmNhQGRp\n" +
+ "Z3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" +
+ "ANx18IzAdZaawGIfJvfE4Zrq4FZzW5nNAUSoCLbVp9oaBBg5kkp4o4HC9Xd6\n" +
+ "ULRw/5qrxsfKboNPQpj7Jgva3G3WqZlVUmfpKAOS3OWwBZoPFflrWXJW8vo5\n" +
+ "/Kpo7g8fEIMv/J36F5bdguPmRX3AS4BEH+0s4IT9kVySVGkl5WJp3OXuAFK9\n" +
+ "MwutdQKFp2RQLcUZGTDAJtvJ0/0uma1ZtQtN1EGuhUhDWdy3qOKi3sOP17ih\n" +
+ "YqZoUFLkzzGnlIXan0YyF1bl8utmPRL/Q9uY73fPy4GNNLHGUEom0eQ+QVCv\n" +
+ "bK4iNC7Va26Dunm4dmVI2gkpZGMiuftHdoWMhkTLCdsCAwEAATANBgkqhkiG\n" +
+ "9w0BAQUFAAOCAQEAtTYOXeFhKFoRZcA/gwN5Tb4opgsHAlKFzfiR0BBstWog\n" +
+ "WxyQ2TA8xkieil5k+aFxd+8EJx8H6+Qm93N0yUQYGmbT4EOvkTvRyyzYdFQ6\n" +
+ "HE3K1GjNI3wdEJ5F6fYAbqbNGf9PLCmPV03Ed5K+4EwJ+11EhmYhqLkyolbV\n" +
+ "6YyDfFk/xPEL553snr2cGA4+wjl5KLcDDQjLxufZATdQEOzMYRZA1K8xdHv8\n" +
+ "PzGn0EdzMzkbzE5q10mDEQb+64JYMzJM8FasHpwvVpp7wUocpf1VNs78lk30\n" +
+ "sPDst2yC7S8xmUJMqbINuBVd8d+6ybVK1GSYsyapMMj9puyrliGtf8J4tg==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Entrust.net_Global_Secure_Personal_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEgzCCA+ygAwIBAgIEOJ725DANBgkqhkiG9w0BAQQFADCBtDEUMBIGA1UE\n" +
+ "ChMLRW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9HQ0NB\n" +
+ "X0NQUyBpbmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsT\n" +
+ "HChjKSAyMDAwIEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1\n" +
+ "c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAy\n" +
+ "MDcxNjE2NDBaFw0yMDAyMDcxNjQ2NDBaMIG0MRQwEgYDVQQKEwtFbnRydXN0\n" +
+ "Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0dDQ0FfQ1BTIGluY29y\n" +
+ "cC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDIwMDAg\n" +
+ "RW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2xp\n" +
+ "ZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA\n" +
+ "A4GNADCBiQKBgQCTdLS25MVL1qFof2LV7PdRV7NySpj10InJrWPNTTVRaoTU\n" +
+ "rcloeW+46xHbh65cJFET8VQlhK8pK5/jgOLZy93GRUk0iJBeAZfv6lOm3fzB\n" +
+ "3ksqJeTpNfpVBQbliXrqpBFXO/x8PTbNZzVtpKklWb1m9fkn5JVn1j+SgF7y\n" +
+ "NH0rhQIDAQABo4IBnjCCAZowEQYJYIZIAYb4QgEBBAQDAgAHMIHdBgNVHR8E\n" +
+ "gdUwgdIwgc+ggcyggcmkgcYwgcMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUAw\n" +
+ "PgYDVQQLFDd3d3cuZW50cnVzdC5uZXQvR0NDQV9DUFMgaW5jb3JwLiBieSBy\n" +
+ "ZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0\n" +
+ "Lm5ldCBMaW1pdGVkMTMwMQYDVQQDEypFbnRydXN0Lm5ldCBDbGllbnQgQ2Vy\n" +
+ "dGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw\n" +
+ "IoAPMjAwMDAyMDcxNjE2NDBagQ8yMDIwMDIwNzE2NDY0MFowCwYDVR0PBAQD\n" +
+ "AgEGMB8GA1UdIwQYMBaAFISLdP3FjcD/J20gN0V8/i3OutN9MB0GA1UdDgQW\n" +
+ "BBSEi3T9xY3A/ydtIDdFfP4tzrrTfTAMBgNVHRMEBTADAQH/MB0GCSqGSIb2\n" +
+ "fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQQFAAOBgQBObzWA\n" +
+ "O9GK9Q6nIMstZVXQkvTnhLUGJoMShAusO7JE7r3PQNsgDrpuFOow4DtifH+L\n" +
+ "a3xKp9U1PL6oXOpLu5OOgGarDyn9TS2/GpsKkMWr2tGzhtQvJFJcem3G8v7l\n" +
+ "TRowjJDyutdKPkN+1MhQGof4T4HHdguEOnKdzmVml64mXg==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Entrust.net_Global_Secure_Server_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIElTCCA/6gAwIBAgIEOJsRPDANBgkqhkiG9w0BAQQFADCBujEUMBIGA1UE\n" +
+ "ChMLRW50cnVzdC5uZXQxPzA9BgNVBAsUNnd3dy5lbnRydXN0Lm5ldC9TU0xf\n" +
+ "Q1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc\n" +
+ "KGMpIDIwMDAgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVz\n" +
+ "dC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe\n" +
+ "Fw0wMDAyMDQxNzIwMDBaFw0yMDAyMDQxNzUwMDBaMIG6MRQwEgYDVQQKEwtF\n" +
+ "bnRydXN0Lm5ldDE/MD0GA1UECxQ2d3d3LmVudHJ1c3QubmV0L1NTTF9DUFMg\n" +
+ "aW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykg\n" +
+ "MjAwMCBFbnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5l\n" +
+ "dCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0G\n" +
+ "CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHwV9OcfHO8GCGD9JYf9Mzly0XonUw\n" +
+ "tZZkJi9ow0SrqHXmAGc0V55lxyKbc+bT3QgON1WqJUaBbL3+qPZ1V1eMkGxK\n" +
+ "wz6LS0MKyRFWmponIpnPVZ5h2QLifLZ8OAfc439PmrkDQYC2dWcTC5/oVzbI\n" +
+ "XQA23mYU2m52H083jIITiQIDAQABo4IBpDCCAaAwEQYJYIZIAYb4QgEBBAQD\n" +
+ "AgAHMIHjBgNVHR8EgdswgdgwgdWggdKggc+kgcwwgckxFDASBgNVBAoTC0Vu\n" +
+ "dHJ1c3QubmV0MT8wPQYDVQQLFDZ3d3cuZW50cnVzdC5uZXQvU1NMX0NQUyBp\n" +
+ "bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAy\n" +
+ "MDAwIEVudHJ1c3QubmV0IExpbWl0ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0\n" +
+ "IFNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNV\n" +
+ "BAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMDAyMDQxNzIwMDBagQ8yMDIwMDIw\n" +
+ "NDE3NTAwMFowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFMtswGvjuz7L/CKc\n" +
+ "/vuLkpyw8m4iMB0GA1UdDgQWBBTLbMBr47s+y/winP77i5KcsPJuIjAMBgNV\n" +
+ "HRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkq\n" +
+ "hkiG9w0BAQQFAAOBgQBi24GRzsiad0Iv7L0no1MPUBvqTpLwqa+poLpIYcvv\n" +
+ "yQbvH9X07t9WLebKahlzqlO+krNQAraFJnJj2HVQYnUUt7NQGj/KEQALhUVp\n" +
+ "bbalrlHhStyCP2yMNLJ3a9kC9n8O6mUE8c1UyrrJzOCE98g+EZfTYAkYvAX/\n" +
+ "bIkz8OwVDw==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Entrust.net_Premium_2048_Secure_Server_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UE\n" +
+ "ChMLRW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNf\n" +
+ "MjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsT\n" +
+ "HChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1\n" +
+ "c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEy\n" +
+ "MjQxNzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0\n" +
+ "Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29y\n" +
+ "cC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkg\n" +
+ "RW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2Vy\n" +
+ "dGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEF\n" +
+ "AAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4\n" +
+ "QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/EC\n" +
+ "DNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj\n" +
+ "/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLP\n" +
+ "KQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZd\n" +
+ "enoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH\n" +
+ "4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB\n" +
+ "0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJ\n" +
+ "FrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B\n" +
+ "AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFh\n" +
+ "fGPjK50xA3B20qMooPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVU\n" +
+ "KcgF7bISKo30Axv/55IQh7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaoho\n" +
+ "wXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2\n" +
+ "+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof888\n" +
+ "6ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Entrust.net_Secure_Personal_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UE\n" +
+ "BhMCVVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50\n" +
+ "cnVzdC5uZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBs\n" +
+ "aW1pdHMgbGlhYi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExp\n" +
+ "bWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0\n" +
+ "aW9uIEF1dGhvcml0eTAeFw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBa\n" +
+ "MIHJMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNV\n" +
+ "BAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5mby9DUFMgaW5jb3Jw\n" +
+ "LiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMpIDE5OTkgRW50\n" +
+ "cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50\n" +
+ "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GL\n" +
+ "ADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo6oT9n3V5z8GKUZSv\n" +
+ "x1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDeg7K6PvHV\n" +
+ "iTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173\n" +
+ "iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSCARkw\n" +
+ "ggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50\n" +
+ "cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0Ff\n" +
+ "SW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UE\n" +
+ "CxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50\n" +
+ "cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYD\n" +
+ "VQQDEwRDUkwxMCygKqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9D\n" +
+ "bGllbnQxLmNybDArBgNVHRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkx\n" +
+ "MDEyMTkyNDMwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW\n" +
+ "/O5bs8qZdIuV6kwwHQYDVR0OBBYEFMT7nCl7l81MlvzuW7PKmXSLlepMMAwG\n" +
+ "A1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI\n" +
+ "hvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7pFuPeJoSSJn59DXeDDYHAmsQ\n" +
+ "OokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzzwy5E97BnRqqS5TvaHBkU\n" +
+ "ODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/aEkP/TOYGJqibGapE\n" +
+ "PHayXOw=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Entrust.net_Secure_Server_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UE\n" +
+ "BhMCVVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50\n" +
+ "cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl\n" +
+ "MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UE\n" +
+ "AxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1\n" +
+ "dGhvcml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQsw\n" +
+ "CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3\n" +
+ "dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlh\n" +
+ "Yi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVkMTow\n" +
+ "OAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp\n" +
+ "b24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0\n" +
+ "VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHIN\n" +
+ "iC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3wkrYKZImZNHk\n" +
+ "mGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcwggHT\n" +
+ "MBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHY\n" +
+ "pIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5\n" +
+ "BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChs\n" +
+ "aW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBM\n" +
+ "aW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl\n" +
+ "cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNo\n" +
+ "dHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAi\n" +
+ "gA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMC\n" +
+ "AQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYE\n" +
+ "FPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9\n" +
+ "B0EABAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKn\n" +
+ "CqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2Zcgx\n" +
+ "xufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd2cNgQ4xYDiKWL2KjLB+6\n" +
+ "rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Equifax_Secure_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQG\n" +
+ "EwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1\n" +
+ "cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4\n" +
+ "MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgx\n" +
+ "LTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0\n" +
+ "eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2R\n" +
+ "FGiYCh7+2gRvE4RiIcPRfM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO\n" +
+ "/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuv\n" +
+ "K9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAGA1UdHwRp\n" +
+ "MGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEt\n" +
+ "MCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5\n" +
+ "MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjAL\n" +
+ "BgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gjIBBPM5iQn9Qw\n" +
+ "HQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMBAf8w\n" +
+ "GgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GB\n" +
+ "AFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y\n" +
+ "7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2u\n" +
+ "FHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Equifax_Secure_Global_eBusiness_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJV\n" +
+ "UzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1\n" +
+ "aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0\n" +
+ "MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoT\n" +
+ "E0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJl\n" +
+ "IEdsb2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw\n" +
+ "gYkCgYEAuucXkAJlsTRVPEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQy\n" +
+ "td4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORR\n" +
+ "OhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxnhcXIw2EC\n" +
+ "AwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8w\n" +
+ "HwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6o\n" +
+ "oHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf\n" +
+ "2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkAZ70Br83gcfxa\n" +
+ "z2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIYNMR1\n" +
+ "pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Equifax_Secure_eBusiness_CA_1.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJV\n" +
+ "UzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1\n" +
+ "aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcN\n" +
+ "MjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZh\n" +
+ "eCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2lu\n" +
+ "ZXNzIENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fe\n" +
+ "k6lfWg0XTzQaDJj0ItlZ1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5\n" +
+ "/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4aIZX5UkxVWsUPOE9G+m34LjXW\n" +
+ "HXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBkMBEGCWCG\n" +
+ "SAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4\n" +
+ "MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBq\n" +
+ "R3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnm\n" +
+ "JXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+WB5Hh1Q+WKG1\n" +
+ "tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+KpYr\n" +
+ "tWKmpj29f5JZzVoqgrI3eQ==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Equifax_Secure_eBusiness_CA_2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQG\n" +
+ "EwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlm\n" +
+ "YXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5\n" +
+ "MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXgg\n" +
+ "U2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0Et\n" +
+ "MjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF\n" +
+ "7Y6yEb3+6+e0dMKP/wXn2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKD\n" +
+ "pkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HM\n" +
+ "HMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAGA1UdHwRp\n" +
+ "MGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBT\n" +
+ "ZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y\n" +
+ "MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjAL\n" +
+ "BgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBqy/3YIHqngnYw\n" +
+ "HQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMBAf8w\n" +
+ "GgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GB\n" +
+ "AAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy\n" +
+ "0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkt\n" +
+ "y3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // GTE_CyberTrust_Global_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgw\n" +
+ "FgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRy\n" +
+ "dXN0IFNvbHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3Qg\n" +
+ "R2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1\n" +
+ "MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYD\n" +
+ "VQQLEx5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMT\n" +
+ "GkdURSBDeWJlclRydXN0IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUA\n" +
+ "A4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9pTAipTHBsiQl8i4\n" +
+ "ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6XALn\n" +
+ "ZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8F\n" +
+ "LztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh3\n" +
+ "46B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq\n" +
+ "81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0PlZPvy5TYnh+d\n" +
+ "XIVtx6quTx8itc2VrbqnzPmrC3p/\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // GTE_CyberTrust_Root_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgw\n" +
+ "FgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRy\n" +
+ "dXN0IFJvb3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQsw\n" +
+ "CQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQD\n" +
+ "ExNHVEUgQ3liZXJUcnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n" +
+ "iQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8K\n" +
+ "DPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPw\n" +
+ "KfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44AwID\n" +
+ "AQABMA0GCSqGSIb3DQEBBAUAA4GBABKzdcZfHeFhVYAA1IFLezEPI2PnPfMD\n" +
+ "+fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWlIjeaY8JIILTbcuPI9tl8vrGv\n" +
+ "U9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9ApybW1EDp3zdHSo1TRJ6V6e\n" +
+ "6bR64eVaH4QwnNOfpSXY\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // GeoTrust_Global_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYT\n" +
+ "AlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVz\n" +
+ "dCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBC\n" +
+ "MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE\n" +
+ "AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
+ "MIIBCgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEH\n" +
+ "CIjaWC9mOSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlC\n" +
+ "GDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7\n" +
+ "csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAj\n" +
+ "Nvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdRe\n" +
+ "JivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQAB\n" +
+ "o1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9\n" +
+ "qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1luMrMTjANBgkq\n" +
+ "hkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Qzxpe\n" +
+ "R+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWV\n" +
+ "Yrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF\n" +
+ "PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot\n" +
+ "2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeX\n" +
+ "xx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm\n" +
+ "Mw==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // GlobalSign_Root_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzEL\n" +
+ "MAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNV\n" +
+ "BAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05\n" +
+ "ODA5MDExMjAwMDBaFw0xNDAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkw\n" +
+ "FwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRsw\n" +
+ "GQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUA\n" +
+ "A4IBDwAwggEKAoIBAQDaDuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR\n" +
+ "4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc\n" +
+ "71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4\n" +
+ "bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgK\n" +
+ "OOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMW\n" +
+ "ea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DP\n" +
+ "AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIABjAdBgNVHQ4EFgQUYHtmGkUNl8qJ\n" +
+ "UC99BM00qP/8/UswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOC\n" +
+ "AQEArqqf/LfSyx9fOSkoGJ40yWxPbxrwZKJwSk8ThptgKJ7ogUmYfQq75bCd\n" +
+ "PTbbjwVR/wkxKh/diXeeDy5slQTthsu0AD+EAk2AaioteAuubyuig0SDH81Q\n" +
+ "gkwkr733pbTIWg/050deSY43lv6aiAU62cDbKYfmGZZHpzqmjIs8d/5GY6dT\n" +
+ "2iHRrH5Jokvmw2dZL7OKDrssvamqQnw1wdh/1acxOk5jQzmvCLBhNIzTmKlD\n" +
+ "NPYPhyk7ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBg\n" +
+ "Hcl5JLL2bP2oZg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // RSA_Root_Certificate_1.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlD\n" +
+ "ZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu\n" +
+ "Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRp\n" +
+ "b24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNv\n" +
+ "bS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYy\n" +
+ "NjAwMjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\n" +
+ "IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4x\n" +
+ "NTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24g\n" +
+ "QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8x\n" +
+ "IDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3\n" +
+ "DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2f\n" +
+ "NUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChM\n" +
+ "MFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34\n" +
+ "t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs3x/b\n" +
+ "e0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0Wu\n" +
+ "PIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A\n" +
+ "PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // RSA_Security_1024_v3.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICXDCCAcWgAwIBAgIQCgEBAQAAAnwAAAALAAAAAjANBgkqhkiG9w0BAQUF\n" +
+ "ADA6MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0Eg\n" +
+ "U2VjdXJpdHkgMTAyNCBWMzAeFw0wMTAyMjIyMTAxNDlaFw0yNjAyMjIyMDAx\n" +
+ "NDlaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJT\n" +
+ "QSBTZWN1cml0eSAxMDI0IFYzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" +
+ "gQDV3f5mCc8kPD6ugU5OisRpgFtZO9+5TUzKtS3DJy08rwBCbbwoppbPf9dY\n" +
+ "rIMKo1W1exeQFYRMiu4mmdxY78c4pqqv0I5CyGLXq6yp+0p9v+r+Ek3d/yYt\n" +
+ "bzZUaMjShFbuklNhCbM/OZuoyZu9zp9+1BlqFikYvtc6adwlWzMaUQIDAQAB\n" +
+ "o2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSME\n" +
+ "GDAWgBTEwBykB5T9zU0B1FTapQxf3q4FWjAdBgNVHQ4EFgQUxMAcpAeU/c1N\n" +
+ "AdRU2qUMX96uBVowDQYJKoZIhvcNAQEFBQADgYEAPy1q4yZDlX2Jl2X7deRy\n" +
+ "HUZXxGFraZ8SmyzVWujAovBDleMf6XbN3Ou8k6BlCsdNT1+nr6JGFLkM88y9\n" +
+ "am63nd4lQtBU/55oc2PcJOsiv6hy8l4A4Q1OOkNumU4/iXgDmMrzVcydro7B\n" +
+ "qkWY+o8aoI2II/EVQQ2lRj6RP4vr93E=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // RSA_Security_2048_v3.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUF\n" +
+ "ADA6MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0Eg\n" +
+ "U2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5\n" +
+ "MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJT\n" +
+ "QSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" +
+ "CgKCAQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37\n" +
+ "RqtBaB4Y6lXIL5F4iSj7Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E\n" +
+ "0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J\n" +
+ "6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iHKrtjEAMq\n" +
+ "s6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzD\n" +
+ "uvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2Mw\n" +
+ "YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAW\n" +
+ "gBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NRMKSq6UWuNST6\n" +
+ "/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmYv/3V\n" +
+ "EhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5g\n" +
+ "EydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+\n" +
+ "f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJq\n" +
+ "aHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEk\n" +
+ "llgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA\n" +
+ "pKnXwiJPZ9d37CAFYd4=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // TC_TrustCenter__Germany__Class_2_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDXDCCAsWgAwIBAgICA+owDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYT\n" +
+ "AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYD\n" +
+ "VQQKEzFUQyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3\n" +
+ "b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAyIENB\n" +
+ "MSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAe\n" +
+ "Fw05ODAzMDkxMTU5NTlaFw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJE\n" +
+ "RTEQMA4GA1UECBMHSGFtYnVyZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UE\n" +
+ "ChMxVEMgVHJ1c3RDZW50ZXIgZm9yIFNlY3VyaXR5IGluIERhdGEgTmV0d29y\n" +
+ "a3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTEp\n" +
+ "MCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVAdHJ1c3RjZW50ZXIuZGUwgZ8w\n" +
+ "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANo46O0yAClxgwENv4wB3NrGrTmk\n" +
+ "qYov1YtcaF9QxmL1Zr3KkSLsqh1R1z2zUbKDTl3LSbDwTFXlay3HhQswHJJO\n" +
+ "gtTKAu33b77c4OMUuAVT8pr0VotanoWT0bSCVq5Nu6hLVxa8/vhYnvgpjbB7\n" +
+ "zXjJT6yLZwzxnPv8V5tXXE8NAgMBAAGjazBpMA8GA1UdEwEB/wQFMAMBAf8w\n" +
+ "DgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3LnRy\n" +
+ "dXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G\n" +
+ "CSqGSIb3DQEBBAUAA4GBAIRS+yjf/x91AbwBvgRWl2p0QiQxg/lGsQaKic+W\n" +
+ "LDO/jLVfenKhhQbOhvgFjuj5Jcrag4wGrOs2bYWRNAQ29ELw+HkuCkhcq8xR\n" +
+ "T3h2oNmsGb0q0WkEKJHKNhAngFdb0lz1wlurZIFjdFH0l7/NEij3TWZ/p/Ac\n" +
+ "ASZ4smZHcFFk\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // TC_TrustCenter__Germany__Class_3_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDXDCCAsWgAwIBAgICA+swDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYT\n" +
+ "AkRFMRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYD\n" +
+ "VQQKEzFUQyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3\n" +
+ "b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAzIENB\n" +
+ "MSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAe\n" +
+ "Fw05ODAzMDkxMTU5NTlaFw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJE\n" +
+ "RTEQMA4GA1UECBMHSGFtYnVyZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UE\n" +
+ "ChMxVEMgVHJ1c3RDZW50ZXIgZm9yIFNlY3VyaXR5IGluIERhdGEgTmV0d29y\n" +
+ "a3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTEp\n" +
+ "MCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVAdHJ1c3RjZW50ZXIuZGUwgZ8w\n" +
+ "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALa0wTUFLg2N7KBAahwOJ6ZQkmtQ\n" +
+ "GwfeLud2zODa/ISoXoxjaitN2U4CdhHBC/KNecoAtvGwDtf7pBc9r6tpepYn\n" +
+ "v68zoZoqWarEtTcI8hKlMbZD9TKWcSgoq40oht+77uMMfTDWw1Krj10nnGvA\n" +
+ "o+cFa1dJRLNu6mTP0o56UHd3AgMBAAGjazBpMA8GA1UdEwEB/wQFMAMBAf8w\n" +
+ "DgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3LnRy\n" +
+ "dXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G\n" +
+ "CSqGSIb3DQEBBAUAA4GBABY9xs3Bu4VxhUafPiCPUSiZ7C1FIWMjWwS7TJC4\n" +
+ "iJIETb19AaM/9uzO8d7+feXhPrvGq14L3T2WxMup1Pkm5gZOngylerpuw3yC\n" +
+ "GdHHsbHD2w2Om0B8NwvxXej9H5CIpQ5ON2QhqE6NtJ/x3kit1VYYUimLRzQS\n" +
+ "CdS7kjXvD9s0\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Thawte_Personal_Basic_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMC\n" +
+ "WkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3du\n" +
+ "MRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlm\n" +
+ "aWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBl\n" +
+ "cnNvbmFsIEJhc2ljIENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNp\n" +
+ "Y0B0aGF3dGUuY29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVow\n" +
+ "gcsxCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNV\n" +
+ "BAcTCUNhcGUgVG93bjEaMBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAm\n" +
+ "BgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xITAfBgNV\n" +
+ "BAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBDQTEoMCYGCSqGSIb3DQEJARYZ\n" +
+ "cGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOB\n" +
+ "jQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53dXLdjUmbllegeNTK\n" +
+ "P1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdKwPQIcOk8RHtQ\n" +
+ "fmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7G1sY0b8j\n" +
+ "kyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOB\n" +
+ "gQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7\n" +
+ "c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95\n" +
+ "B21P9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Thawte_Personal_Freemail_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMC\n" +
+ "WkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3du\n" +
+ "MRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlm\n" +
+ "aWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBl\n" +
+ "cnNvbmFsIEZyZWVtYWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1m\n" +
+ "cmVlbWFpbEB0aGF3dGUuY29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIz\n" +
+ "NTk1OVowgdExCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUx\n" +
+ "EjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UEChMRVGhhd3RlIENvbnN1bHRp\n" +
+ "bmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24x\n" +
+ "JDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBDQTErMCkGCSqG\n" +
+ "SIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhhd3RlLmNvbTCBnzANBgkq\n" +
+ "hkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfYDFG26nKRsIRefS0N\n" +
+ "j3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5ErHzmj+hND3Ef\n" +
+ "QDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVquzgkCGqY\n" +
+ "x7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq\n" +
+ "hkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP\n" +
+ "MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgC\n" +
+ "neSa/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr\n" +
+ "5PjRzneigQ==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Thawte_Personal_Premium_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMC\n" +
+ "WkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3du\n" +
+ "MRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlm\n" +
+ "aWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBl\n" +
+ "cnNvbmFsIFByZW1pdW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXBy\n" +
+ "ZW1pdW1AdGhhd3RlLmNvbTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5\n" +
+ "NTlaMIHPMQswCQYDVQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIw\n" +
+ "EAYDVQQHEwlDYXBlIFRvd24xGjAYBgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5n\n" +
+ "MSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMSMw\n" +
+ "IQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJlbWl1bSBDQTEqMCgGCSqGSIb3\n" +
+ "DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUuY29tMIGfMA0GCSqGSIb3\n" +
+ "DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0VsBd/eJxZRNkERbGw7\n" +
+ "7f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWIEt12TfIa/G8j\n" +
+ "Hnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYDZicRFTuq\n" +
+ "W/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3\n" +
+ "DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH\n" +
+ "b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVx\n" +
+ "eTBhKXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1\n" +
+ "KzGJ\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Thawte_Premium_Server_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMC\n" +
+ "WkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3du\n" +
+ "MR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2Vy\n" +
+ "dGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3Rl\n" +
+ "IFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNl\n" +
+ "cnZlckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1\n" +
+ "OVowgc4xCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQ\n" +
+ "BgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMUVGhhd3RlIENvbnN1bHRpbmcg\n" +
+ "Y2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24x\n" +
+ "ITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3\n" +
+ "DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0B\n" +
+ "AQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhI\n" +
+ "NTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQug2SBhRz1JPL\n" +
+ "lyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/qgeN\n" +
+ "9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B\n" +
+ "AQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI\n" +
+ "hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZ\n" +
+ "a4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcU\n" +
+ "Qg==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Thawte_Server_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMC\n" +
+ "WkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3du\n" +
+ "MR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2Vy\n" +
+ "dGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3Rl\n" +
+ "IFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0\n" +
+ "ZS5jb20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkG\n" +
+ "A1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2Fw\n" +
+ "ZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UE\n" +
+ "CxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQ\n" +
+ "VGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRz\n" +
+ "QHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I\n" +
+ "/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC\n" +
+ "6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCXL+eQbcAoQpnX\n" +
+ "TEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzARMA8G\n" +
+ "A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWD\n" +
+ "TSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e\n" +
+ "QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdni\n" +
+ "TCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Thawte_Time_Stamping_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMC\n" +
+ "WkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmls\n" +
+ "bGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmlj\n" +
+ "YXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcw\n" +
+ "MTAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTAT\n" +
+ "BgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN\n" +
+ "BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24x\n" +
+ "HzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcN\n" +
+ "AQEBBQADgY0AMIGJAoGBANYrWHhhRYZT6jR7UZztsOYuGA7+4F+oJ9O0yeB8\n" +
+ "WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQaWt9MevPZQx08EHp5JduQ/vBR\n" +
+ "5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL8vg7ij5FrHGSALSQQZj7\n" +
+ "X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN\n" +
+ "AQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC9RAIDb/LogWK\n" +
+ "0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQpgCed/r8\n" +
+ "zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZCayJ\n" +
+ "SdM=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // UTN-USER_First-Network_Applications.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUF\n" +
+ "ADCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0\n" +
+ "IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEw\n" +
+ "HwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVU\n" +
+ "Ti1VU0VSRmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0\n" +
+ "ODM5WhcNMTkwNzA5MTg1NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgT\n" +
+ "AlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVT\n" +
+ "RVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVz\n" +
+ "dC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBBcHBsaWNh\n" +
+ "dGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz+5Gh5DZV\n" +
+ "hawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2N3kDuatpjQclthln5LAb\n" +
+ "GHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCHiZMlIJpDgmkkdihZ\n" +
+ "NaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hAReYFmnjDRy7rh4\n" +
+ "xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1axwiP8vv\n" +
+ "/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6gyN7i\n" +
+ "gEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD\n" +
+ "AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf\n" +
+ "8NPhahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0\n" +
+ "LmNvbS9VVE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0G\n" +
+ "CSqGSIb3DQEBBQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXh\n" +
+ "i6r/fWRRzwr/vH3YIWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUq\n" +
+ "f9FuVSTiuwL7MT++6LzsQCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAf\n" +
+ "hZOVBt5P1CeptqX8Fs1zMT+4ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvP\n" +
+ "NximmMatBrTcCKME1SmklpoSZ0qMYEWd8SOasACcaLWYUNPvji6SZbFIPiG+\n" +
+ "FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUbQErNaLly7HF27FSOH4UMAWr6pjis\n" +
+ "H8SE\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // ValiCert_Class_1_VA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlD\n" +
+ "ZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu\n" +
+ "Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRp\n" +
+ "b24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNv\n" +
+ "bS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYy\n" +
+ "NTIyMjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\n" +
+ "IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4x\n" +
+ "NTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24g\n" +
+ "QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8x\n" +
+ "IDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3\n" +
+ "DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw\n" +
+ "8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m\n" +
+ "+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSN\n" +
+ "dnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwGlN+V\n" +
+ "YH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8so\n" +
+ "gTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw\n" +
+ "nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // ValiCert_Class_2_VA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlD\n" +
+ "ZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu\n" +
+ "Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRp\n" +
+ "b24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNv\n" +
+ "bS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYy\n" +
+ "NjAwMTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\n" +
+ "IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4x\n" +
+ "NTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g\n" +
+ "QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8x\n" +
+ "IDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3\n" +
+ "DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc\n" +
+ "65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQ\n" +
+ "b7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcn\n" +
+ "wbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZSWI4\n" +
+ "OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZ\n" +
+ "oDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC\n" +
+ "W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // ValiCert_OCSP_Responder.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDSDCCArGgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBsjEkMCIGA1UEBxMb\n" +
+ "VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2Vy\n" +
+ "dCwgSW5jLjEsMCoGA1UECxMjQ2xhc3MgMSBWYWxpZGF0aW9uIEF1dGhvcml0\n" +
+ "eSAtIE9DU1AxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQubmV0LzEg\n" +
+ "MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb20wHhcNMDAwMjEyMTE1\n" +
+ "MDA1WhcNMDUwMjEwMTE1MDA1WjCBsjEkMCIGA1UEBxMbVmFsaUNlcnQgVmFs\n" +
+ "aWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwgSW5jLjEsMCoG\n" +
+ "A1UECxMjQ2xhc3MgMSBWYWxpZGF0aW9uIEF1dGhvcml0eSAtIE9DU1AxITAf\n" +
+ "BgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQubmV0LzEgMB4GCSqGSIb3DQEJ\n" +
+ "ARYRaW5mb0B2YWxpY2VydC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ\n" +
+ "AoGBAMeML6fDQIc7PdfEmlgUZArDCDliGs/S66nxaXSKyg5adsyiUk7Q88R6\n" +
+ "tfimHLujp6RTh1uNwAC71WYk53TGFsivyANi1TKHolKRRJSVqEdDbaVInPZM\n" +
+ "ddVPYufJ/3v0JIynvCh2tTKgJXO3Ry94+Eb5hxTwd/wKd+hP/Ywf+mLZAgMB\n" +
+ "AAGjbDBqMA8GCSsGAQUFBzABBQQCBQAwEwYDVR0lBAwwCgYIKwYBBQUHAwkw\n" +
+ "CwYDVR0PBAQDAgGGMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0\n" +
+ "cDovL29jc3AyLnZhbGljZXJ0Lm5ldDANBgkqhkiG9w0BAQUFAAOBgQAVxeC4\n" +
+ "NHISBiCoYpWT0byTupCr3E6Njo2YTOMy9Ss/s5f7qqKtQJetaL1crVMO0Kaz\n" +
+ "DawamY2qMB7PDnD/ArB3ZYPN2gdcUs1Zu6LI4rQWg4/UlXmTLei/RJMxkjDT\n" +
+ "NDTxEPshrC70w11kY3qZ4ZqrQh1IZqZ3N7hVPK3+ZbBi6Q==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_1_Public_Primary_Certification_Authority.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8x\n" +
+ "CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UE\n" +
+ "CxMuQ2xhc3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv\n" +
+ "cml0eTAeFw05NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNV\n" +
+ "BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh\n" +
+ "c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCB\n" +
+ "nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3\n" +
+ "noaACpEO+jglr0aIguVzqKCbJF0NH8xlbgyw0FaEGIeaBpsQoXPftFg5a27B\n" +
+ "9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR4k5FVmkfeAKA2txHkSm7NsljXMXg\n" +
+ "1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATANBgkqhkiG9w0BAQIFAAOBgQBM\n" +
+ "P7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZoEWx8QszznC7EBz8UsA9P\n" +
+ "/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5FvjqBUuUfx3CHMjj\n" +
+ "t/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89FxlA==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_1_Public_Primary_Certification_Authority_-_G2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcEx\n" +
+ "CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UE\n" +
+ "CxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv\n" +
+ "cml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAt\n" +
+ "IEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBU\n" +
+ "cnVzdCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVow\n" +
+ "gcExCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoG\n" +
+ "A1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1\n" +
+ "dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5j\n" +
+ "LiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2ln\n" +
+ "biBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq\n" +
+ "0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYKVdPfQ4chEWWKfo+9\n" +
+ "Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSmFc/IReumXY6c\n" +
+ "PvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQIDAQABMA0G\n" +
+ "CSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0Jh9Zr\n" +
+ "bWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul\n" +
+ "uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4i\n" +
+ "P/68DzFc6PLZ\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_1_Public_Primary_Certification_Authority_-_G3.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHK\n" +
+ "MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV\n" +
+ "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5\n" +
+ "IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBD\n" +
+ "BgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlm\n" +
+ "aWNhdGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3\n" +
+ "MTYyMzU5NTlaMIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24s\n" +
+ "IEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNV\n" +
+ "BAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQg\n" +
+ "dXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFBy\n" +
+ "aW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI\n" +
+ "hvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4nN493GwTFtl63SRR\n" +
+ "ZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO8ESlV8dAWB6j\n" +
+ "Rx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjVojYJrKsh\n" +
+ "JlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjbPG7P\n" +
+ "oBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2\n" +
+ "6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHh\n" +
+ "v2Vrn5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQ\n" +
+ "BfGfMY1aqtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/N\n" +
+ "y9Sn2WCVhDr4wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUf\n" +
+ "xJM8/XmPBNQ+T+r3ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFM\n" +
+ "DSZl4kSAHsef493oCtrspSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5\n" +
+ "SCJ5ShkPshw+IHTZasO+8ih4E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXV\n" +
+ "OBRgmaNL3gaWcSzy27YfpO8/7g==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_1_Public_Primary_OCSP_Responder.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDnjCCAwegAwIBAgIQK2jUo0aexTsoCas4XX8nIDANBgkqhkiG9w0BAQUF\n" +
+ "ADBfMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1\n" +
+ "BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB\n" +
+ "dXRob3JpdHkwHhcNMDAwODA0MDAwMDAwWhcNMDQwODAzMjM1OTU5WjCBpzEX\n" +
+ "MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy\n" +
+ "dXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczov\n" +
+ "L3d3dy52ZXJpc2lnbi5jb20vUlBBIChjKTAwMS4wLAYDVQQDEyVDbGFzcyAx\n" +
+ "IFB1YmxpYyBQcmltYXJ5IE9DU1AgUmVzcG9uZGVyMIGfMA0GCSqGSIb3DQEB\n" +
+ "AQUAA4GNADCBiQKBgQC57V56Ondfzl86UvzNZPdxtW9qlsZZklWUXS9bLsER\n" +
+ "6iaKy6eBPPZaRN56Ey/9WlHZezcmSsAnPwQDalbBgyzhb1upVFAkSsYuekyh\n" +
+ "WzdUJCExH6F4GHansXDaItBq/gdiQMb39pt9DAa4S8co5GYjhFHvRreT2IEz\n" +
+ "y+U2rMboBQIDAQABo4IBEDCCAQwwIAYDVR0RBBkwF6QVMBMxETAPBgNVBAMT\n" +
+ "CE9DU1AgMS0xMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwudmVyaXNp\n" +
+ "Z24uY29tL3BjYTEuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEIGCCsGAQUF\n" +
+ "BwEBBDYwNDAyBggrBgEFBQcwAaYmFiRodHRwOi8vb2NzcC52ZXJpc2lnbi5j\n" +
+ "b20vb2NzcC9zdGF0dXMwRAYDVR0gBD0wOzA5BgtghkgBhvhFAQcBATAqMCgG\n" +
+ "CCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vUlBBMAkGA1Ud\n" +
+ "EwQCMAAwCwYDVR0PBAQDAgeAMA0GCSqGSIb3DQEBBQUAA4GBAHCQ3bjkvlMX\n" +
+ "fH8C6dX3i5mTMWCNfuZgayTvYKzSzpHegG0JpNO4OOVEynJeDS3Bd5y9LAN4\n" +
+ "KY2kpXeH9fErJq3MB2w6VFoo4AnzTQoEytRYaQuns/XdAaXn3PAfusFdkI2z\n" +
+ "6k/BEVmXarIrE7HarZehs7GgIFvKMquNzxPwHynD\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_2_Public_Primary_Certification_Authority.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzEL\n" +
+ "MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQL\n" +
+ "Ey5DbGFzcyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y\n" +
+ "aXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UE\n" +
+ "BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz\n" +
+ "cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGf\n" +
+ "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZM\n" +
+ "JaLtVRKXxaeAufqDwSCg+i8VDXyhYGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvE\n" +
+ "erf4Zh+AVPy3wo5ZShRXRtGak75BkQO7FYCTXOvnzAhsPz6zSvz/S2wj1VCC\n" +
+ "JkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBAIob\n" +
+ "K/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxgJ8pFUs4W7z8GZOeUaHxg\n" +
+ "MxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Ncr6Pc5iaAIzy4RHT3\n" +
+ "Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_2_Public_Primary_Certification_Authority_-_G2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHB\n" +
+ "MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNV\n" +
+ "BAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRo\n" +
+ "b3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4g\n" +
+ "LSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24g\n" +
+ "VHJ1c3QgTmV0d29yazAeFw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTla\n" +
+ "MIHBMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6\n" +
+ "BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB\n" +
+ "dXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIElu\n" +
+ "Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNp\n" +
+ "Z24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" +
+ "p4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjMHiwSViy4AWkszJkf\n" +
+ "rbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjwDqL7MWzJ5m+Z\n" +
+ "Jwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cCAwEAATAN\n" +
+ "BgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9jinb3/\n" +
+ "7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX\n" +
+ "rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6x\n" +
+ "RnInjBJ7xUS0rg==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_2_Public_Primary_Certification_Authority_-_G3.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcox\n" +
+ "CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UE\n" +
+ "CxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkg\n" +
+ "VmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMG\n" +
+ "A1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZp\n" +
+ "Y2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcx\n" +
+ "NjIzNTk1OVowgcoxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwg\n" +
+ "SW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UE\n" +
+ "CxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1\n" +
+ "c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJp\n" +
+ "bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMIIBIjANBgkqhkiG\n" +
+ "9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWUJ92lvuCwTY+zYVY8\n" +
+ "1nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDOJxOeBUebMXoT\n" +
+ "2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUYwZF7C9UT\n" +
+ "AJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9okoqQ\n" +
+ "HgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN\n" +
+ "qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVC\n" +
+ "YQ/ESrg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekh\n" +
+ "ktdmnLfexbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf\n" +
+ "0xwLRtxyID+u7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydE\n" +
+ "p85EXdQbkJgNHkKUsQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377B\n" +
+ "MnMiIYtYgXsVkXq642RIsH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab\n" +
+ "5iXiQkWquJCtvgiPqQtCGJTPcjnhsUPgKM+351psE2tJs//jGHyJizNdrDPX\n" +
+ "p/naOlXJWBD5qu9ats9LS98q\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_2_Public_Primary_OCSP_Responder.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDnjCCAwegAwIBAgIQCUYX5h3Y1BygDKBi6HmKpzANBgkqhkiG9w0BAQUF\n" +
+ "ADBfMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1\n" +
+ "BgNVBAsTLkNsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB\n" +
+ "dXRob3JpdHkwHhcNMDAwODAxMDAwMDAwWhcNMDQwNzMxMjM1OTU5WjCBpzEX\n" +
+ "MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy\n" +
+ "dXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczov\n" +
+ "L3d3dy52ZXJpc2lnbi5jb20vUlBBIChjKTAwMS4wLAYDVQQDEyVDbGFzcyAy\n" +
+ "IFB1YmxpYyBQcmltYXJ5IE9DU1AgUmVzcG9uZGVyMIGfMA0GCSqGSIb3DQEB\n" +
+ "AQUAA4GNADCBiQKBgQDQymMxYX9ENHwFfQs9apDLeUt3Cj9LxyPlwGItfpx+\n" +
+ "PoiHkdCs6E1Jh6KWkIrdBKUCP4yb6Yn+YqDiWr3I3bR45qVCkwhnAcAgTddc\n" +
+ "9F3as+M3plIaLExlTYqH2aij8UlUuzxcgFFoxvtJ/wtVqxXd+5rBuR10DbKM\n" +
+ "RF2J/J/5gwIDAQABo4IBEDCCAQwwIAYDVR0RBBkwF6QVMBMxETAPBgNVBAMT\n" +
+ "CE9DU1AgMS0yMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwudmVyaXNp\n" +
+ "Z24uY29tL3BjYTIuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEIGCCsGAQUF\n" +
+ "BwEBBDYwNDAyBggrBgEFBQcwAaYmFiRodHRwOi8vb2NzcC52ZXJpc2lnbi5j\n" +
+ "b20vb2NzcC9zdGF0dXMwRAYDVR0gBD0wOzA5BgtghkgBhvhFAQcBATAqMCgG\n" +
+ "CCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vUlBBMAkGA1Ud\n" +
+ "EwQCMAAwCwYDVR0PBAQDAgeAMA0GCSqGSIb3DQEBBQUAA4GBAB99CW4kRnUE\n" +
+ "nPMmm+M5bhfvvL2iG9IChIar0ECXLMRDiDcZayKoA3FQnSDcNmAgmnMtc1Vs\n" +
+ "WJsswrQ0LHozQsqR2elDr88e4PXEeqs/cmMeqTfhWzuIsxOGgpBXy1f/9Fa+\n" +
+ "It3jl6jhvCJDwt1N2/aBnpIUnjkPE1TegtjAXjSN\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_3_Public_Primary_Certification_Authority.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzEL\n" +
+ "MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQL\n" +
+ "Ey5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y\n" +
+ "aXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UE\n" +
+ "BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz\n" +
+ "cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGf\n" +
+ "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69q\n" +
+ "RUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3In\n" +
+ "zPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a\n" +
+ "/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtM\n" +
+ "EivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPw\n" +
+ "TtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzk\n" +
+ "uxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_3_Public_Primary_Certification_Authority_-_G2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcEx\n" +
+ "CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UE\n" +
+ "CxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv\n" +
+ "cml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAt\n" +
+ "IEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBU\n" +
+ "cnVzdCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVow\n" +
+ "gcExCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoG\n" +
+ "A1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1\n" +
+ "dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5j\n" +
+ "LiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2ln\n" +
+ "biBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM\n" +
+ "XtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXX\n" +
+ "wc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg013gfqLptQ5GV\n" +
+ "j0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQABMA0G\n" +
+ "CSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01U\n" +
+ "bSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i\n" +
+ "F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo\n" +
+ "1KpYoJ2daZH9\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHK\n" +
+ "MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV\n" +
+ "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5\n" +
+ "IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBD\n" +
+ "BgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlm\n" +
+ "aWNhdGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3\n" +
+ "MTYyMzU5NTlaMIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24s\n" +
+ "IEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNV\n" +
+ "BAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQg\n" +
+ "dXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFBy\n" +
+ "aW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI\n" +
+ "hvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2\n" +
+ "R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2tKmFZpGcmTNDo\n" +
+ "vFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUccLwg\n" +
+ "TS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+V\n" +
+ "k7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ\n" +
+ "Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJ\n" +
+ "OxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my\n" +
+ "/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f\n" +
+ "j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoA\n" +
+ "Wii/gt/4uhMdUIaC/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8S\n" +
+ "GhJouPtmmRQURVyu565pF4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbb\n" +
+ "o27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh\n" +
+ "/sVFuq1ruQp6Tk9LhO5L8X3dEQ==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_3_Public_Primary_OCSP_Responder.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDojCCAwugAwIBAgIQLpaev7ZibOx76XPM42zBhDANBgkqhkiG9w0BAQUF\n" +
+ "ADBfMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1\n" +
+ "BgNVBAsTLkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB\n" +
+ "dXRob3JpdHkwHhcNMDAwODA0MDAwMDAwWhcNMDQwODAzMjM1OTU5WjCBpzEX\n" +
+ "MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy\n" +
+ "dXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczov\n" +
+ "L3d3dy52ZXJpc2lnbi5jb20vUlBBIChjKTAwMS4wLAYDVQQDEyVDbGFzcyAz\n" +
+ "IFB1YmxpYyBQcmltYXJ5IE9DU1AgUmVzcG9uZGVyMIGfMA0GCSqGSIb3DQEB\n" +
+ "AQUAA4GNADCBiQKBgQDx5AgOg7t140jluNum8Lmr6Txix141W9ACVBHYydFW\n" +
+ "uXZLuat65s269gwE1n7WsAplrE454/H3LaMlOe+wi8++2wxdbnD0B81w9zrA\n" +
+ "PjUW7XiMQ8/CJi5H1oZ9nPG+1mcMIiWkymXmH3p4KC8/BdsEIb/hRWb+PLeC\n" +
+ "7Vq4FhW5VQIDAQABo4IBFDCCARAwIAYDVR0RBBkwF6QVMBMxETAPBgNVBAMT\n" +
+ "CE9DU1AgMS0zMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwudmVyaXNp\n" +
+ "Z24uY29tL3BjYTMuMS4xLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCTBCBggr\n" +
+ "BgEFBQcBAQQ2MDQwMgYIKwYBBQUHMAGmJhYkaHR0cDovL29jc3AudmVyaXNp\n" +
+ "Z24uY29tL29jc3Avc3RhdHVzMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQEw\n" +
+ "KjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL1JQQTAJ\n" +
+ "BgNVHRMEAjAAMAsGA1UdDwQEAwIHgDANBgkqhkiG9w0BAQUFAAOBgQAC9lNj\n" +
+ "wKke8tCLMzCPSJtMsFa0g3FKvtxQ2PW24AvbvXhP6c8JNNopSZ0Bc1qRkYJU\n" +
+ "LBMK03cjzzf8Y96n4/a3tWlFKEnDkdyqRxypiJksBSqNjYr6YuJatwAgXTnE\n" +
+ "KMLL/J6oia5bPY4S6jKy/OsU1wkVGsDNG9W1FU5B1ZbjTg==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_4_Public_Primary_Certification_Authority_-_G2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcEx\n" +
+ "CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UE\n" +
+ "CxMzQ2xhc3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv\n" +
+ "cml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAt\n" +
+ "IEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBU\n" +
+ "cnVzdCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVow\n" +
+ "gcExCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoG\n" +
+ "A1UECxMzQ2xhc3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1\n" +
+ "dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5j\n" +
+ "LiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2ln\n" +
+ "biBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6\n" +
+ "8OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDMHO0oW369atyzkSTK\n" +
+ "QWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtKqsGgtG7rL+VX\n" +
+ "xbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwIDAQABMA0G\n" +
+ "CSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwjcSGI\n" +
+ "L4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y\n" +
+ "cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckzt\n" +
+ "ImRPT8qAkbYp\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Class_4_Public_Primary_Certification_Authority_-_G3.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHK\n" +
+ "MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV\n" +
+ "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5\n" +
+ "IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBD\n" +
+ "BgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlm\n" +
+ "aWNhdGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3\n" +
+ "MTYyMzU5NTlaMIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24s\n" +
+ "IEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNV\n" +
+ "BAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQg\n" +
+ "dXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFBy\n" +
+ "aW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI\n" +
+ "hvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYl\n" +
+ "S+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ+mGuqPKljYXC\n" +
+ "KtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM8BDc\n" +
+ "VHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdL\n" +
+ "MEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY\n" +
+ "ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDD\n" +
+ "Zq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1Wr\n" +
+ "IhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt\n" +
+ "mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csK\n" +
+ "vE+MW8VLADsfKoKmfjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluP\n" +
+ "QSjA1egtTaRezarZ7c7c2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kP\n" +
+ "mF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr\n" +
+ "9Xgn2uf3ZkPznoM+IKrDNWCRzg==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_RSA_Secure_Server_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzEL\n" +
+ "MAkGA1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMu\n" +
+ "MS4wLAYDVQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9y\n" +
+ "aXR5MB4XDTk0MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UE\n" +
+ "BhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD\n" +
+ "VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGb\n" +
+ "MA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6O\n" +
+ "LDfO6zV4ZFQD5YRAUcm/jwjiioII0haGN1XpsSECrXZogZoFokvJSyVmIlZs\n" +
+ "iAeP94FZbYQHZXATcXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJVCxzOmmC\n" +
+ "sZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZIhvcNAQECBQADfgBl3X7hsuyw\n" +
+ "4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3YQO2WxZpO8ZECAyIUwxr\n" +
+ "l0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc1/p3yjkWWW8O6tO1\n" +
+ "g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Secure_Server_OCSP_Responder.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDnzCCAwygAwIBAgIRAP9F1SddJPuzwjkkU1fhT94wDQYJKoZIhvcNAQEF\n" +
+ "BQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5\n" +
+ "LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24g\n" +
+ "QXV0aG9yaXR5MB4XDTAwMDgwNDAwMDAwMFoXDTA0MDgwMzIzNTk1OVowgZ4x\n" +
+ "FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU\n" +
+ "cnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQgaHR0cHM6\n" +
+ "Ly93d3cudmVyaXNpZ24uY29tL1JQQSAoYykwMDElMCMGA1UEAxMcU2VjdXJl\n" +
+ "IFNlcnZlciBPQ1NQIFJlc3BvbmRlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw\n" +
+ "gYkCgYEAuFGZZIUO7rMKaPC/Y3YdU/X8oXiMM+6f9L452psPTUepjyDoS0S9\n" +
+ "zs17kNEw6JDEJXuJKN699pMd/7n/krWpjeSuzOLDB4Nqo3IQASdiIqY1Jjkt\n" +
+ "ns9gDPxHpNfQQninHWzQy08VpykKtJVFxLHnWgnXOZXYHTWewr2zXcEMSx8C\n" +
+ "AwEAAaOCAR0wggEZMCAGA1UdEQQZMBekFTATMREwDwYDVQQDEwhPQ1NQIDEt\n" +
+ "NDA+BgNVHR8ENzA1MDOgMaAvhi1odHRwOi8vY3JsLnZlcmlzaWduLmNvbS9S\n" +
+ "U0FTZWN1cmVTZXJ2ZXItcC5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwkwQgYI\n" +
+ "KwYBBQUHAQEENjA0MDIGCCsGAQUFBzABpiYWJGh0dHA6Ly9vY3NwLnZlcmlz\n" +
+ "aWduLmNvbS9vY3NwL3N0YXR1czBEBgNVHSAEPTA7MDkGC2CGSAGG+EUBBwEB\n" +
+ "MCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9SUEEw\n" +
+ "CQYDVR0TBAIwADALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEFBQADfgAAsxBT\n" +
+ "ZpxJky4xoAJC0lhXfmah/huKYRhQQCweK0Gl1tv/rAgcWgVtAlwqtpZPR9u+\n" +
+ "TtvOzLqGuBjOsRKRX2P380g+zPFNE+RtCZR4AJLLoyCdBgtqoEMHztEZbI8Y\n" +
+ "dZqfFzP9qSa44+LewqjEWop/mNYHBmvMVp6GcM7U7w==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Verisign_Time_Stamping_Authority_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDzTCCAzagAwIBAgIQU2GyYK7bcY6nlLMTM/QHCTANBgkqhkiG9w0BAQUF\n" +
+ "ADCBwTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTww\n" +
+ "OgYDVQQLEzNDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24g\n" +
+ "QXV0aG9yaXR5IC0gRzIxOjA4BgNVBAsTMShjKSAxOTk4IFZlcmlTaWduLCBJ\n" +
+ "bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAsTFlZlcmlT\n" +
+ "aWduIFRydXN0IE5ldHdvcmswHhcNMDAwOTI2MDAwMDAwWhcNMTAwOTI1MjM1\n" +
+ "OTU5WjCBpTEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl\n" +
+ "cmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBh\n" +
+ "dCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTAwMSwwKgYDVQQD\n" +
+ "EyNWZXJpU2lnbiBUaW1lIFN0YW1waW5nIEF1dGhvcml0eSBDQTCBnzANBgkq\n" +
+ "hkiG9w0BAQEFAAOBjQAwgYkCgYEA0hmdZ8IAIVlizrQJIkRpivglWtvtDbc2\n" +
+ "fk7gu5Q+kCWHwmFHKdm9VLhjzCx9abQzNvQ3B5rB3UBU/OB4naCTuQk9I1F/\n" +
+ "RMIUdNsKvsvJMDRAmD7Q1yUQgZS9B0+c1lQn3y6ov8uQjI11S7zi6ESHzeZB\n" +
+ "CiVu6PQkAsVSD27smHUCAwEAAaOB3zCB3DAPBgNVHRMECDAGAQH/AgEAMEUG\n" +
+ "A1UdIAQ+MDwwOgYMYIZIAYb4RQEHFwEDMCowKAYIKwYBBQUHAgEWHGh0dHBz\n" +
+ "Oi8vd3d3LnZlcmlzaWduLmNvbS9ycGEwMQYDVR0fBCowKDAmoCSgIoYgaHR0\n" +
+ "cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwCwYDVR0PBAQDAgEGMEIG\n" +
+ "CCsGAQUFBwEBBDYwNDAyBggrBgEFBQcwAaYmFiRodHRwOi8vb2NzcC52ZXJp\n" +
+ "c2lnbi5jb20vb2NzcC9zdGF0dXMwDQYJKoZIhvcNAQEFBQADgYEAgnBold+2\n" +
+ "DcIBcBlK0lRWHqzyRUyHuPU163hLBanInTsZIS5wNEqi9YngFXVF5yg3ADQn\n" +
+ "Keg3S/LvRJdrF1Eaw1adPBqK9kpGRjeM+sv1ZFo4aC4cw+9wzrhGBha/937n\n" +
+ "tag+RaypJXUie28/sJyU58dzq6wf7iWbwBbtt8pb8BQ=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Visa_International_Global_Root_2.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDgDCCAmigAwIBAgICAx4wDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMC\n" +
+ "VVMxDTALBgNVBAoTBFZJU0ExLzAtBgNVBAsTJlZpc2EgSW50ZXJuYXRpb25h\n" +
+ "bCBTZXJ2aWNlIEFzc29jaWF0aW9uMRIwEAYDVQQDEwlHUCBSb290IDIwHhcN\n" +
+ "MDAwODE2MjI1MTAwWhcNMjAwODE1MjM1OTAwWjBhMQswCQYDVQQGEwJVUzEN\n" +
+ "MAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNl\n" +
+ "cnZpY2UgQXNzb2NpYXRpb24xEjAQBgNVBAMTCUdQIFJvb3QgMjCCASIwDQYJ\n" +
+ "KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkBcLWqxEDwq2omYXkZAPy/mzdZ\n" +
+ "DK9vZBv42pWUJGkzEXDK41Z0ohdXZFwgBuHW73G3O/erwWnQSaSxBNf0V2KJ\n" +
+ "XLB1LRckaeNCYOTudNargFbYiCjh+20i/SN8RnNPflRzHqgsVVh1t0zzWkWl\n" +
+ "Ahr62p3DRcMiXvOL8WAp0sdftAw6UYPvMPjU58fy+pmjIlC++QU3o63tmsPm\n" +
+ "7IgbthknGziLgE3sucfFicv8GjLtI/C1AVj59o/ghalMCXI5Etuz9c9OYmTa\n" +
+ "xhkVOmMd6RdVoUwiPDQyRvhlV7or7zaMavrZ2UT0qt2E1w0cslSsMoW0ZA3e\n" +
+ "QbuxNMYBhjJk1Z8CAwEAAaNCMEAwHQYDVR0OBBYEFJ59SzS/ca3CBfYDdYDO\n" +
+ "qU8axCRMMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqG\n" +
+ "SIb3DQEBBQUAA4IBAQAhpXYUVfmtJ3CPPPTVbMjMCqujmAuKBiPFyWHbmQdp\n" +
+ "NSYx/scuhMKZYdQN6X0uEyt8joW2hcdLzzW2LEc9zikv2G+fiRxkk78IvXbQ\n" +
+ "kIqUs38oW26sTTMs7WXcFsziza6kPWKSBpUmv9+55CCmc2rBvveURNZNbyoL\n" +
+ "axhNdBA2aGpawWqn3TYpjLgwi08hPwAuVDAHOrqK5MOeyti12HvOdUVmB/Rt\n" +
+ "Ldh6yumJivIj2C/LbgA2T/vwLwHMD8AiZfSr4k5hLQOCfZEWtTDVFN5ex5D8\n" +
+ "ofyrEK9ca3CnB+8phuiyJccg/ybdd+95RBTEvd07xQObdyPsoOy7Wjm1zK0G\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // Visa_eCommerce_Root.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUF\n" +
+ "ADBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlz\n" +
+ "YSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMT\n" +
+ "E1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0\n" +
+ "MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UE\n" +
+ "CxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAa\n" +
+ "BgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA\n" +
+ "A4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh\n" +
+ "28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8bRaVK7362\n" +
+ "rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81\n" +
+ "q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtF\n" +
+ "Wsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0\n" +
+ "lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaLdXe6YJ2E5/4t\n" +
+ "AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G\n" +
+ "A1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOC\n" +
+ "AQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR\n" +
+ "zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKht\n" +
+ "cbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGI\n" +
+ "xHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu\n" +
+ "YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/\n" +
+ "hC3euiInlhBx6yLt398znM/jra6O1I7mT1GvFpLgXPYHDw==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // beTRUSTed_Root_CA-Baltimore_Implementation.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFajCCBFKgAwIBAgIEPLU9RjANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQK\n" +
+ "EwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEG\n" +
+ "A1UEAxMqYmVUUlVTVGVkIFJvb3QgQ0EtQmFsdGltb3JlIEltcGxlbWVudGF0\n" +
+ "aW9uMB4XDTAyMDQxMTA3Mzg1MVoXDTIyMDQxMTA3Mzg1MVowZjESMBAGA1UE\n" +
+ "ChMJYmVUUlVTVGVkMRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAx\n" +
+ "BgNVBAMTKmJlVFJVU1RlZCBSb290IENBLUJhbHRpbW9yZSBJbXBsZW1lbnRh\n" +
+ "dGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALx+xDmcjOPW\n" +
+ "HIb/ymKt4H8wRXqOGrO4x/nRNv8i805qX4QQ+2aBw5R5MdKR4XeOGCrDFN5R\n" +
+ "9U+jK7wYFuK13XneIviCfsuBH/0nLI/6l2Qijvj/YaOcGx6Sj8CoCd8JEey3\n" +
+ "fTGaGuqDIQY8n7pc/5TqarjDa1U0Tz0yH92BFODEPM2dMPgwqZfT7syj0B9f\n" +
+ "HBOB1BirlNFjw55/NZKeX0Tq7PQiXLfoPX2k+YmpkbIq2eszh+6l/ePazIjm\n" +
+ "iSZuxyuC0F6dWdsU7JGDBcNeDsYq0ATdcT0gTlgn/FP7eHgZFLL8kFKJOGJg\n" +
+ "B7Sg7KxrUNb9uShr71ItOrL/8QFArDcCAwEAAaOCAh4wggIaMA8GA1UdEwEB\n" +
+ "/wQFMAMBAf8wggG1BgNVHSAEggGsMIIBqDCCAaQGDysGAQQBsT4AAAEJKIOR\n" +
+ "MTCCAY8wggFIBggrBgEFBQcCAjCCAToaggE2UmVsaWFuY2Ugb24gb3IgdXNl\n" +
+ "IG9mIHRoaXMgQ2VydGlmaWNhdGUgY3JlYXRlcyBhbiBhY2tub3dsZWRnbWVu\n" +
+ "dCBhbmQgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5k\n" +
+ "YXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgdGhlIENlcnRpZmlj\n" +
+ "YXRpb24gUHJhY3RpY2UgU3RhdGVtZW50IGFuZCB0aGUgUmVseWluZyBQYXJ0\n" +
+ "eSBBZ3JlZW1lbnQsIHdoaWNoIGNhbiBiZSBmb3VuZCBhdCB0aGUgYmVUUlVT\n" +
+ "VGVkIHdlYiBzaXRlLCBodHRwOi8vd3d3LmJldHJ1c3RlZC5jb20vcHJvZHVj\n" +
+ "dHNfc2VydmljZXMvaW5kZXguaHRtbDBBBggrBgEFBQcCARY1aHR0cDovL3d3\n" +
+ "dy5iZXRydXN0ZWQuY29tL3Byb2R1Y3RzX3NlcnZpY2VzL2luZGV4Lmh0bWww\n" +
+ "HQYDVR0OBBYEFEU9w6nR3D8kVpgccxiIav+DR+22MB8GA1UdIwQYMBaAFEU9\n" +
+ "w6nR3D8kVpgccxiIav+DR+22MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0B\n" +
+ "AQUFAAOCAQEASZK8o+6svfoNyYt5hhwjdrCAWXf82n+0S9/DZEtqTg6t8n1Z\n" +
+ "dwWtColzsPq8y9yNAIiPpqCy6qxSJ7+hSHyXEHu67RMdmgduyzFiEuhjA6p9\n" +
+ "beP4G3YheBufS0OM00mG9htc9i5gFdPp43t1P9ACg9AYgkHNZTfqjjJ+vWuZ\n" +
+ "XTARyNtIVBw74acT02pIk/c9jH8F6M7ziCpjBLjqflh8AXtb4cV97yHgjQ5d\n" +
+ "UX2xZ/2jvTg2xvI4hocalmhgRvsoFEdV4aeADGvi6t9NfJBIoDa9CReJf8Py\n" +
+ "05yc493EG931t3GzUwWJBtDLSoDByFOQtTwxiBdQn8nEDovYqAJjDQ==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // beTRUSTed_Root_CA.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFLDCCBBSgAwIBAgIEOU99hzANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQG\n" +
+ "EwJXVzESMBAGA1UEChMJYmVUUlVTVGVkMRswGQYDVQQDExJiZVRSVVNUZWQg\n" +
+ "Um9vdCBDQXMxGjAYBgNVBAMTEWJlVFJVU1RlZCBSb290IENBMB4XDTAwMDYy\n" +
+ "MDE0MjEwNFoXDTEwMDYyMDEzMjEwNFowWjELMAkGA1UEBhMCV1cxEjAQBgNV\n" +
+ "BAoTCWJlVFJVU1RlZDEbMBkGA1UEAxMSYmVUUlVTVGVkIFJvb3QgQ0FzMRow\n" +
+ "GAYDVQQDExFiZVRSVVNUZWQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD\n" +
+ "ggEPADCCAQoCggEBANS0c3oTCjhVAb6JVuGUntS+WutKNHUbYSnE4a0IYCF4\n" +
+ "SP+00PpeQY1hRIfo7clY+vyTmt9P6j41ffgzeubx181vSUs9Ty1uDoM6GHh3\n" +
+ "o8/n9E1z2Jo7Gh2+lVPPIJfCzz4kUmwMjmVZxXH/YgmPqsWPzGCgc0rXOD8V\n" +
+ "cr+il7dw6K/ifhYGTPWqZCZyByWtNfwYsSbX2P8ZDoMbjNx4RWc0PfSvHI3k\n" +
+ "bWvtILNnmrRhyxdviTX/507AMhLn7uzf/5cwdO2NR47rtMNE5qdMf1ZD6Li8\n" +
+ "tr76g5fmu/vEtpO+GRg+jIG5c4gW9JZDnGdzF5DYCW5jrEq2I8QBoa2k5MUC\n" +
+ "AwEAAaOCAfgwggH0MA8GA1UdEwEB/wQFMAMBAf8wggFZBgNVHSAEggFQMIIB\n" +
+ "TDCCAUgGCisGAQQBsT4BAAAwggE4MIIBAQYIKwYBBQUHAgIwgfQagfFSZWxp\n" +
+ "YW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVz\n" +
+ "IGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0\n" +
+ "ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGFuZCBjZXJ0aWZpY2F0aW9u\n" +
+ "IHByYWN0aWNlIHN0YXRlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IGJl\n" +
+ "VFJVU1RlZCdzIHdlYiBzaXRlLCBodHRwczovL3d3dy5iZVRSVVNUZWQuY29t\n" +
+ "L3ZhdWx0L3Rlcm1zMDEGCCsGAQUFBwIBFiVodHRwczovL3d3dy5iZVRSVVNU\n" +
+ "ZWQuY29tL3ZhdWx0L3Rlcm1zMDQGA1UdHwQtMCswKaAnoCWkIzAhMRIwEAYD\n" +
+ "VQQKEwliZVRSVVNUZWQxCzAJBgNVBAYTAldXMB0GA1UdDgQWBBQquZtpLjub\n" +
+ "2M3eKjEENGvKBxirZzAfBgNVHSMEGDAWgBQquZtpLjub2M3eKjEENGvKBxir\n" +
+ "ZzAOBgNVHQ8BAf8EBAMCAf4wDQYJKoZIhvcNAQEFBQADggEBAHlh26Nebhax\n" +
+ "6nZR+csVm8tpvuaBa58oH2U+3RGFktToQb9+M70j5/Egv6S0phkBxoyNNXxl\n" +
+ "pE8JpNbYIxUFE6dDea/bow6be3ga8wSGWsb2jCBHOElQBp1yZzrwmAOtlmdE\n" +
+ "/D8QDYZN5AA7KXvOOzuZhmElQITcE2K3+spZ1gMe1lMBzW1MaFVA4e5rxyoA\n" +
+ "AEiCswoBw2AqDPeCNe5IhpbkdNQ96gFxugR1QKepfzk5mlWXKWWuGVUlBXJH\n" +
+ "0+gY3Ljpr0NzARJ0o+FcXxVdJPP55PS2Z2cS52QiivalQaYctmBjRYoQtLpG\n" +
+ "EK5BV2VsPyMQPyEQWbfkQN0mDCP2qq4=\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // beTRUSTed_Root_CA_-_Entrust_Implementation.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGUTCCBTmgAwIBAgIEPLVPQDANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQK\n" +
+ "EwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEG\n" +
+ "A1UEAxMqYmVUUlVTVGVkIFJvb3QgQ0EgLSBFbnRydXN0IEltcGxlbWVudGF0\n" +
+ "aW9uMB4XDTAyMDQxMTA4MjQyN1oXDTIyMDQxMTA4NTQyN1owZjESMBAGA1UE\n" +
+ "ChMJYmVUUlVTVGVkMRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAx\n" +
+ "BgNVBAMTKmJlVFJVU1RlZCBSb290IENBIC0gRW50cnVzdCBJbXBsZW1lbnRh\n" +
+ "dGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALr0RAOqEmq1\n" +
+ "Q+xVkrYwfTVXDNvzDSduTPdQqJtOK2/b9a0cS12zqcH+e0TrW6MFDR/FNCsw\n" +
+ "ACnxeECypP869AGIF37m1CbTukzqMvtDd5eHI8XbQ6P1KqNRXuE70mVpflUV\n" +
+ "m3rnafdE4Fe1FehmYA8NA/uCjqPoEXtsvsdjDheT389Lrm5zdeDzqrmkwAkb\n" +
+ "hepxKYhBMvnwKg5sCfJ0a2ZsUhMfGLzUPvfYbiCeyv78IZTuEyhL11xeDGbu\n" +
+ "6bsPwTSxfwh28z0mcMmLJR1iJAzqHHVOwBLkuhMdMCktVjMFu5dZfsZJT4nX\n" +
+ "LySotohAtWSSU1Yk5KKghbNekLQSM80CAwEAAaOCAwUwggMBMIIBtwYDVR0g\n" +
+ "BIIBrjCCAaowggGmBg8rBgEEAbE+AAACCSiDkTEwggGRMIIBSQYIKwYBBQUH\n" +
+ "AgIwggE7GoIBN1JlbGlhbmNlIG9uIG9yIHVzZSBvZiB0aGlzIENlcnRpZmlj\n" +
+ "YXRlIGNyZWF0ZXMgYW4gYWNrbm93bGVkZ21lbnQgYW5kIGFjY2VwdGFuY2Ug\n" +
+ "b2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29u\n" +
+ "ZGl0aW9ucyBvZiB1c2UsIHRoZSBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0\n" +
+ "YXRlbWVudCBhbmQgdGhlIFJlbHlpbmcgUGFydHkgQWdyZWVtZW50LCB3aGlj\n" +
+ "aCBjYW4gYmUgZm91bmQgYXQgdGhlIGJlVFJVU1RlZCB3ZWIgc2l0ZSwgaHR0\n" +
+ "cHM6Ly93d3cuYmV0cnVzdGVkLmNvbS9wcm9kdWN0c19zZXJ2aWNlcy9pbmRl\n" +
+ "eC5odG1sMEIGCCsGAQUFBwIBFjZodHRwczovL3d3dy5iZXRydXN0ZWQuY29t\n" +
+ "L3Byb2R1Y3RzX3NlcnZpY2VzL2luZGV4Lmh0bWwwEQYJYIZIAYb4QgEBBAQD\n" +
+ "AgAHMIGJBgNVHR8EgYEwfzB9oHugeaR3MHUxEjAQBgNVBAoTCWJlVFJVU1Rl\n" +
+ "ZDEbMBkGA1UECxMSYmVUUlVTVGVkIFJvb3QgQ0FzMTMwMQYDVQQDEypiZVRS\n" +
+ "VVNUZWQgUm9vdCBDQSAtIEVudHJ1c3QgSW1wbGVtZW50YXRpb24xDTALBgNV\n" +
+ "BAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMjA0MTEwODI0MjdagQ8yMDIyMDQx\n" +
+ "MTA4NTQyN1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFH1w5a44iwY/qhwa\n" +
+ "j/nPJDCqhIQWMB0GA1UdDgQWBBR9cOWuOIsGP6ocGo/5zyQwqoSEFjAMBgNV\n" +
+ "HRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkq\n" +
+ "hkiG9w0BAQUFAAOCAQEAKrgXzh8QlOu4mre5X+za95IkrNySO8cgjfKZ5V04\n" +
+ "ocI07cUTWVwFtStPYZuR+0H8/NU8TZh2BvWBfevdkObRVlTa4y0MnxEylCIB\n" +
+ "evZsLHRnBMylj44ss0O1lKLQfelifwa+JwGDnjr9iu6YQ0pr17WXOzq/T220\n" +
+ "Y/ozADQuLW2WyXvKmWO6vvT2MKAtmJbpVkQFqUSjYRDrgqFnXbxdJ3Wqiig2\n" +
+ "KjiS2d2kXgClzMx8KSreKJCrt+G2/30lC0DYqjSjLd4H61/OCt3Kfjp9JsFi\n" +
+ "aDrmLzfzgYYhxKlkqu9FNtEaZnz46TfW1mG+oq1I59/mdP7TbX3SJdysYlep\n" +
+ "9w==\n" +
+ "-----END CERTIFICATE-----\n");
+ if (cert != null) certs.add(cert);
+
+ cert = generate(factory,
+ // beTRUSTed_Root_CA_-_RSA_Implementation.crt
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFaDCCBFCgAwIBAgIQO1nHe81bV569N1KsdrSqGjANBgkqhkiG9w0BAQUF\n" +
+ "ADBiMRIwEAYDVQQKEwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBS\n" +
+ "b290IENBczEvMC0GA1UEAxMmYmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1w\n" +
+ "bGVtZW50YXRpb24wHhcNMDIwNDExMTExODEzWhcNMjIwNDEyMTEwNzI1WjBi\n" +
+ "MRIwEAYDVQQKEwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290\n" +
+ "IENBczEvMC0GA1UEAxMmYmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVt\n" +
+ "ZW50YXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkujQw\n" +
+ "CY5X0LkGLG9uJIAiv11DpvpPrILnHGhwhRujbrWqeNluB0s/6d/16uhUoWGK\n" +
+ "Di9pdRi3DOUUjXFumLhV/AyV0Jtu4S2I1DpAa5LxmZZk3tv/ePTulh1HiXzU\n" +
+ "vrmIdyM6CeYEnm2qXtLIvZpOGd+J6lsOfsPktPDgaTuID0GQ+NRxQyTBjyZL\n" +
+ "O1bp/4xsN+lFrYWMU8NghpBKlsmzVLC7F/AcRdnUGxlkVgoZ98zh/4avflhe\n" +
+ "rHqQH8koOUV7orbHnB/ahdQhhlkwk75TMzf270HPM8ercmsl9fNTGwxMLvF1\n" +
+ "S++gh/f+ihXQbNXL+WhTuXAVE8L1LvtDNXUtAgMBAAGjggIYMIICFDAMBgNV\n" +
+ "HRMEBTADAQH/MIIBtQYDVR0gBIIBrDCCAagwggGkBg8rBgEEAbE+AAADCSiD\n" +
+ "kTEwggGPMEEGCCsGAQUFBwIBFjVodHRwOi8vd3d3LmJldHJ1c3RlZC5jb20v\n" +
+ "cHJvZHVjdHNfc2VydmljZXMvaW5kZXguaHRtbDCCAUgGCCsGAQUFBwICMIIB\n" +
+ "OhqCATZSZWxpYW5jZSBvbiBvciB1c2Ugb2YgdGhpcyBDZXJ0aWZpY2F0ZSBj\n" +
+ "cmVhdGVzIGFuIGFja25vd2xlZGdtZW50IGFuZCBhY2NlcHRhbmNlIG9mIHRo\n" +
+ "ZSB0aGVuIGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlv\n" +
+ "bnMgb2YgdXNlLCB0aGUgQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1l\n" +
+ "bnQgYW5kIHRoZSBSZWx5aW5nIFBhcnR5IEFncmVlbWVudCwgd2hpY2ggY2Fu\n" +
+ "IGJlIGZvdW5kIGF0IHRoZSBiZVRSVVNUZWQgd2ViIHNpdGUsIGh0dHA6Ly93\n" +
+ "d3cuYmV0cnVzdGVkLmNvbS9wcm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1s\n" +
+ "MAsGA1UdDwQEAwIBBjAfBgNVHSMEGDAWgBSp7BR++dlDzFMrFK3P9/BZiUHN\n" +
+ "GTAdBgNVHQ4EFgQUqewUfvnZQ8xTKxStz/fwWYlBzRkwDQYJKoZIhvcNAQEF\n" +
+ "BQADggEBANuXsHXqDMTBmMpWBcCorSZIry0g6IHHtt9DwSwddUvUQo3neqh0\n" +
+ "3GZCWYez9Wlt2ames30cMcH1VOJZJEnl7r05pmuKmET7m9cqg5c0Lcd9NUwt\n" +
+ "NLg+DcTsiCevnpL9UGGCqGAHFFPMZRPB9kdEadIxyKbdLrML3kqNWz2rDcI1\n" +
+ "UqJWN8wyiyiFQpyRQHpwKzg21eFzGh/l+n5f3NacOzDq28BbJ1zTcwfBwvNM\n" +
+ "m2+fG8oeqqg4MwlYsq78B+g23FW6L09A/nq9BqaBwZMifIYRCgZ3SK41ty8y\n" +
+ "mmFei74pnykkiFY5LKjSq5YDWtRIn7lAhAuYaPsBQ9Yb4gmxlxw=\n" +
+ "-----END CERTIFICATE-----\n");
+
+ CA_CERTS = new StaticTrustAnchors((X509Certificate[]) certs.toArray(new X509Certificate[0]));
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Alert.java b/gnu/javax/net/ssl/provider/Alert.java
new file mode 100644
index 000000000..c31e1bef5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Alert.java
@@ -0,0 +1,474 @@
+/* Alert.java -- SSL Alert message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An alert message in the SSL protocol. Alerts are sent both as warnings
+ * which may allow execution to continue, or they may be fatal, which will
+ * halt this session. An alert object is composed of two enums -- the level,
+ * which indicates the seriousness of the alert, and the description, which
+ * indicates the reason for the alert.
+ *
+ * <pre>
+ * struct {
+ * AlertLevel level;
+ * AlertDescription description;
+ * }
+ * </pre>
+ */
+final class Alert implements Constructed
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ /** The alert level enumerated. */
+ private final Level level;
+
+ /** The alert description enumerated. */
+ private final Description description;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ Alert(Level level, Description description)
+ {
+ this.level = level;
+ this.description = description;
+ }
+
+ // Class method.
+ // -------------------------------------------------------------------------
+
+ static Alert read(InputStream in) throws IOException
+ {
+ Level level = Level.read(in);
+ Description desc = Description.read(in);
+ return new Alert(level, desc);
+ }
+
+ static Alert forName(String name)
+ {
+ if (name == null)
+ {
+ return new Alert(Level.FATAL, Description.INTERNAL_ERROR);
+ }
+ Description desc = Description.INTERNAL_ERROR;
+ if (name.equals("close_notify"))
+ {
+ desc = Description.CLOSE_NOTIFY;
+ }
+ else if (name.equals("unexpected_message"))
+ {
+ desc = Description.UNEXPECTED_MESSAGE;
+ }
+ else if (name.equals("bad_record_mac"))
+ {
+ desc = Description.BAD_RECORD_MAC;
+ }
+ else if (name.equals("DECRYPTION_FAILED"))
+ {
+ desc = Description.DECRYPTION_FAILED;
+ }
+ else if (name.equals("record_overflow"))
+ {
+ desc = Description.RECORD_OVERFLOW;
+ }
+ else if (name.equals("decompression_failure"))
+ {
+ desc = Description.DECOMPRESSION_FAILURE;
+ }
+ else if (name.equals("handshake_failure"))
+ {
+ desc = Description.HANDSHAKE_FAILURE;
+ }
+ else if (name.equals("no_certificate"))
+ {
+ desc = Description.NO_CERTIFICATE;
+ }
+ else if (name.equals("bad_certificate"))
+ {
+ desc = Description.BAD_CERTIFICATE;
+ }
+ else if (name.equals("unsupported_certificate"))
+ {
+ desc = Description.UNSUPPORTED_CERTIFICATE;
+ }
+ else if (name.equals("certificate_revoked"))
+ {
+ desc = Description.CERTIFICATE_REVOKED;
+ }
+ else if (name.equals("certificate_expired"))
+ {
+ desc = Description.CERTIFICATE_EXPIRED;
+ }
+ else if (name.equals("certificate_unknown"))
+ {
+ desc = Description.CERTIFICATE_UNKNOWN;
+ }
+ else if (name.equals("illegal_parameter"))
+ {
+ desc = Description.ILLEGAL_PARAMETER;
+ }
+ else if (name.equals("unknown_ca"))
+ {
+ desc = Description.UNKNOWN_CA;
+ }
+ else if (name.equals("access_denied"))
+ {
+ desc = Description.ACCESS_DENIED;
+ }
+ else if (name.equals("decode_error"))
+ {
+ desc = Description.DECODE_ERROR;
+ }
+ else if (name.equals("decrypt_error"))
+ {
+ desc = Description.DECRYPT_ERROR;
+ }
+ else if (name.equals("export_restriction"))
+ {
+ desc = Description.EXPORT_RESTRICTION;
+ }
+ else if (name.equals("protocol_version"))
+ {
+ desc = Description.PROTOCOL_VERSION;
+ }
+ else if (name.equals("insufficient_security"))
+ {
+ desc = Description.INSUFFICIENT_SECURITY;
+ }
+ else if (name.equals("internal_error"))
+ {
+ desc = Description.INTERNAL_ERROR;
+ }
+ else if (name.equals("user_canceled"))
+ {
+ desc = Description.USER_CANCELED;
+ }
+ else if (name.equals("no_renegotiation"))
+ {
+ desc = Description.NO_RENEGOTIATION;
+ }
+ else if (name.equals("unsupported_extension"))
+ {
+ desc = Description.UNSUPPORTED_EXTENSION;
+ }
+ else if (name.equals("certificate_unobtainable"))
+ {
+ desc = Description.CERTIFICATE_UNOBTAINABLE;
+ }
+ else if (name.equals("unrecognized_name"))
+ {
+ desc = Description.UNRECOGNIZED_NAME;
+ }
+ else if (name.equals("bad_certificate_status_response"))
+ {
+ desc = Description.BAD_CERTIFICATE_STATUS_RESPONSE;
+ }
+ else if (name.equals("bad_certificate_hash_value"))
+ {
+ desc = Description.BAD_CERTIFICATE_HASH_VALUE;
+ }
+ else if (name.equals("unknown_srp_username"))
+ {
+ desc = Description.UNKNOWN_SRP_USERNAME;
+ }
+ else if (name.equals("missing_srp_username"))
+ {
+ desc = Description.MISSING_SRP_USERNAME;
+ }
+ return new Alert(Level.FATAL, desc);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ out.write((byte) level.getValue());
+ out.write((byte) description.getValue());
+ }
+
+ byte[] getEncoded()
+ {
+ return new byte[] { (byte) level.getValue(),
+ (byte) description.getValue() };
+ }
+
+ Level getLevel()
+ {
+ return level;
+ }
+
+ Description getDescription()
+ {
+ return description;
+ }
+
+ public String toString()
+ {
+ String nl = System.getProperty("line.separator");
+ return "struct {" + nl +
+ " level = " + level + ";" + nl +
+ " description = " + description + ";" + nl +
+ "} Alert;" + nl;
+ }
+
+ // Inner classes.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The level enumeration.
+ *
+ * <pre>
+ * enum { warning(1), fatal(2), (255) } AlertLevel;
+ * </pre>
+ */
+ static final class Level implements Enumerated
+ {
+
+ // Constants and fields.
+ // -----------------------------------------------------------------------
+
+ static final Level WARNING = new Level(1), FATAL = new Level(2);
+
+ private final int value;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ private Level(int value)
+ {
+ this.value = value;
+ }
+
+ // Class method.
+ // -----------------------------------------------------------------------
+
+ static Level read(InputStream in) throws IOException
+ {
+ int i = in.read();
+ if (i == -1)
+ {
+ throw new EOFException("unexpected end of stream");
+ }
+ switch (i & 0xFF)
+ {
+ case 1: return WARNING;
+ case 2: return FATAL;
+ default: return new Level(i);
+ }
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return new byte[] { (byte) value };
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ switch (value)
+ {
+ case 1: return "warning";
+ case 2: return "fatal";
+ default: return "unknown(" + value + ")";
+ }
+ }
+ }
+
+ /**
+ * The description enumeration.
+ */
+ static final class Description implements Enumerated
+ {
+
+ // Constants and fields.
+ // -----------------------------------------------------------------------
+
+ static final Description
+ CLOSE_NOTIFY = new Description( 0),
+ UNEXPECTED_MESSAGE = new Description( 10),
+ BAD_RECORD_MAC = new Description( 20),
+ DECRYPTION_FAILED = new Description( 21),
+ RECORD_OVERFLOW = new Description( 22),
+ DECOMPRESSION_FAILURE = new Description( 30),
+ HANDSHAKE_FAILURE = new Description( 40),
+ NO_CERTIFICATE = new Description( 41),
+ BAD_CERTIFICATE = new Description( 42),
+ UNSUPPORTED_CERTIFICATE = new Description( 43),
+ CERTIFICATE_REVOKED = new Description( 44),
+ CERTIFICATE_EXPIRED = new Description( 45),
+ CERTIFICATE_UNKNOWN = new Description( 46),
+ ILLEGAL_PARAMETER = new Description( 47),
+ UNKNOWN_CA = new Description( 48),
+ ACCESS_DENIED = new Description( 49),
+ DECODE_ERROR = new Description( 50),
+ DECRYPT_ERROR = new Description( 51),
+ EXPORT_RESTRICTION = new Description( 60),
+ PROTOCOL_VERSION = new Description( 70),
+ INSUFFICIENT_SECURITY = new Description( 71),
+ INTERNAL_ERROR = new Description( 80),
+ USER_CANCELED = new Description( 90),
+ NO_RENEGOTIATION = new Description(100),
+ UNSUPPORTED_EXTENSION = new Description(110),
+ CERTIFICATE_UNOBTAINABLE = new Description(111),
+ UNRECOGNIZED_NAME = new Description(112),
+ BAD_CERTIFICATE_STATUS_RESPONSE = new Description(113),
+ BAD_CERTIFICATE_HASH_VALUE = new Description(114),
+ UNKNOWN_SRP_USERNAME = new Description(120),
+ MISSING_SRP_USERNAME = new Description(121);
+
+ private final int value;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ private Description(int value)
+ {
+ this.value = value;
+ }
+
+ // Class method.
+ // -----------------------------------------------------------------------
+
+ static Description read(InputStream in) throws IOException
+ {
+ int i = in.read();
+ if (i == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ switch (i)
+ {
+ case 0: return CLOSE_NOTIFY;
+ case 10: return UNEXPECTED_MESSAGE;
+ case 20: return BAD_RECORD_MAC;
+ case 21: return DECRYPTION_FAILED;
+ case 22: return RECORD_OVERFLOW;
+ case 30: return DECOMPRESSION_FAILURE;
+ case 40: return HANDSHAKE_FAILURE;
+ case 41: return NO_CERTIFICATE;
+ case 42: return BAD_CERTIFICATE;
+ case 43: return UNSUPPORTED_CERTIFICATE;
+ case 44: return CERTIFICATE_REVOKED;
+ case 45: return CERTIFICATE_EXPIRED;
+ case 46: return CERTIFICATE_UNKNOWN;
+ case 47: return ILLEGAL_PARAMETER;
+ case 48: return UNKNOWN_CA;
+ case 49: return ACCESS_DENIED;
+ case 50: return DECODE_ERROR;
+ case 51: return DECRYPT_ERROR;
+ case 60: return EXPORT_RESTRICTION;
+ case 70: return PROTOCOL_VERSION;
+ case 71: return INSUFFICIENT_SECURITY;
+ case 80: return INTERNAL_ERROR;
+ case 90: return USER_CANCELED;
+ case 100: return NO_RENEGOTIATION;
+ case 120: return UNKNOWN_SRP_USERNAME;
+ case 121: return MISSING_SRP_USERNAME;
+ default: return new Description(i);
+ }
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return new byte[] { (byte) value };
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ switch (value)
+ {
+ case 0: return "close_notify";
+ case 10: return "unexpected_message";
+ case 20: return "bad_record_mac";
+ case 21: return "decryption_failed";
+ case 22: return "record_overflow";
+ case 30: return "decompression_failure";
+ case 40: return "handshake_failure";
+ case 42: return "bad_certificate";
+ case 43: return "unsupported_certificate";
+ case 44: return "certificate_revoked";
+ case 45: return "certificate_expired";
+ case 46: return "certificate_unknown";
+ case 47: return "illegal_parameter";
+ case 48: return "unknown_ca";
+ case 49: return "access_denied";
+ case 50: return "decode_error";
+ case 51: return "decrypt_error";
+ case 60: return "export_restriction";
+ case 70: return "protocol_version";
+ case 71: return "insufficient_security";
+ case 80: return "internal_error";
+ case 90: return "user_canceled";
+ case 100: return "no_renegotiation";
+ case 110: return "unsupported_extension";
+ case 111: return "certificate_unobtainable";
+ case 112: return "unrecognized_name";
+ case 113: return "bad_certificate_status_response";
+ case 114: return "bad_certificate_hash_value";
+ case 120: return "unknown_srp_username";
+ case 121: return "missing_srp_username";
+ default: return "unknown(" + value + ")";
+ }
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/AlertException.java b/gnu/javax/net/ssl/provider/AlertException.java
new file mode 100644
index 000000000..666efe5ac
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/AlertException.java
@@ -0,0 +1,76 @@
+/* AlertException.java -- exceptions generated by SSL alerts.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import javax.net.ssl.SSLException;
+
+class AlertException extends SSLException
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final Alert alert;
+ private final boolean isLocal;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ AlertException(Alert alert, boolean isLocal)
+ {
+ super(alert.getDescription().toString());
+ this.alert = alert;
+ this.isLocal = isLocal;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String getMessage()
+ {
+ return alert.getDescription() + ": " +
+ (isLocal ? "locally generated; " : "remotely generated; ") +
+ alert.getLevel();
+ }
+
+ public Alert getAlert ()
+ {
+ return alert;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Certificate.java b/gnu/javax/net/ssl/provider/Certificate.java
new file mode 100644
index 000000000..b1d6b2a01
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Certificate.java
@@ -0,0 +1,194 @@
+/* Certificate.java -- SSL Certificate message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import java.util.LinkedList;
+
+import javax.net.ssl.SSLProtocolException;
+
+final class Certificate implements Handshake.Body
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final X509Certificate[] certs;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ Certificate(X509Certificate[] certs)
+ {
+ if (certs == null)
+ {
+ throw new NullPointerException();
+ }
+ this.certs = certs;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static Certificate read(InputStream in, CertificateType type)
+ throws IOException
+ {
+ if (type == CertificateType.X509)
+ {
+ int len = (in.read() & 0xFF) << 16 | (in.read() & 0xFF) << 8
+ | (in.read() & 0xFF);
+ byte[] buf = new byte[len];
+ int count = 0;
+ while (count < len)
+ {
+ int l = in.read(buf, count, len - count);
+ if (l == -1)
+ {
+ throw new EOFException("unexpected end of stream");
+ }
+ count += l;
+ }
+ try
+ {
+ LinkedList certs = new LinkedList();
+ CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ ByteArrayInputStream bin = new ByteArrayInputStream(buf);
+ count = 0;
+ while (count < len)
+ {
+ int len2 = (bin.read() & 0xFF) << 16 | (bin.read() & 0xFF) << 8
+ | (bin.read() & 0xFF);
+ certs.add(fact.generateCertificate(bin));
+ count += len2 + 3;
+ }
+ return new Certificate((X509Certificate[])
+ certs.toArray(new X509Certificate[certs.size()]));
+ }
+ catch (CertificateException ce)
+ {
+ SSLProtocolException sslpe = new SSLProtocolException(ce.getMessage());
+ sslpe.initCause (ce);
+ throw sslpe;
+ }
+ }
+ else if (type == CertificateType.OPEN_PGP)
+ {
+ throw new UnsupportedOperationException("not yet implemented");
+ }
+ else
+ throw new Error("unsupported certificate type "+type);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ try
+ {
+ for (int i = 0; i < certs.length; i++)
+ {
+ byte[] enc = certs[i].getEncoded();
+ bout.write((enc.length >>> 16) & 0xFF);
+ bout.write((enc.length >>> 8) & 0xFF);
+ bout.write( enc.length & 0xFF);
+ bout.write(enc);
+ }
+ }
+ catch (CertificateEncodingException cee)
+ {
+ throw new Error("cannot encode certificates");
+ }
+ catch (IOException ignored)
+ {
+ }
+ out.write(bout.size() >>> 16 & 0xFF);
+ out.write(bout.size() >>> 8 & 0xFF);
+ out.write(bout.size() & 0xFF);
+ bout.writeTo(out);
+ }
+
+ X509Certificate[] getCertificates()
+ {
+ return certs;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ out.println(" certificateList =");
+ for (int i = 0; i < certs.length; i++)
+ {
+ BufferedReader r =
+ new BufferedReader(new StringReader(certs[i].toString()));
+ String s;
+ try
+ {
+ while ((s = r.readLine()) != null)
+ {
+ out.print(" ");
+ out.println(s);
+ }
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ out.println("} Certificate;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CertificateRequest.java b/gnu/javax/net/ssl/provider/CertificateRequest.java
new file mode 100644
index 000000000..0f788039b
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CertificateRequest.java
@@ -0,0 +1,285 @@
+/* CertificateRequest.java -- SSL CertificateRequest message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import java.util.LinkedList;
+import java.security.Principal;
+
+final class CertificateRequest implements Handshake.Body
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final ClientType[] types;
+ private final Principal[] authorities;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ CertificateRequest(ClientType[] types, Principal[] authorities)
+ {
+ if (types == null)
+ {
+ throw new NullPointerException();
+ }
+ this.types = types;
+ if (authorities == null)
+ {
+ throw new NullPointerException();
+ }
+ this.authorities = authorities;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static CertificateRequest read(InputStream in) throws IOException
+ {
+ DataInputStream din = new DataInputStream(in);
+ ClientType[] types = new ClientType[din.readUnsignedByte()];
+ for (int i = 0; i < types.length; i++)
+ {
+ types[i] = ClientType.read(din);
+ }
+
+ LinkedList authorities = new LinkedList();
+ byte[] buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ ByteArrayInputStream bin = new ByteArrayInputStream(buf);
+ try
+ {
+ String x500name = Util.getSecurityProperty("jessie.x500.class");
+ if (x500name == null)
+ {
+ x500name = "org.metastatic.jessie.pki.X500Name";
+ }
+ Class x500class = null;
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ if (cl != null)
+ {
+ x500class = cl.loadClass(x500name);
+ }
+ else
+ {
+ x500class = Class.forName(x500name);
+ }
+ Constructor c = x500class.getConstructor(new Class[] { new byte[0].getClass() });
+ while (bin.available() > 0)
+ {
+ buf = new byte[(bin.read() & 0xFF) << 8 | (bin.read() & 0xFF)];
+ bin.read(buf);
+ authorities.add(c.newInstance(new Object[] { buf }));
+ }
+ }
+ catch (IOException ioe)
+ {
+ throw ioe;
+ }
+ catch (Exception ex)
+ {
+ throw new Error(ex.toString());
+ }
+ return new CertificateRequest(types,
+ (Principal[]) authorities.toArray(new Principal[authorities.size()]));
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ out.write(types.length);
+ for (int i = 0; i < types.length; i++)
+ {
+ out.write(types[i].getValue());
+ }
+
+ try
+ {
+ Class x500class = authorities[0].getClass();
+ Method m = x500class.getMethod("getEncoded", null);
+ for (int i = 0; i < authorities.length; i++)
+ {
+ byte[] buf = (byte[]) m.invoke(authorities[i], null);
+ bout.write(buf.length >>> 8 & 0xFF);
+ bout.write(buf.length & 0xFF);
+ bout.write(buf, 0, buf.length);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Error(ex.toString());
+ }
+ out.write(bout.size() >>> 8 & 0xFF);
+ out.write(bout.size() & 0xFF);
+ bout.writeTo(out);
+ }
+
+ ClientType[] getTypes()
+ {
+ return types;
+ }
+
+ String[] getTypeStrings()
+ {
+ try
+ {
+ return (String[]) Util.transform(types, String.class, "toString", null);
+ }
+ catch (Exception x)
+ {
+ return null;
+ }
+ }
+
+ Principal[] getAuthorities()
+ {
+ return authorities;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ out.print(" types = ");
+ for (int i = 0; i < types.length; i++)
+ {
+ out.print(types[i]);
+ if (i != types.length - 1)
+ out.print(", ");
+ }
+ out.println(";");
+ out.println(" authorities =");
+ for (int i = 0; i < authorities.length; i++)
+ {
+ out.print(" ");
+ out.print(authorities[i].getName());
+ if (i != types.length - 1)
+ out.println(",");
+ }
+ out.println(";");
+ out.println("} CertificateRequest;");
+ return str.toString();
+ }
+
+ // Inner class.
+ // -------------------------------------------------------------------------
+
+ static final class ClientType implements Enumerated
+ {
+
+ // Constants and fields.
+ // -----------------------------------------------------------------------
+
+ static final ClientType
+ RSA_SIGN = new ClientType(1), DSS_SIGN = new ClientType(2),
+ RSA_FIXED_DH = new ClientType(3), DSS_FIXED_DH = new ClientType(4);
+
+ private final int value;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ private ClientType(int value)
+ {
+ this.value = value;
+ }
+
+ // Class method.
+ // -----------------------------------------------------------------------
+
+ static ClientType read(InputStream in) throws IOException
+ {
+ int i = in.read();
+ if (i == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ switch (i & 0xFF)
+ {
+ case 1: return RSA_SIGN;
+ case 2: return DSS_SIGN;
+ case 3: return RSA_FIXED_DH;
+ case 4: return DSS_FIXED_DH;
+ default: return new ClientType(i);
+ }
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return new byte[] { (byte) value };
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ switch (value)
+ {
+ case 1: return "rsa_sign";
+ case 2: return "dss_sign";
+ case 3: return "rsa_fixed_dh";
+ case 4: return "dss_fixed_dh";
+ default: return "unknown(" + value + ")";
+ }
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CertificateType.java b/gnu/javax/net/ssl/provider/CertificateType.java
new file mode 100644
index 000000000..c5705939f
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CertificateType.java
@@ -0,0 +1,104 @@
+/* CertificateType.java -- the certificate type extension.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+
+final class CertificateType implements Enumerated
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ static final CertificateType X509 = new CertificateType(0);
+ static final CertificateType OPEN_PGP = new CertificateType(1);
+
+ private final int value;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ private CertificateType(int value)
+ {
+ this.value = value;
+ }
+
+ // Class method.
+ // -------------------------------------------------------------------------
+
+ static CertificateType read(InputStream in) throws IOException
+ {
+ int value = in.read();
+ if (value == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ switch (value & 0xFF)
+ {
+ case 0: return X509;
+ case 1: return OPEN_PGP;
+ default: return new CertificateType(value);
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return new byte[] { (byte) value };
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ switch (value)
+ {
+ case 0: return "X.509";
+ case 1: return "OpenPGP";
+ default: return "unknown(" + value + ")";
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CertificateVerify.java b/gnu/javax/net/ssl/provider/CertificateVerify.java
new file mode 100644
index 000000000..e0bf130f1
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CertificateVerify.java
@@ -0,0 +1,95 @@
+/* CertificateVerify.java -- SSL CertificateVerify message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.security.PublicKey;
+
+final class CertificateVerify extends Signature implements Handshake.Body
+{
+
+ // Contstructor.
+ // -------------------------------------------------------------------------
+
+ CertificateVerify(Object sigValue, String sigAlg)
+ {
+ super(sigValue, sigAlg);
+ }
+
+ // Class method.
+ // --------------------------------------------------------------------------
+
+ static Signature read(InputStream in, CipherSuite suite, PublicKey key)
+ throws IOException
+ {
+ Signature sig = Signature.read(in, suite, key);
+ return new CertificateVerify(sig.getSigValue(), sig.getSigAlg());
+ }
+
+ // Instance method.
+ // -------------------------------------------------------------------------
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ BufferedReader r = new BufferedReader(new StringReader(super.toString()));
+ String s;
+ try
+ {
+ while ((s = r.readLine()) != null)
+ {
+ out.print(" ");
+ out.println(s);
+ }
+ }
+ catch (IOException ignored)
+ {
+ }
+ out.println("} CertificateVerify;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CipherSuite.java b/gnu/javax/net/ssl/provider/CipherSuite.java
new file mode 100644
index 000000000..de916817b
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CipherSuite.java
@@ -0,0 +1,754 @@
+/* CipherSuite.java -- Supported cipher suites.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.lang.reflect.Field;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+
+import gnu.javax.crypto.cipher.CipherFactory;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+
+final class CipherSuite implements Constructed
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ private static final List tlsSuiteNames = new LinkedList();
+ private static final HashMap namesToSuites = new HashMap();
+
+ // SSL CipherSuites.
+ static final CipherSuite SSL_NULL_WITH_NULL_NULL =
+ new CipherSuite("null", "null", "null", "null", 0, 0x00, 0x00,
+ "SSL_NULL_WITH_NULL_NULL", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_NULL_MD5 =
+ new CipherSuite("null", "RSA", "RSA", "SSLMAC-MD5", 0, 0x00, 0x01,
+ "SSL_RSA_WITH_NULL_MD5", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_NULL_SHA =
+ new CipherSuite("null", "RSA", "RSA", "SSLMAC-SHA", 0, 0x00, 0x02,
+ "SSL_RSA_WITH_NULL_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_EXPORT_WITH_RC4_40_MD5 =
+ new CipherSuite("RC4", "RSA", "RSA", "SSLMAC-MD5", 5, 0x00, 0x03,
+ "SSL_RSA_EXPORT_WITH_RC4_40_MD5", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_RC4_128_MD5 =
+ new CipherSuite("RC4", "RSA", "RSA", "SSLMAC-MD5", 16, 0x00, 0x04,
+ "SSL_RSA_WITH_RC4_128_MD5", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_RC4_128_SHA =
+ new CipherSuite("RC4", "RSA", "RSA", "SSLMAC-SHA", 16, 0x00, 0x05,
+ "SSL_RSA_WITH_RC4_128_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "RSA", "RSA", "SSLMAC-SHA", 5, 0x00, 0x08,
+ "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "RSA", "RSA", "SSLMAC-SHA", 8, 0x00, 0x09,
+ "SSL_RSA_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "RSA", "RSA", "SSLMAC-SHA", 24, 0x00, 0x0A,
+ "SSL_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "DH", "DSS", "SSLMAC-SHA", 5, 0x00, 0x0B,
+ "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_DSS_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "DH", "DSS", "SSLMAC-SHA", 8, 0x00, 0x0C,
+ "SSL_DH_DSS_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "DH", "DSS", "SSLMAC-SHA", 24, 0x00, 0x0D,
+ "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "DH", "RSA", "SSLMAC-SHA", 5, 0x00, 0x0E,
+ "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "DH", "RSA", "SSLMAC-SHA", 8, 0x00, 0x0F,
+ "SSL_DH_RSA_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "DH", "RSA", "SSLMAC-SHA", 24, 0x00, 0x10,
+ "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "DHE", "DSS", "SSLMAC-SHA", 5, 0x00, 0x11,
+ "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "DHE", "DSS", "SSLMAC-SHA", 8, 0x00, 0x12,
+ "SSL_DHE_DSS_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "DHE", "DSS", "SSLMAC-SHA", 24, 0x00, 0x13,
+ "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "DHE", "RSA", "SSLMAC-SHA", 5, 0x00, 0x14,
+ "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "DHE", "RSA", "SSLMAC-SHA", 8, 0x00, 0x15,
+ "SSL_DHE_RSA_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "DHE", "RSA", "SSLMAC-SHA", 24, 0x00, 0x16,
+ "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
+
+ // AES CipherSuites.
+ static final CipherSuite SSL_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "RSA", "RSA", "SSLMAC-SHA", 16, 0x00, 0x2F,
+ "SSL_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_DSS_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "DH", "DSS", "SSLMAC-SHA", 16, 0x00, 0x30,
+ "SSL_DH_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "DH", "RSA", "SSLMAC-SHA", 16, 0x00, 0x31,
+ "SSL_DH_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "DHE", "DSS", "SSLMAC-SHA", 16, 0x00, 0x32,
+ "SSL_DHE_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "DHE", "RSA", "SSLMAC-SHA", 16, 0x00, 0x33,
+ "SSL_DHE_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "RSA", "RSA", "SSLMAC-SHA", 32, 0x00, 0x35,
+ "SSL_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_DSS_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "DH", "DSS", "SSLMAC-SHA", 32, 0x00, 0x36,
+ "SSL_DH_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DH_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "DH", "RSA", "SSLMAC-SHA", 32, 0x00, 0x37,
+ "SSL_DH_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "DHE", "DSS", "SSLMAC-SHA", 32, 0x00, 0x38,
+ "SSL_DHE_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "DHE", "RSA", "SSLMAC-SHA", 32, 0x00, 0x39,
+ "SSL_DHE_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
+
+ // Ciphersuites from the OpenPGP extension draft.
+ static final CipherSuite SSL_DHE_DSS_WITH_CAST_128_CBC_SHA =
+ new CipherSuite("CAST5", "DHE", "DSS", "HMAC-SHA", 16, 0x00, 0x70,
+ "SSL_DHE_DSS_WITH_CAST_128_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_WITH_CAST_128_CBC_RMD =
+ new CipherSuite("CAST5", "DHE", "DSS", "HMAC-RIPEMD-160", 16, 0x00, 0x71,
+ "SSL_DHE_DSS_WITH_CAST_128_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite("TripleDES", "DHE", "DSS", "HMAC-RIPEMD-160", 24, 0x00, 0x72,
+ "SSL_DHE_DSS_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_WITH_AES_128_CBC_RMD =
+ new CipherSuite("AES", "DHE", "DSS", "HMAC-RIPEMD-160", 16, 0x00, 0x73,
+ "SSL_DHE_DSS_WITH_AES_128_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_DSS_WITH_AES_256_CBC_RMD =
+ new CipherSuite("AES", "DHE", "DSS", "HMAC-RIPEMD-160", 32, 0x00, 0x74,
+ "SSL_DHE_DSS_WITH_AES_256_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_CAST_128_CBC_SHA =
+ new CipherSuite("CAST5", "DHE", "RSA", "HMAC-SHA", 16, 0x00, 0x75,
+ "SSL_DHE_RSA_WITH_CAST_128_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_CAST_128_CBC_RMD =
+ new CipherSuite("CAST5", "DHE", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x76,
+ "SSL_DHE_RSA_WITH_CAST_128_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite("TripleDES", "DHE", "RSA", "HMAC-RIPEMD-160", 24, 0x00, 0x77,
+ "SSL_DHE_RSA_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_AES_128_CBC_RMD =
+ new CipherSuite("AES", "DHE", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x78,
+ "SSL_DHE_RSA_WITH_AES_128_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_DHE_RSA_WITH_AES_256_CBC_RMD =
+ new CipherSuite("AES", "DHE", "RSA", "HMAC-RIPEMD-160", 32, 0x00, 0x79,
+ "SSL_DHE_RSA_WITH_AES_256_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_CAST_128_CBC_SHA =
+ new CipherSuite("CAST5", "RSA", "RSA", "HMAC-SHA", 16, 0x00, 0x7A,
+ "SSL_RSA_WITH_CAST_128_CBC_SHA", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_CAST_128_CBC_RMD =
+ new CipherSuite("CAST5", "RSA", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x7B,
+ "SSL_RSA_WITH_CAST_128_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite("TripleDES", "RSA", "RSA", "HMAC-RIPEMD-160", 24, 0x00, 0x7C,
+ "SSL_RSA_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_AES_128_CBC_RMD =
+ new CipherSuite("AES", "RSA", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x7D,
+ "SSL_RSA_WITH_AES_128_CBC_RMD", ProtocolVersion.SSL_3);
+ static final CipherSuite SSL_RSA_WITH_AES_256_CBC_RMD =
+ new CipherSuite("AES", "RSA", "RSA", "HMAC-RIPEMD-160", 32, 0x00, 0x7E,
+ "SSL_RSA_WITH_AES_256_CBC_RMD", ProtocolVersion.SSL_3);
+
+ static final CipherSuite TLS_NULL_WITH_NULL_NULL =
+ new CipherSuite("null", "null", "null", "null", 0, 0x00, 0x00,
+ "TLS_NULL_WITH_NULL_NULL", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_NULL_MD5 =
+ new CipherSuite("null", "RSA", "RSA", "HMAC-MD5", 0, 0x00, 0x01,
+ "TLS_RSA_WITH_NULL_MD5", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_NULL_SHA =
+ new CipherSuite("null", "RSA", "RSA", "HMAC-SHA", 0, 0x00, 0x02,
+ "TLS_RSA_WITH_NULL_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 =
+ new CipherSuite("RC4", "RSA", "RSA", "HMAC-MD5", 5, 0x00, 0x03,
+ "TLS_RSA_EXPORT_WITH_RC4_40_MD5", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_RC4_128_MD5 =
+ new CipherSuite("RC4", "RSA", "RSA", "HMAC-MD5", 16, 0x00, 0x04,
+ "TLS_RSA_WITH_RC4_128_MD5", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_RC4_128_SHA =
+ new CipherSuite("RC4", "RSA", "RSA", "HMAC-SHA", 16, 0x00, 0x05,
+ "TLS_RSA_WITH_RC4_128_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "RSA", "RSA", "HMAC-SHA", 5, 0x00, 0x08,
+ "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "RSA", "RSA", "HMAC-SHA", 8, 0x00, 0x09,
+ "TLS_RSA_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "RSA", "RSA", "HMAC-SHA", 24, 0x00, 0x0A,
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "DH", "DSS", "HMAC-SHA", 5, 0x00, 0x0B,
+ "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "DH", "DSS", "HMAC-SHA", 8, 0x00, 0x0C,
+ "TLS_DH_DSS_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "DH", "DSS", "HMAC-SHA", 24, 0x00, 0x0D,
+ "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "DH", "RSA", "HMAC-SHA", 5, 0x00, 0x0E,
+ "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "DH", "RSA", "HMAC-SHA", 8, 0x00, 0x0F,
+ "TLS_DH_RSA_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "DH", "RSA", "HMAC-SHA", 24, 0x00, 0x10,
+ "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "DHE", "DSS", "HMAC-SHA", 5, 0x00, 0x11,
+ "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "DHE", "DSS", "HMAC-SHA", 8, 0x00, 0x12,
+ "TLS_DHE_DSS_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "DHE", "DSS", "HMAC-SHA", 24, 0x00, 0x13,
+ "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite("DES", "DHE", "RSA", "HMAC-SHA", 5, 0x00, 0x14,
+ "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite("DES", "DHE", "RSA", "HMAC-SHA", 8, 0x00, 0x15,
+ "TLS_DHE_RSA_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "DHE", "RSA", "HMAC-SHA", 24, 0x00, 0x16,
+ "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
+
+ // AES CipherSuites.
+ static final CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "RSA", "RSA", "HMAC-SHA", 16, 0x00, 0x2F,
+ "TLS_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_DSS_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "DH", "DSS", "HMAC-SHA", 16, 0x00, 0x30,
+ "TLS_DH_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "DH", "RSA", "HMAC-SHA", 16, 0x00, 0x31,
+ "TLS_DH_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "DHE", "DSS", "HMAC-SHA", 16, 0x00, 0x32,
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "DHE", "RSA", "HMAC-SHA", 16, 0x00, 0x33,
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "RSA", "RSA", "HMAC-SHA", 32, 0x00, 0x35,
+ "TLS_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_DSS_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "DH", "DSS", "HMAC-SHA", 32, 0x00, 0x36,
+ "TLS_DH_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DH_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "DH", "RSA", "HMAC-SHA", 32, 0x00, 0x37,
+ "TLS_DH_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "DHE", "DSS", "HMAC-SHA", 32, 0x00, 0x38,
+ "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "DHE", "RSA", "HMAC-SHA", 32, 0x00, 0x39,
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+
+ // Secure remote password (SRP) ciphersuites
+ static final CipherSuite TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "SRP", "anon", "HMAC-SHA", 24, 0x00, 0x50,
+ "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "SRP", "RSA", "HMAC-SHA", 24, 0x00, 0x51,
+ "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite("TripleDES", "SRP", "DSS", "HMAC-SHA", 24, 0x00, 0x52,
+ "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_SRP_SHA_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "SRP", "anon", "HMAC-SHA", 16, 0x00, 0x53,
+ "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "SRP", "RSA", "HMAC-SHA", 16, 0x00, 0x54,
+ "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA =
+ new CipherSuite("AES", "SRP", "DSS", "HMAC-SHA", 16, 0x00, 0x55,
+ "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_SRP_SHA_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "SRP", "anon", "HMAC-SHA", 32, 0x00, 0x56,
+ "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "SRP", "RSA", "HMAC-SHA", 32, 0x00, 0x57,
+ "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA =
+ new CipherSuite("AES", "SRP", "DSS", "HMAC-SHA", 32, 0x00, 0x58,
+ "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+
+ // Ciphersuites from the OpenPGP extension draft.
+ static final CipherSuite TLS_DHE_DSS_WITH_CAST_128_CBC_SHA =
+ new CipherSuite("CAST5", "DHE", "DSS", "HMAC-SHA", 16, 0x00, 0x70,
+ "TLS_DHE_DSS_WITH_CAST_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_WITH_CAST_128_CBC_RMD =
+ new CipherSuite("CAST5", "DHE", "DSS", "HMAC-RIPEMD-160", 16, 0x00, 0x71,
+ "TLS_DHE_DSS_WITH_CAST_128_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite("TripleDES", "DHE", "DSS", "HMAC-RIPEMD-160", 24, 0x00, 0x72,
+ "TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_RMD =
+ new CipherSuite("AES", "DHE", "DSS", "HMAC-RIPEMD-160", 16, 0x00, 0x73,
+ "TLS_DHE_DSS_WITH_AES_128_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_RMD =
+ new CipherSuite("AES", "DHE", "DSS", "HMAC-RIPEMD-160", 32, 0x00, 0x74,
+ "TLS_DHE_DSS_WITH_AES_256_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_CAST_128_CBC_SHA =
+ new CipherSuite("CAST5", "DHE", "RSA", "HMAC-SHA", 16, 0x00, 0x75,
+ "TLS_DHE_RSA_WITH_CAST_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_CAST_128_CBC_RMD =
+ new CipherSuite("CAST5", "DHE", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x76,
+ "TLS_DHE_RSA_WITH_CAST_128_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite("TripleDES", "DHE", "RSA", "HMAC-RIPEMD-160", 24, 0x00, 0x77,
+ "TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_RMD =
+ new CipherSuite("AES", "DHE", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x78,
+ "TLS_DHE_RSA_WITH_AES_128_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_RMD =
+ new CipherSuite("AES", "DHE", "RSA", "HMAC-RIPEMD-160", 32, 0x00, 0x79,
+ "TLS_DHE_RSA_WITH_AES_256_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_CAST_128_CBC_SHA =
+ new CipherSuite("CAST5", "RSA", "RSA", "HMAC-SHA", 16, 0x00, 0x7A,
+ "TLS_RSA_WITH_CAST_128_CBC_SHA", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_CAST_128_CBC_RMD =
+ new CipherSuite("CAST5", "RSA", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x7B,
+ "TLS_RSA_WITH_CAST_128_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite("TripleDES", "RSA", "RSA", "HMAC-RIPEMD-160", 24, 0x00, 0x7C,
+ "TLS_RSA_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_AES_128_CBC_RMD =
+ new CipherSuite("AES", "RSA", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x7D,
+ "TLS_RSA_WITH_AES_128_CBC_RMD", ProtocolVersion.TLS_1);
+ static final CipherSuite TLS_RSA_WITH_AES_256_CBC_RMD =
+ new CipherSuite("AES", "RSA", "RSA", "HMAC-RIPEMD-160", 32, 0x00, 0x7E,
+ "TLS_RSA_WITH_AES_256_CBC_RMD", ProtocolVersion.TLS_1);
+
+ private final String cipherName;
+ private final String kexName;
+ private final String sigName;
+ private final String macName;
+ private final boolean exportable;
+ private final boolean isStream;
+ private final int keyLength;
+ private final byte[] id;
+ private final String name;
+ private final ProtocolVersion version;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ private CipherSuite(String cipherName, String kexName, String sigName,
+ String macName, int keyLength, int id1, int id2,
+ String name, ProtocolVersion version)
+ {
+ this.cipherName = cipherName.intern();
+ this.kexName = kexName.intern();
+ this.sigName = sigName.intern();
+ this.macName = macName.intern();
+ this.exportable = keyLength <= 5;
+ this.isStream = cipherName.equals("null") || cipherName.equals("RC4");
+ this.keyLength = keyLength;
+ this.id = new byte[] { (byte) id1, (byte) id2 };
+ this.name = name.intern();
+ this.version = version;
+ namesToSuites.put(name, this);
+ if (name.startsWith("TLS"))
+ {
+ tlsSuiteNames.add(name);
+ }
+ }
+
+ private CipherSuite(byte[] id)
+ {
+ cipherName = null;
+ kexName = null;
+ sigName = null;
+ macName = null;
+ exportable = false;
+ isStream = false;
+ keyLength = 0;
+ this.id = id;
+ name = null;
+ version = null;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns the cipher suite for the given name, or null if there is no
+ * such suite.
+ *
+ * @return The named cipher suite.
+ */
+ static CipherSuite forName(String name)
+ {
+ return (CipherSuite) namesToSuites.get(name);
+ }
+
+ static List availableSuiteNames()
+ {
+ return tlsSuiteNames;
+ }
+
+ static CipherSuite read(InputStream in) throws IOException
+ {
+ DataInputStream din = new DataInputStream(in);
+ byte[] id = new byte[2];
+ din.readFully(id);
+ return new CipherSuite(id);
+ }
+
+ static IMode getCipher(String cbcCipherName)
+ {
+ IBlockCipher cipher = CipherFactory.getInstance(cbcCipherName);
+ if (cipher == null)
+ {
+ return null;
+ }
+ return ModeFactory.getInstance("CBC", cipher, cipher.defaultBlockSize());
+ }
+
+ static Cipher getJCECipher (final String name)
+ throws NoSuchAlgorithmException, NoSuchPaddingException
+ {
+ final String provider = Util.getSecurityProperty ("jessie.with.jce.provider");
+ if (name.equals ("RC4"))
+ {
+ if (provider != null)
+ {
+ try
+ {
+ return Cipher.getInstance (name, provider);
+ }
+ catch (NoSuchProviderException nsae)
+ {
+ // Fall through. Try any available provider.
+ }
+ }
+
+ return Cipher.getInstance (name);
+ }
+ else
+ {
+ // Oh, hey! Look! Something else Sun doesn't understand: SSLv3 padding
+ // is different than TLSv1 in subtle, but important, ways. But they
+ // sorta look the same, so why not make them equivalent?
+ //
+ // There should be a seperate padding "TLS1Padding".
+ if (provider != null)
+ {
+ try
+ {
+ return Cipher.getInstance (name + "/CBC/SSL3Padding", provider);
+ }
+ catch (NoSuchProviderException nspe)
+ {
+ // Fall through. Try any available provider.
+ }
+ }
+ return Cipher.getInstance (name + "/CBC/SSL3Padding");
+ }
+ }
+
+ static IMac getMac(String macName)
+ {
+ if (macName.startsWith("SSLMAC-"))
+ {
+ return new SSLHMac(macName.substring(7));
+ }
+ else
+ {
+ return MacFactory.getInstance(macName);
+ }
+ }
+
+ static Mac getJCEMac (final String name)
+ throws NoSuchAlgorithmException
+ {
+ final String provider = Util.getSecurityProperty ("jessie.with.jce.provider");
+ if (provider != null)
+ {
+ try
+ {
+ return Mac.getInstance (name, provider);
+ }
+ catch (NoSuchProviderException nspe)
+ {
+ // Fall through. Try any available provider.
+ }
+ }
+ return Mac.getInstance (name);
+ }
+
+ // Intance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ out.write(id);
+ }
+
+ CipherSuite resolve(ProtocolVersion version)
+ {
+ if (version == ProtocolVersion.SSL_3)
+ {
+ if (id[0] == 0x00) switch (id[1])
+ {
+ case 0x00: return SSL_NULL_WITH_NULL_NULL;
+ case 0x01: return SSL_RSA_WITH_NULL_MD5;
+ case 0x02: return SSL_RSA_WITH_NULL_SHA;
+ case 0x03: return SSL_RSA_EXPORT_WITH_RC4_40_MD5;
+ case 0x04: return SSL_RSA_WITH_RC4_128_MD5;
+ case 0x05: return SSL_RSA_WITH_RC4_128_SHA;
+ case 0x08: return SSL_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x09: return SSL_RSA_WITH_DES_CBC_SHA;
+ case 0x0A: return SSL_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x0B: return SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x0C: return SSL_DH_DSS_WITH_DES_CBC_SHA;
+ case 0x0D: return SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA;
+ case 0x0E: return SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x0F: return SSL_DH_RSA_WITH_DES_CBC_SHA;
+ case 0x10: return SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x11: return SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x12: return SSL_DHE_DSS_WITH_DES_CBC_SHA;
+ case 0x13: return SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+ case 0x14: return SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x15: return SSL_DHE_RSA_WITH_DES_CBC_SHA;
+ case 0x16: return SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x2F: return SSL_RSA_WITH_AES_128_CBC_SHA;
+ case 0x30: return SSL_DH_DSS_WITH_AES_128_CBC_SHA;
+ case 0x31: return SSL_DH_RSA_WITH_AES_128_CBC_SHA;
+ case 0x32: return SSL_DHE_DSS_WITH_AES_128_CBC_SHA;
+ case 0x33: return SSL_DHE_RSA_WITH_AES_128_CBC_SHA;
+ case 0x35: return SSL_RSA_WITH_AES_256_CBC_SHA;
+ case 0x36: return SSL_DH_DSS_WITH_AES_256_CBC_SHA;
+ case 0x37: return SSL_DH_RSA_WITH_AES_256_CBC_SHA;
+ case 0x38: return SSL_DHE_DSS_WITH_AES_256_CBC_SHA;
+ case 0x39: return SSL_DHE_RSA_WITH_AES_256_CBC_SHA;
+ }
+ }
+ else if (version == ProtocolVersion.TLS_1 ||
+ version == ProtocolVersion.TLS_1_1)
+ {
+ if (id[0] == 0x00) switch (id[1])
+ {
+ case 0x00: return TLS_NULL_WITH_NULL_NULL;
+ case 0x01: return TLS_RSA_WITH_NULL_MD5;
+ case 0x02: return TLS_RSA_WITH_NULL_SHA;
+ case 0x03: return TLS_RSA_EXPORT_WITH_RC4_40_MD5;
+ case 0x04: return TLS_RSA_WITH_RC4_128_MD5;
+ case 0x05: return TLS_RSA_WITH_RC4_128_SHA;
+ case 0x08: return TLS_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x09: return TLS_RSA_WITH_DES_CBC_SHA;
+ case 0x0A: return TLS_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x0B: return TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x0C: return TLS_DH_DSS_WITH_DES_CBC_SHA;
+ case 0x0D: return TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA;
+ case 0x0E: return TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x0F: return TLS_DH_RSA_WITH_DES_CBC_SHA;
+ case 0x10: return TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x11: return TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x12: return TLS_DHE_DSS_WITH_DES_CBC_SHA;
+ case 0x13: return TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+ case 0x14: return TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x15: return TLS_DHE_RSA_WITH_DES_CBC_SHA;
+ case 0x16: return TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x2F: return TLS_RSA_WITH_AES_128_CBC_SHA;
+ case 0x30: return TLS_DH_DSS_WITH_AES_128_CBC_SHA;
+ case 0x31: return TLS_DH_RSA_WITH_AES_128_CBC_SHA;
+ case 0x32: return TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+ case 0x33: return TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+ case 0x35: return TLS_RSA_WITH_AES_256_CBC_SHA;
+ case 0x36: return TLS_DH_DSS_WITH_AES_256_CBC_SHA;
+ case 0x37: return TLS_DH_RSA_WITH_AES_256_CBC_SHA;
+ case 0x38: return TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+ case 0x39: return TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+ case 0x50: return TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
+ case 0x51: return TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x52: return TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+ case 0x53: return TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
+ case 0x54: return TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+ case 0x55: return TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+ case 0x56: return TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
+ case 0x57: return TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+ case 0x58: return TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+ case 0x70: return TLS_DHE_DSS_WITH_CAST_128_CBC_SHA;
+ case 0x71: return TLS_DHE_DSS_WITH_CAST_128_CBC_RMD;
+ case 0x72: return TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD;
+ case 0x73: return TLS_DHE_DSS_WITH_AES_128_CBC_RMD;
+ case 0x74: return TLS_DHE_DSS_WITH_AES_256_CBC_RMD;
+ case 0x75: return TLS_DHE_RSA_WITH_CAST_128_CBC_SHA;
+ case 0x76: return TLS_DHE_RSA_WITH_CAST_128_CBC_RMD;
+ case 0x77: return TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD;
+ case 0x78: return TLS_DHE_RSA_WITH_AES_128_CBC_RMD;
+ case 0x79: return TLS_DHE_RSA_WITH_AES_256_CBC_RMD;
+ case 0x7A: return TLS_RSA_WITH_CAST_128_CBC_SHA;
+ case 0x7B: return TLS_RSA_WITH_CAST_128_CBC_RMD;
+ case 0x7C: return TLS_RSA_WITH_3DES_EDE_CBC_RMD;
+ case 0x7D: return TLS_RSA_WITH_AES_128_CBC_RMD;
+ case 0x7E: return TLS_RSA_WITH_AES_256_CBC_RMD;
+ }
+ }
+ return this;
+ }
+
+ String getCipher()
+ {
+ return cipherName;
+ }
+
+ int getKeyLength()
+ {
+ return keyLength;
+ }
+
+ String getKeyExchange()
+ {
+ return kexName;
+ }
+
+ String getSignature()
+ {
+ return sigName;
+ }
+
+ String getMac()
+ {
+ return macName;
+ }
+
+ boolean isExportable()
+ {
+ return exportable;
+ }
+
+ boolean isStreamCipher()
+ {
+ return isStream;
+ }
+
+ String getAuthType()
+ {
+ if (kexName.equals("RSA"))
+ {
+ if (isExportable())
+ {
+ return "RSA_EXPORT";
+ }
+ return "RSA";
+ }
+ return kexName + "_" + sigName;
+ }
+
+ byte[] getId()
+ {
+ return id;
+ }
+
+ ProtocolVersion getVersion()
+ {
+ return version;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof CipherSuite))
+ {
+ return false;
+ }
+ if (o == this)
+ return true;
+ byte[] id = ((CipherSuite) o).getId();
+ return id[0] == this.id[0] &&
+ id[1] == this.id[1];
+ }
+
+ public int hashCode()
+ {
+ if (version == null)
+ {
+ return 0xFFFF0000 | (id[0] & 0xFF) << 8 | (id[1] & 0xFF);
+ }
+ return version.getMajor() << 24 | version.getMinor() << 16
+ | (id[0] & 0xFF) << 8 | (id[1] & 0xFF);
+ }
+
+ public String toString()
+ {
+ if (name == null)
+ {
+ return "UNKNOWN { " + (id[0] & 0xFF) + ", " + (id[1] & 0xFF) + " }";
+ }
+ return name;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ClientHello.java b/gnu/javax/net/ssl/provider/ClientHello.java
new file mode 100644
index 000000000..259051df1
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientHello.java
@@ -0,0 +1,253 @@
+/* ClientHello.java -- SSL ClientHello message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.net.ssl.SSLProtocolException;
+
+final class ClientHello implements Handshake.Body
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private ProtocolVersion version;
+ private Random random;
+ private byte[] sessionId;
+ private List suites;
+ private List comp;
+ private List extensions;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ ClientHello(ProtocolVersion version, Random random,
+ byte[] sessionId, List suites, List comp)
+ {
+ this(version, random, sessionId, suites, comp, null);
+ }
+
+ ClientHello(ProtocolVersion version, Random random,
+ byte[] sessionId, List suites, List comp, List extensions)
+ {
+ this.version = version;
+ this.random = random;
+ this.sessionId = sessionId;
+ this.suites = suites;
+ this.comp = comp;
+ this.extensions = extensions;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static ClientHello read(InputStream in) throws IOException
+ {
+ ProtocolVersion vers = ProtocolVersion.read(in);
+ Random rand = Random.read(in);
+ byte[] id = new byte[in.read() & 0xFF];
+ in.read(id);
+ int len = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
+ ArrayList suites = new ArrayList(len / 2);
+ for (int i = 0; i < len; i += 2)
+ {
+ suites.add(CipherSuite.read(in).resolve(vers));
+ }
+ len = in.read() & 0xFF;
+ ArrayList comp = new ArrayList(len);
+ for (int i = 0; i < len; i++)
+ {
+ comp.add(CompressionMethod.read(in));
+ }
+
+ List ext = null;
+ // Since parsing MAY need to continue into the extensions fields, or it
+ // may end here, the specified input stream MUST be a ByteArrayInputStream
+ // over all the data this hello contains. Otherwise this will mess up
+ // the data stream.
+ if (in.available() > 0) // then we have extensions.
+ {
+ ext = new LinkedList();
+ len = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
+ int count = 0;
+ while (count < len)
+ {
+ Extension e = Extension.read(in);
+ ext.add(e);
+ count += e.getValue().length + 4;
+ }
+ }
+ return new ClientHello(vers, rand, id, suites, comp, ext);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ version.write(out);
+ random.write(out);
+ out.write(sessionId.length);
+ out.write(sessionId);
+ out.write((suites.size() << 1) >>> 8 & 0xFF);
+ out.write((suites.size() << 1) & 0xFF);
+ for (Iterator i = suites.iterator(); i.hasNext(); )
+ {
+ ((CipherSuite) i.next()).write(out);
+ }
+ out.write(comp.size());
+ for (Iterator i = comp.iterator(); i.hasNext(); )
+ {
+ out.write(((CompressionMethod) i.next()).getValue());
+ }
+ if (extensions != null)
+ {
+ ByteArrayOutputStream out2 = new ByteArrayOutputStream();
+ for (Iterator i = extensions.iterator(); i.hasNext(); )
+ {
+ ((Extension) i.next()).write(out2);
+ }
+ out.write(out2.size() >>> 8 & 0xFF);
+ out.write(out2.size() & 0xFF);
+ out2.writeTo(out);
+ }
+ }
+
+ ProtocolVersion getVersion()
+ {
+ return version;
+ }
+
+ Random getRandom()
+ {
+ return random;
+ }
+
+ byte[] getSessionId()
+ {
+ return sessionId;
+ }
+
+ List getCipherSuites()
+ {
+ return suites;
+ }
+
+ List getCompressionMethods()
+ {
+ return comp;
+ }
+
+ List getExtensions()
+ {
+ return extensions;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ out.println(" version = " + version + ";");
+ BufferedReader r = new BufferedReader(new StringReader(random.toString()));
+ String s;
+ try
+ {
+ while ((s = r.readLine()) != null)
+ {
+ out.print(" ");
+ out.println(s);
+ }
+ }
+ catch (IOException ignored)
+ {
+ }
+ out.println(" sessionId = " + Util.toHexString(sessionId, ':') + ";");
+ out.println(" cipherSuites = {");
+ for (Iterator i = suites.iterator(); i.hasNext(); )
+ {
+ out.print(" ");
+ out.println(i.next());
+ }
+ out.println(" };");
+ out.print(" compressionMethods = { ");
+ for (Iterator i = comp.iterator(); i.hasNext(); )
+ {
+ out.print(i.next());
+ if (i.hasNext())
+ out.print(", ");
+ }
+ out.println(" };");
+ if (extensions != null)
+ {
+ out.println(" extensions = {");
+ for (Iterator i = extensions.iterator(); i.hasNext(); )
+ {
+ r = new BufferedReader(new StringReader(i.next().toString()));
+ try
+ {
+ while ((s = r.readLine()) != null)
+ {
+ out.print(" ");
+ out.println(s);
+ }
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ out.println(" };");
+ }
+ out.println("} ClientHello;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ClientKeyExchange.java b/gnu/javax/net/ssl/provider/ClientKeyExchange.java
new file mode 100644
index 000000000..828aa8d5e
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientKeyExchange.java
@@ -0,0 +1,181 @@
+/* ClientKeyExchange.java -- SSL ClientKeyExchange message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import java.math.BigInteger;
+
+import java.security.PublicKey;
+import java.security.interfaces.RSAKey;
+import javax.crypto.interfaces.DHPublicKey;
+
+final class ClientKeyExchange implements Handshake.Body
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final Object exObject;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ ClientKeyExchange(byte[] encryptedSecret)
+ {
+ exObject = encryptedSecret;
+ }
+
+ ClientKeyExchange(BigInteger bigint)
+ {
+ exObject = bigint;
+ }
+
+ // Class method.
+ // -------------------------------------------------------------------------
+
+ static ClientKeyExchange read(InputStream in, CipherSuite suite,
+ PublicKey key)
+ throws IOException
+ {
+ DataInputStream din = new DataInputStream(in);
+ if (suite.getKeyExchange().equals("RSA"))
+ {
+ int len = 0;
+ if (suite.getVersion() == ProtocolVersion.SSL_3)
+ {
+ len = (((RSAKey) key).getModulus().bitLength()+7) / 8;
+ }
+ else
+ {
+ len = din.readUnsignedShort();
+ }
+ byte[] buf = new byte[len];
+ din.readFully(buf);
+ return new ClientKeyExchange(buf);
+ }
+ else if (suite.getKeyExchange().equals("SRP"))
+ {
+ byte[] buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ return new ClientKeyExchange(new BigInteger(1, buf));
+ }
+ else if (key == null || !(key instanceof DHPublicKey)) // explicit.
+ {
+ byte[] buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ return new ClientKeyExchange(new BigInteger(1, buf));
+ }
+ else
+ {
+ return new ClientKeyExchange(new byte[0]);
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ throw new UnsupportedOperationException("use write(java.io.OutputStream,ProtocolVersion) instead");
+ }
+
+ public void write(OutputStream out, ProtocolVersion version) throws IOException
+ {
+ if (exObject instanceof byte[])
+ {
+ byte[] b = (byte[]) exObject;
+ if (b.length > 0)
+ {
+ if (version != ProtocolVersion.SSL_3)
+ {
+ out.write(b.length >>> 8 & 0xFF);
+ out.write(b.length & 0xFF);
+ }
+ out.write(b);
+ }
+ }
+ else
+ {
+ byte[] bigint = ((BigInteger) exObject).toByteArray();
+ if (bigint[0] == 0x00)
+ {
+ out.write(bigint.length - 1 >>> 8 & 0xFF);
+ out.write(bigint.length - 1 & 0xFF);
+ out.write(bigint, 1, bigint.length - 1);
+ }
+ else
+ {
+ out.write(bigint.length >>> 8 & 0xFF);
+ out.write(bigint.length & 0xFF);
+ out.write(bigint);
+ }
+ }
+ }
+
+ Object getExchangeObject()
+ {
+ return exObject;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ if (exObject instanceof byte[] && ((byte[]) exObject).length > 0)
+ {
+ out.println(" encryptedPreMasterSecret =");
+ out.print(Util.hexDump((byte[]) exObject, " "));
+ }
+ else if (exObject instanceof BigInteger)
+ {
+ out.println(" clientPublic = " + ((BigInteger) exObject).toString(16) + ";");
+ }
+ out.println("} ClientKeyExchange;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CompressionMethod.java b/gnu/javax/net/ssl/provider/CompressionMethod.java
new file mode 100644
index 000000000..c2fdf05f9
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CompressionMethod.java
@@ -0,0 +1,104 @@
+/* CompressionMethod.java -- the compression method enum.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+
+final class CompressionMethod implements Enumerated
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ static final CompressionMethod NULL = new CompressionMethod(0),
+ ZLIB = new CompressionMethod(1);
+
+ private final int value;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ private CompressionMethod(int value)
+ {
+ this.value = value;
+ }
+
+ // Class method.
+ // -------------------------------------------------------------------------
+
+ static CompressionMethod read(InputStream in) throws IOException
+ {
+ int value = in.read();
+ if (value == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ switch (value & 0xFF)
+ {
+ case 0: return NULL;
+ case 1: return ZLIB;
+ default: return new CompressionMethod(value);
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return new byte[] { (byte) value };
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ switch (value)
+ {
+ case 0: return "null";
+ case 1: return "zlib";
+ default: return "unknown(" + value + ")";
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Constructed.java b/gnu/javax/net/ssl/provider/Constructed.java
new file mode 100644
index 000000000..ee3f56a7f
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Constructed.java
@@ -0,0 +1,57 @@
+/* Constructed.java -- constructed type.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * The base interface to SSL constructed types.
+ */
+interface Constructed
+{
+
+ /**
+ * Writes this structure's encoded form to the given output stream.
+ *
+ * @param out The output stream.
+ * @throws IOException If an I/O error occurs.
+ */
+ void write(OutputStream out) throws IOException;
+}
diff --git a/gnu/javax/net/ssl/provider/ContentType.java b/gnu/javax/net/ssl/provider/ContentType.java
new file mode 100644
index 000000000..336809467
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ContentType.java
@@ -0,0 +1,135 @@
+/* ContentType.java -- record layer content type.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * The content type enumeration, which marks packets in the record layer.
+ *
+ * <pre>enum { change_cipher_spec(20), alert(21), handshake(22),
+ * application_data(23), (255) } ContentType;</pre>
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+final class ContentType implements Enumerated
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ static final ContentType CLIENT_HELLO_V2 = new ContentType( 1);
+ static final ContentType CHANGE_CIPHER_SPEC = new ContentType(20);
+ static final ContentType ALERT = new ContentType(21);
+ static final ContentType HANDSHAKE = new ContentType(22);
+ static final ContentType APPLICATION_DATA = new ContentType(23);
+
+ private int value;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ private ContentType(int value)
+ {
+ this.value = value;
+ }
+
+ // Class methods.
+ // ------------------------------------------------------------------------
+
+ static final ContentType read(InputStream in) throws IOException
+ {
+ int value = in.read();
+ if (value == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ switch (value & 0xFF)
+ {
+ case 1: return CLIENT_HELLO_V2;
+ case 20: return CHANGE_CIPHER_SPEC;
+ case 21: return ALERT;
+ case 22: return HANDSHAKE;
+ case 23: return APPLICATION_DATA;
+ default: return new ContentType(value);
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return new byte[] { (byte) value };
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (o == null || !(o instanceof ContentType))
+ {
+ return false;
+ }
+ return ((ContentType) o).value == value;
+ }
+
+ public int hashCode()
+ {
+ return getValue();
+ }
+
+ public String toString()
+ {
+ switch (value)
+ {
+ case 1: return "v2_client_hello";
+ case 20: return "change_cipher_spec";
+ case 21: return "alert";
+ case 22: return "handshake";
+ case 23: return "application_data";
+ default: return "unknown(" + value + ")";
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Context.java b/gnu/javax/net/ssl/provider/Context.java
new file mode 100644
index 000000000..2bd7193f2
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Context.java
@@ -0,0 +1,334 @@
+/* Context.java -- SSLContext implementation.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.File;
+import java.io.InputStream;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStoreException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.UnrecoverableKeyException;
+import java.sql.SQLException;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContextSpi;
+import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+
+import gnu.javax.net.ssl.NullManagerParameters;
+import gnu.javax.net.ssl.SRPTrustManager;
+import gnu.javax.net.ssl.StaticTrustAnchors;
+
+/**
+ * This is Jessie's implementation of a {@link javax.net.ssl.SSLContext}
+ * engine, and is available under the algorithm names ``SSLv3'', ``SSL'',
+ * ``TLSv1'', and ``TLS''.
+ */
+public final class Context extends SSLContextSpi
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private SessionContext clientSessions;
+ private SessionContext serverSessions;
+ private X509KeyManager keyManager;
+ private X509TrustManager trustManager;
+ private SRPTrustManager srpTrustManager;
+ private SecureRandom random;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public Context()
+ {
+ String codec = Util.getSecurityProperty("jessie.clientSessionContext.codec");
+ String codecClass = null;
+ if (codec == null)
+ {
+ codec = "null";
+ }
+ if (codec.equalsIgnoreCase("xml"))
+ {
+ codecClass = "gnu.javax.net.ssl.provider.XMLSessionContext";
+ }
+ else if (codec.equalsIgnoreCase("jdbc"))
+ {
+ codecClass = "gnu.javax.net.ssl.provider.JDBCSessionContext";
+ }
+ else if (codec.equalsIgnoreCase("null"))
+ {
+ codecClass = "gnu.javax.net.ssl.provider.SessionContext";
+ }
+ else
+ {
+ throw new IllegalArgumentException("no such codec: " + codec);
+ }
+ try
+ {
+ ClassLoader cl = Context.class.getClassLoader();
+ if (cl == null)
+ {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+ clientSessions = (SessionContext) cl.loadClass(codecClass).newInstance();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ throw new IllegalArgumentException(ex.toString());
+ }
+
+ codec = Util.getSecurityProperty("jessie.serverSessionContext.codec");
+ if (codec == null)
+ {
+ codec = "null";
+ }
+ if (codec.equalsIgnoreCase("xml"))
+ {
+ codecClass = "gnu.javax.net.ssl.provider.XMLSessionContext";
+ }
+ else if (codec.equalsIgnoreCase("jdbc"))
+ {
+ codecClass = "gnu.javax.net.ssl.provider.JDBCSessionContext";
+ }
+ else if (codec.equalsIgnoreCase("null"))
+ {
+ codecClass = "gnu.javax.net.ssl.provider.SessionContext";
+ }
+ else
+ {
+ throw new IllegalArgumentException("no such codec: " + codec);
+ }
+ try
+ {
+ ClassLoader cl = Context.class.getClassLoader();
+ if (cl == null)
+ {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+ serverSessions = (SessionContext) cl.loadClass(codecClass).newInstance();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ throw new IllegalArgumentException(ex.toString());
+ }
+ }
+
+ // Engine methods.
+ // -------------------------------------------------------------------------
+
+ protected SSLSessionContext engineGetClientSessionContext()
+ {
+ return clientSessions;
+ }
+
+ protected SSLSessionContext engineGetServerSessionContext()
+ {
+ return serverSessions;
+ }
+
+ protected javax.net.ssl.SSLServerSocketFactory engineGetServerSocketFactory()
+ {
+ if (keyManager == null || (trustManager == null && srpTrustManager == null)
+ || random == null)
+ {
+ throw new IllegalStateException();
+ }
+ return new SSLServerSocketFactory(trustManager, srpTrustManager, keyManager,
+ random, serverSessions);
+ }
+
+ protected javax.net.ssl.SSLSocketFactory engineGetSocketFactory()
+ {
+ if (keyManager == null || trustManager == null || random == null)
+ {
+ throw new IllegalStateException();
+ }
+ return new SSLSocketFactory(trustManager, keyManager, random, clientSessions);
+ }
+
+ protected void engineInit(KeyManager[] keyManagers,
+ TrustManager[] trustManagers, SecureRandom random)
+ throws KeyManagementException
+ {
+ keyManager = null;
+ trustManager = null;
+ srpTrustManager = null;
+ if (keyManagers != null)
+ {
+ for (int i = 0; i < keyManagers.length; i++)
+ {
+ if (keyManagers[i] instanceof X509KeyManager)
+ {
+ keyManager = (X509KeyManager) keyManagers[i];
+ break;
+ }
+ }
+ }
+ if (keyManager == null)
+ {
+ keyManager = defaultKeyManager();
+ }
+ if (trustManagers != null)
+ {
+ for (int i = 0; i < trustManagers.length; i++)
+ {
+ if (trustManagers[i] instanceof X509TrustManager)
+ {
+ if (trustManager == null)
+ {
+ trustManager = (X509TrustManager) trustManagers[i];
+ }
+ }
+ else if (trustManagers[i] instanceof SRPTrustManager)
+ {
+ if (srpTrustManager == null)
+ {
+ srpTrustManager = (SRPTrustManager) trustManagers[i];
+ }
+ }
+ }
+ }
+ if (trustManager == null && srpTrustManager == null)
+ {
+ trustManager = defaultTrustManager();
+ }
+ if (random != null)
+ {
+ this.random = random;
+ }
+ else
+ {
+ this.random = defaultRandom();
+ }
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private X509KeyManager defaultKeyManager() throws KeyManagementException
+ {
+ KeyManagerFactory fact = null;
+ try
+ {
+ fact = KeyManagerFactory.getInstance("JessieX509", "Jessie");
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new KeyManagementException();
+ }
+ catch (NoSuchProviderException nspe)
+ {
+ throw new KeyManagementException();
+ }
+ try
+ {
+ fact.init(null, null);
+ return (X509KeyManager) fact.getKeyManagers()[0];
+ }
+ catch (NoSuchAlgorithmException nsae) { }
+ catch (KeyStoreException kse) { }
+ catch (UnrecoverableKeyException uke) { }
+ catch (IllegalStateException ise) { }
+
+ try
+ {
+ fact.init(new NullManagerParameters());
+ return (X509KeyManager) fact.getKeyManagers()[0];
+ }
+ catch (Exception shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen.toString());
+ }
+ }
+
+ private X509TrustManager defaultTrustManager() throws KeyManagementException
+ {
+ try
+ {
+ TrustManagerFactory fact =
+ TrustManagerFactory.getInstance("JessieX509", "Jessie");
+ fact.init(StaticTrustAnchors.CA_CERTS);
+ return (X509TrustManager) fact.getTrustManagers()[0];
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new KeyManagementException(nsae.toString());
+ }
+ catch (NoSuchProviderException nspe)
+ {
+ throw new KeyManagementException(nspe.toString());
+ }
+ catch (InvalidAlgorithmParameterException kse)
+ {
+ throw new KeyManagementException(kse.toString());
+ }
+ }
+
+ private SecureRandom defaultRandom() throws KeyManagementException
+ {
+ String alg = Util.getSecurityProperty("jessie.secure.random");
+ if (alg == null)
+ {
+ alg = "Fortuna";
+ }
+ SecureRandom rand = null;
+ try
+ {
+ rand = SecureRandom.getInstance(alg);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new KeyManagementException(nsae.toString());
+ }
+
+ return rand;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/DiffieHellman.java b/gnu/javax/net/ssl/provider/DiffieHellman.java
new file mode 100644
index 000000000..ad48c7959
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/DiffieHellman.java
@@ -0,0 +1,285 @@
+/* DiffieHellman.java -- Diffie-Hellman key exchange.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.math.BigInteger;
+import gnu.javax.crypto.key.dh.GnuDHPrivateKey;
+
+/**
+ * <p>Simple implementation of two-party Diffie-Hellman key agreement.</p>
+ *
+ * <p>The primes used in this class are from the following documents:</p>
+ *
+ * <ul>
+ * <li>D. Harkins and D. Carrel, "The Internet Key Exchange (IKE)", <a
+ * href="http://www.ietf.org/rfc/rfc2409.txt">RFC 2409</a>.</li>
+ * <li>T. Kivinen and M. Kojo, "More Modular
+ * Exponential (MODP) Diffie-Hellman groups for Internet Key Exchange
+ * (IKE)", <a href="http://www.ietf.org/rfc/rfc3526.txt">RFC
+ * 3526</a>.</li>
+ * </li>
+ *
+ * <p>The generator for all these primes is 2.</p>
+ */
+final class DiffieHellman
+{
+
+ // Class method.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Get the system's Diffie-Hellman parameters, in which <i>g</i> is 2
+ * and <i>p</i> is determined by the property
+ * <code>"jessie.keypool.dh.group"</code>. The default value for <i>p</i>
+ * is 18, corresponding to {@link #GROUP_18}.
+ */
+ static GnuDHPrivateKey getParams()
+ {
+ BigInteger p = DiffieHellman.GROUP_5;
+ String group = Util.getSecurityProperty("jessie.key.dh.group");
+ if (group != null)
+ {
+ group = group.trim();
+ if (group.equals("1"))
+ p = DiffieHellman.GROUP_1;
+ else if (group.equals("2"))
+ p = DiffieHellman.GROUP_2;
+ else if (group.equals("5"))
+ p = DiffieHellman.GROUP_5;
+ else if (group.equals("14"))
+ p = DiffieHellman.GROUP_14;
+ else if (group.equals("15"))
+ p = DiffieHellman.GROUP_15;
+ else if (group.equals("16"))
+ p = DiffieHellman.GROUP_16;
+ else if (group.equals("17"))
+ p = DiffieHellman.GROUP_17;
+ else if (group.equals("18"))
+ p = DiffieHellman.GROUP_18;
+ }
+ return new GnuDHPrivateKey(null, p, DH_G, null);
+ }
+
+ // Constants.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The generator for all Diffie Hellman groups below.
+ */
+ static final BigInteger DH_G = BigInteger.valueOf(2L);
+
+ /**
+ * p = 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 }
+ */
+ static final BigInteger GROUP_1 = new BigInteger("00" +
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 16);
+
+ /**
+ * p = 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }
+ */
+ static final BigInteger GROUP_2 = new BigInteger("00" +
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" +
+ "FFFFFFFFFFFFFFFF", 16);
+
+ /**
+ * This prime p = 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }.
+ */
+ static final BigInteger GROUP_5 = new BigInteger("00" +
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
+ "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16);
+
+ /**
+ * p = 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }.
+ */
+ static final BigInteger GROUP_14 = new BigInteger("00" +
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" +
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
+ "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16);
+
+ /**
+ * p = 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }.
+ */
+ static final BigInteger GROUP_15 = new BigInteger("00" +
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" +
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" +
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" +
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" +
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" +
+ "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", 16);
+
+ /**
+ * p = 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }.
+ */
+ static final BigInteger GROUP_16 = new BigInteger("00" +
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" +
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" +
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" +
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" +
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" +
+ "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" +
+ "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" +
+ "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" +
+ "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" +
+ "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" +
+ "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" +
+ "FFFFFFFFFFFFFFFF", 16);
+
+ static final BigInteger GROUP_17 = new BigInteger("00" +
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" +
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" +
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" +
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" +
+ "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" +
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" +
+ "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" +
+ "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" +
+ "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" +
+ "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" +
+ "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" +
+ "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" +
+ "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" +
+ "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" +
+ "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" +
+ "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" +
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" +
+ "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" +
+ "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" +
+ "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" +
+ "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" +
+ "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" +
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" +
+ "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" +
+ "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" +
+ "6DCC4024FFFFFFFFFFFFFFFF", 16);
+
+ /**
+ * p = 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 }.
+ *
+ * <p>This value, while quite large, is estimated to provide the equivalent
+ * cryptographic strength of a symmetric key between 190 and 320 bits.
+ */
+ static final BigInteger GROUP_18 = new BigInteger("00" +
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" +
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" +
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" +
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" +
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" +
+ "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" +
+ "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" +
+ "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" +
+ "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" +
+ "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" +
+ "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" +
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" +
+ "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" +
+ "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" +
+ "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" +
+ "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" +
+ "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" +
+ "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" +
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" +
+ "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" +
+ "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" +
+ "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" +
+ "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" +
+ "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" +
+ "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" +
+ "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" +
+ "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" +
+ "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" +
+ "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" +
+ "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" +
+ "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" +
+ "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" +
+ "60C980DD98EDD3DFFFFFFFFFFFFFFFFF", 16);
+
+}
diff --git a/gnu/javax/net/ssl/provider/DigestInputStream.java b/gnu/javax/net/ssl/provider/DigestInputStream.java
new file mode 100644
index 000000000..dd138b436
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/DigestInputStream.java
@@ -0,0 +1,103 @@
+/* DigestInputStream.java -- digesting input stream.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import gnu.java.security.hash.IMessageDigest;
+
+final class DigestInputStream extends FilterInputStream
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private IMessageDigest md5, sha;
+ private boolean digesting;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ DigestInputStream(InputStream in, IMessageDigest md5, IMessageDigest sha)
+ {
+ super(in);
+ if (md5 == null || sha == null)
+ throw new NullPointerException();
+ this.md5 = md5;
+ this.sha = sha;
+ digesting = true;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ void setDigesting(boolean digesting)
+ {
+ this.digesting = digesting;
+ }
+
+ public int read() throws IOException
+ {
+ int i = in.read();
+ if (digesting && i != -1)
+ {
+ md5.update((byte) i);
+ sha.update((byte) i);
+ }
+ return i;
+ }
+
+ public int read(byte[] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public int read(byte[] buf, int off, int len) throws IOException
+ {
+ int ret = in.read(buf, off, len);
+ if (digesting && ret != -1)
+ {
+ md5.update(buf, off, ret);
+ sha.update(buf, off, ret);
+ }
+ return ret;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/DigestOutputStream.java b/gnu/javax/net/ssl/provider/DigestOutputStream.java
new file mode 100644
index 000000000..f1548459e
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/DigestOutputStream.java
@@ -0,0 +1,107 @@
+/* DigestOutputStream.java -- digesting output stream.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import gnu.java.security.hash.IMessageDigest;
+
+final class DigestOutputStream extends FilterOutputStream
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private IMessageDigest md5, sha;
+ private boolean digesting;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ DigestOutputStream(OutputStream out, IMessageDigest md5, IMessageDigest sha)
+ {
+ super(out);
+ this.md5 = md5;
+ this.sha = sha;
+ digesting = true;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ void setDigesting(boolean digesting)
+ {
+ this.digesting = digesting;
+ }
+
+ public void write(int b) throws IOException
+ {
+ if (digesting)
+ {
+ md5.update((byte) b);
+ sha.update((byte) b);
+ }
+ out.write(b);
+ }
+
+ public void write(byte[] buf) throws IOException
+ {
+ write(buf, 0, buf.length);
+ }
+
+ public void write(byte[] buf, int off, int len) throws IOException
+ {
+ if (buf == null)
+ {
+ throw new NullPointerException();
+ }
+ if (off < 0 || len < 0 || off+len > buf.length)
+ {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (digesting)
+ {
+ md5.update(buf, off, len);
+ sha.update(buf, off, len);
+ }
+ out.write(buf, off, len);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Enumerated.java b/gnu/javax/net/ssl/provider/Enumerated.java
new file mode 100644
index 000000000..8875addab
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Enumerated.java
@@ -0,0 +1,79 @@
+/* Enumerated.java -- Interface to enumerated types.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+/**
+ * An enumerated type in the SSL protocols. Enumerated values take on
+ * one of a set of possible numeric values, which are not specifically
+ * ordered, and may be extensible to a maximum value.
+ *
+ * <pre>enum { e1(v1), e2(v2), ... [[, (n) ]] }</pre>
+ *
+ * <p>Enumerated types are encoded as big-endian multibyte integers,
+ * which take up the least possible number of bytes. Thus, an
+ * enumeration with up to 255 values will be encoded in a single byte,
+ * and so on.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+interface Enumerated
+{
+
+ /**
+ * Returns the encoded value of this enumerated value, which is
+ * appropriate to send over-the-wire.
+ *
+ * @return The encoded value.
+ */
+ byte[] getEncoded();
+
+ /**
+ * Returns the numeric value of this enumerated value.
+ *
+ * @return The numeric value.
+ */
+ int getValue();
+
+ /**
+ * Returns a string representation of this enumerated value.
+ *
+ * @return The string.
+ */
+ String toString();
+}
diff --git a/gnu/javax/net/ssl/provider/Extension.java b/gnu/javax/net/ssl/provider/Extension.java
new file mode 100644
index 000000000..1c79dd5cb
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Extension.java
@@ -0,0 +1,214 @@
+/* Extension.java -- A TLS hello extension.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+final class Extension implements Constructed
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final Type type;
+ private final byte[] value;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ Extension(Type type, byte[] value)
+ {
+ if (type == null || value == null)
+ {
+ throw new NullPointerException();
+ }
+ this.type = type;
+ this.value = value;
+ }
+
+ // Class method.
+ // -------------------------------------------------------------------------
+
+ static Extension read(InputStream in) throws IOException
+ {
+ Type t = Type.read(in);
+ int len = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
+ byte[] v = new byte[len];
+ int count = 0;
+ while (count < len)
+ {
+ int l = in.read(v, count, len - count);
+ if (l == -1)
+ {
+ throw new EOFException("unexpected end of extension");
+ }
+ count += l;
+ }
+ return new Extension(t, v);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ out.write(type.getEncoded());
+ out.write(value.length >>> 8 & 0xFF);
+ out.write(value.length & 0xFF);
+ out.write(value);
+ }
+
+ Type getType()
+ {
+ return type;
+ }
+
+ byte[] getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ out.println(" type = " + type + ";");
+ out.println(" value =");
+ out.println(Util.hexDump(value, " "));
+ out.println("} Extension;");
+ return str.toString();
+ }
+
+ // Inner class.
+ // -------------------------------------------------------------------------
+
+ static final class Type implements Enumerated
+ {
+
+ // Constants and fields.
+ // -----------------------------------------------------------------------
+
+ static final Type SERVER_NAME = new Type(0);
+ static final Type MAX_FRAGMENT_LENGTH = new Type(1);
+ static final Type CLIENT_CERTIFICATE_URL = new Type(2);
+ static final Type TRUSTED_CA_KEYS = new Type(3);
+ static final Type TRUNCATED_HMAC = new Type(4);
+ static final Type STATUS_REQUEST = new Type(5);
+ static final Type SRP = new Type(6);
+ static final Type CERT_TYPE = new Type(7);
+
+ private final int value;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ private Type(int value)
+ {
+ this.value = value;
+ }
+
+ // Class methods.
+ // -----------------------------------------------------------------------
+
+ static Type read(InputStream in) throws IOException
+ {
+ int i = in.read();
+ if (i == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ int value = (i & 0xFF) << 8;
+ i = in.read();
+ if (i == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ value |= i & 0xFF;
+ switch (value)
+ {
+ case 0: return SERVER_NAME;
+ case 1: return MAX_FRAGMENT_LENGTH;
+ case 2: return CLIENT_CERTIFICATE_URL;
+ case 3: return TRUSTED_CA_KEYS;
+ case 4: return TRUNCATED_HMAC;
+ case 5: return STATUS_REQUEST;
+ case 6: return SRP;
+ case 7: return CERT_TYPE;
+ default: return new Type(value);
+ }
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return new byte[] {
+ (byte) (value >>> 8 & 0xFF), (byte) (value & 0xFF)
+ };
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ switch (value)
+ {
+ case 0: return "server_name";
+ case 1: return "max_fragment_length";
+ case 2: return "client_certificate_url";
+ case 3: return "trusted_ca_keys";
+ case 4: return "truncated_hmac";
+ case 5: return "status_request";
+ case 6: return "srp";
+ case 7: return "cert_type";
+ default: return "unknown(" + value + ")";
+ }
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Extensions.java b/gnu/javax/net/ssl/provider/Extensions.java
new file mode 100644
index 000000000..9ed9619f0
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Extensions.java
@@ -0,0 +1,159 @@
+/* Extensions.java -- various static extension utilities.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.security.auth.x500.X500Principal;
+
+import gnu.java.security.x509.X500DistinguishedName;
+
+final class Extensions
+{
+
+ // Constants.
+ // -------------------------------------------------------------------------
+
+ private static final Integer _512 = new Integer(512),
+ _1024 = new Integer(1024), _2048 = new Integer(2048),
+ _4096 = new Integer(4096);
+
+ // Class methods only.
+ private Extensions() { }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static List getServerName(Extension ex)
+ {
+ LinkedList l = new LinkedList();
+ byte[] buf = ex.getValue();
+ int pos = 0;
+ try
+ {
+ while (pos < buf.length)
+ {
+ if (buf[pos++] != 0)
+ break;
+ int len = (buf[pos++] & 0xFF) << 8;
+ len |= buf[pos++] & 0xFF;
+ l.add(new String(buf, pos, len, "UTF-8"));
+ pos += len;
+ }
+ }
+ catch (Exception x)
+ {
+ }
+ return Collections.unmodifiableList(l);
+ }
+
+ static List getClientCertTypes(Extension ex) throws IOException
+ {
+ List l = new LinkedList();
+ ByteArrayInputStream in = new ByteArrayInputStream(ex.getValue());
+ final int len = in.read() & 0xFF;
+ for (int i = 0; i < len; i++)
+ {
+ l.add(CertificateType.read(in));
+ }
+ return Collections.unmodifiableList(l);
+ }
+
+ static CertificateType getServerCertType(Extension ex) throws IOException
+ {
+ return CertificateType.read(new ByteArrayInputStream(ex.getValue()));
+ }
+
+ static Integer getMaxFragmentLength(Extension ex)
+ {
+ switch (ex.getValue()[0] & 0xFF)
+ {
+ case 1: return _512;
+ case 2: return _1024;
+ case 3: return _2048;
+ case 4: return _4096;
+ }
+ throw new IllegalArgumentException();
+ }
+
+ static Object[] getTrustedCA(Extension ex)
+ {
+ byte[] buf = ex.getValue();
+ int type = buf[0] & 0xFF;
+ try
+ {
+ switch (type)
+ {
+ case 0:
+ return new Object[] { new Integer(type), null };
+ case 1:
+ case 3:
+ return new Object[] { new Integer(type),
+ Util.trim(buf, 1, 20) };
+ case 2:
+ return new Object[] { new Integer(type),
+ new X500Principal(Util.trim(buf, 1, 20)) };
+ }
+ }
+ catch (Exception x)
+ {
+ }
+ throw new IllegalArgumentException();
+ }
+
+ static String getSRPUsername(Extension ex)
+ {
+ int len = ex.getValue()[0] & 0xFF;
+ if (len > ex.getValue().length - 1)
+ throw new IllegalArgumentException();
+ try
+ {
+ return new String(ex.getValue(), 1, len, "UTF-8");
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ throw new Error(uee.toString());
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Finished.java b/gnu/javax/net/ssl/provider/Finished.java
new file mode 100644
index 000000000..8b9c220a5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Finished.java
@@ -0,0 +1,143 @@
+/* Finished.java -- SSL Finished message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+final class Finished implements Handshake.Body
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ /** TLSv1.x verify data. */
+ private final byte[] verifyData;
+
+ /** SSLv3 message digest pair. */
+ private final byte[] md5, sha;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ Finished(byte[] verifyData)
+ {
+ this.verifyData = verifyData;
+ md5 = sha = null;
+ }
+
+ Finished(byte[] md5, byte[] sha)
+ {
+ this.md5 = md5;
+ this.sha = sha;
+ verifyData = null;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static Finished read(InputStream in, CipherSuite suite)
+ throws IOException
+ {
+ DataInputStream din = new DataInputStream(in);
+ if (suite.getVersion().equals(ProtocolVersion.SSL_3))
+ {
+ byte[] md5 = new byte[16];
+ byte[] sha = new byte[20];
+ din.readFully(md5);
+ din.readFully(sha);
+ return new Finished(md5, sha);
+ }
+ else
+ {
+ byte[] buf = new byte[12];
+ din.readFully(buf);
+ return new Finished(buf);
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ if (verifyData != null)
+ out.write(verifyData);
+ else
+ {
+ out.write(md5);
+ out.write(sha);
+ }
+ }
+
+ byte[] getVerifyData()
+ {
+ return verifyData;
+ }
+
+ byte[] getMD5Hash()
+ {
+ return md5;
+ }
+
+ byte[] getSHAHash()
+ {
+ return sha;
+ }
+
+ public String toString()
+ {
+ String nl = System.getProperty("line.separator");
+ if (verifyData != null)
+ {
+ return "struct {" + nl +
+ " verifyData = " + Util.toHexString(verifyData, ':') + ";" + nl +
+ "} Finished;" + nl;
+ }
+ else
+ {
+ return "struct {" + nl +
+ " md5Hash = " + Util.toHexString(md5, ':') + ";" + nl +
+ " shaHash = " + Util.toHexString(sha, ':') + ";" + nl +
+ "} Finished;" + nl;
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/GNUSecurityParameters.java b/gnu/javax/net/ssl/provider/GNUSecurityParameters.java
new file mode 100644
index 000000000..a04c3fd5c
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/GNUSecurityParameters.java
@@ -0,0 +1,490 @@
+/* GNUSecurityParameters.java -- SSL security parameters.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import java.security.SecureRandom;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+import javax.net.ssl.SSLException;
+
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mode.IMode;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+/**
+ * This class implements the {@link SecurityParameters} interface, using the
+ * GNU Crypto interface for ciphers and macs, and the JZlib package for
+ * record compression.
+ */
+class GNUSecurityParameters implements SecurityParameters
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private static final boolean DEBUG_RECORD_LAYER = false;
+ private static final PrintWriter debug = new PrintWriter (System.err, true);
+
+ /**
+ * The CBC block cipher, if any.
+ */
+ IMode inCipher, outCipher;
+
+ /**
+ * The RC4 PRNG, if any.
+ */
+ IRandom inRandom, outRandom;
+
+ /**
+ * The MAC algorithm.
+ */
+ IMac inMac, outMac;
+
+ long inSequence, outSequence;
+ Session session;
+ ProtocolVersion version;
+ int fragmentLength;
+ private Inflater inflater;
+ private Deflater deflater;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ GNUSecurityParameters (Session session)
+ {
+ inSequence = 0;
+ outSequence = 0;
+ this.session = session;
+ fragmentLength = 16384;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void reset()
+ {
+ inSequence = 0L;
+ outSequence = 0L;
+ inCipher = null;
+ outCipher = null;
+ inMac = null;
+ outMac = null;
+ inRandom = null;
+ outRandom = null;
+ deflater = null;
+ inflater = null;
+ }
+
+ public ProtocolVersion getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(ProtocolVersion version)
+ {
+ this.version = version;
+ }
+
+ public void setInCipher(Object inCipher)
+ {
+ if (inCipher instanceof IMode)
+ {
+ this.inCipher = (IMode) inCipher;
+ inRandom = null;
+ }
+ else
+ {
+ inRandom = (IRandom) inCipher;
+ this.inCipher = null;
+ }
+ }
+
+ public void setOutCipher(Object outCipher)
+ {
+ if (outCipher instanceof IMode)
+ {
+ this.outCipher = (IMode) outCipher;
+ outRandom = null;
+ }
+ else
+ {
+ outRandom = (IRandom) outCipher;
+ this.outCipher = null;
+ }
+ }
+
+ public void setInMac(Object inMac)
+ {
+ this.inMac = (IMac) inMac;
+ inSequence = 0L;
+ }
+
+ public void setOutMac(Object outMac)
+ {
+ this.outMac = (IMac) outMac;
+ outSequence = 0L;
+ }
+
+ public void setDeflating (boolean deflate)
+ {
+ if (deflate)
+ {
+ if (deflater == null)
+ deflater = new Deflater();
+ }
+ else
+ deflater = null;
+ }
+
+ public void setInflating (boolean inflate)
+ {
+ if (inflate)
+ {
+ if (inflater == null)
+ inflater = new Inflater();
+ }
+ else
+ inflater = null;
+ }
+
+ public int getFragmentLength()
+ {
+ return fragmentLength;
+ }
+
+ public void setFragmentLength (int fragmentLength)
+ {
+ this.fragmentLength = fragmentLength;
+ }
+
+ /**
+ * Decrypt, verify, and decompress a fragment, returning the transformed
+ * fragment.
+ *
+ * @param fragment The fragment to decrypt.
+ * @param version The protocol version of the fragment's record.
+ * @param type The content type of the record.
+ * @return The decrypted fragment.
+ * @throws MacException If the MAC could not be verified.
+ * @throws OverflowException If the inflated data is too large.
+ * @throws SSLException If decompressing fails.
+ */
+ public synchronized byte[] decrypt (byte[] fragment, ProtocolVersion version,
+ ContentType type)
+ throws MacException, OverflowException, SSLException
+ {
+ boolean badPadding = false;
+
+ // Decrypt the ciphertext, if it is encrypted.
+ if (inCipher != null)
+ {
+ int bs = inCipher.currentBlockSize ();
+ for (int i = 0; i < fragment.length; i += bs)
+ {
+ inCipher.update (fragment, i, fragment, i);
+ }
+ int padLen = fragment[fragment.length-1] & 0xFF;
+ int len = fragment.length - padLen - 1;
+ if (version == ProtocolVersion.SSL_3)
+ {
+ // SSLv3 requires that the padding length not exceed the
+ // cipher's block size.
+ if (padLen >= bs)
+ {
+ badPadding = true;
+ }
+ }
+ else
+ {
+ for (int i = len; i < fragment.length; i++)
+ {
+ // If the TLS padding is wrong, throw a MAC exception below.
+ if ((fragment[i] & 0xFF) != padLen)
+ {
+ badPadding = true;
+ }
+ }
+ }
+ fragment = Util.trim (fragment, len);
+ }
+ else if (inRandom != null)
+ {
+ transformRC4 (fragment, 0, fragment.length, fragment, 0, inRandom);
+ }
+
+ // Check the MAC.
+ if (inMac != null)
+ {
+ inMac.update ((byte) (inSequence >>> 56));
+ inMac.update ((byte) (inSequence >>> 48));
+ inMac.update ((byte) (inSequence >>> 40));
+ inMac.update ((byte) (inSequence >>> 32));
+ inMac.update ((byte) (inSequence >>> 24));
+ inMac.update ((byte) (inSequence >>> 16));
+ inMac.update ((byte) (inSequence >>> 8));
+ inMac.update ((byte) inSequence);
+ inMac.update ((byte) type.getValue());
+ if (version != ProtocolVersion.SSL_3)
+ {
+ inMac.update ((byte) version.getMajor());
+ inMac.update ((byte) version.getMinor());
+ }
+ int macLen = inMac.macSize ();
+ int fragLen = fragment.length - macLen;
+ inMac.update ((byte) (fragLen >>> 8));
+ inMac.update ((byte) fragLen);
+ inMac.update (fragment, 0, fragLen);
+ byte[] mac = inMac.digest ();
+ inMac.reset ();
+ for (int i = 0; i < macLen; i++)
+ {
+ if (fragment[i + fragLen] != mac[i])
+ {
+ throw new MacException();
+ }
+ }
+ if (badPadding)
+ {
+ throw new MacException();
+ }
+ fragment = Util.trim (fragment, fragLen);
+ }
+
+ if (inflater != null)
+ {
+ byte[] buf = new byte[1024];
+ ByteArrayOutputStream bout = new ByteArrayOutputStream (fragment.length << 1);
+ inflater.setInput (fragment);
+ int len;
+ try
+ {
+ while ((len = inflater.inflate (buf)) > 0)
+ {
+ bout.write (buf, 0, len);
+ if (bout.size() > fragmentLength + 1024)
+ throw new OverflowException ("inflated data too large");
+ }
+ }
+ catch (DataFormatException dfe)
+ {
+ throw new SSLException (String.valueOf (dfe));
+ }
+ fragment = bout.toByteArray();
+ inflater.reset();
+ }
+
+ inSequence++;
+ return fragment;
+ }
+
+ /**
+ * Compress, MAC, encrypt, and write a record. The fragment of the
+ * record is taken from <i>buf</i> as <i>len</i> bytes starting at
+ * <i>offset</i>. <i>len</i> <b>must</b> be smaller than or equal to
+ * the configured fragment length.
+ *
+ * @param buf The fragment bytes.
+ * @param off The offset from whence to read.
+ * @param len The size of the fragment.
+ * @param type The content-type for this record.
+ * @param out The output stream to write the record to.
+ * @throws IOException If an I/O error occurs.
+ * @throws SSLException If compression fails.
+ * @throws OverflowException If compression inflates the data beyond
+ * the fragment length plus 1024 bytes.
+ */
+ public synchronized byte[] encrypt (byte[] buf, int off, int len,
+ ContentType type)
+ throws SSLException, OverflowException
+ {
+ // If we are compressing, do it.
+ if (deflater != null)
+ {
+ byte[] buf2 = new byte[1024];
+ ByteArrayOutputStream bout = new ByteArrayOutputStream (len >>> 1);
+ deflater.setInput (buf, off, len);
+ deflater.finish();
+ len = 0;
+ while ((len = deflater.deflate (buf2)) > 0)
+ bout.write (buf2, 0, len);
+ // This should technically never happen for zlib.
+ if (bout.size() > fragmentLength + 1024)
+ throw new OverflowException ("deflated data too large");
+ buf = bout.toByteArray();
+ off = 0;
+ len = buf.length;
+ deflater.reset();
+ }
+
+ // If there is a MAC, compute it.
+ byte[] mac = new byte[0];
+ if (outMac != null)
+ {
+ outMac.update((byte) (outSequence >>> 56));
+ outMac.update((byte) (outSequence >>> 48));
+ outMac.update((byte) (outSequence >>> 40));
+ outMac.update((byte) (outSequence >>> 32));
+ outMac.update((byte) (outSequence >>> 24));
+ outMac.update((byte) (outSequence >>> 16));
+ outMac.update((byte) (outSequence >>> 8));
+ outMac.update((byte) outSequence);
+ outMac.update((byte) type.getValue());
+ if (version != ProtocolVersion.SSL_3)
+ {
+ outMac.update((byte) version.getMajor());
+ outMac.update((byte) version.getMinor());
+ }
+ outMac.update((byte) (len >>> 8));
+ outMac.update((byte) len);
+ outMac.update(buf, off, len);
+ mac = outMac.digest();
+ outMac.reset();
+ }
+ outSequence++;
+
+ // Compute padding if needed.
+ byte[] pad = new byte[0];
+ if (outCipher != null)
+ {
+ int padLen = outCipher.currentBlockSize() -
+ ((len + mac.length + 1) % outCipher.currentBlockSize());
+ // Use a random amount of padding if the protocol is TLS.
+ if (version != ProtocolVersion.SSL_3 && session.random != null)
+ {
+ padLen += (Math.abs(session.random.nextInt ()) & 7) *
+ outCipher.currentBlockSize();
+ while (padLen > 255)
+ {
+ padLen -= outCipher.currentBlockSize();
+ }
+ }
+ pad = new byte[padLen+1];
+ Arrays.fill (pad, (byte) padLen);
+ }
+
+ // Write the record header.
+ final int fraglen = len + mac.length + pad.length;
+
+ // Encrypt and write the fragment.
+ if (outCipher != null)
+ {
+ byte[] buf2 = new byte[fraglen];
+ System.arraycopy (buf, off, buf2, 0, len);
+ System.arraycopy (mac, 0, buf2, len, mac.length);
+ System.arraycopy (pad, 0, buf2, len + mac.length, pad.length);
+ int bs = outCipher.currentBlockSize ();
+ for (int i = 0; i < fraglen; i += bs)
+ {
+ outCipher.update (buf2, i, buf2, i);
+ }
+ return buf2;
+ }
+ else if (outRandom != null)
+ {
+ byte[] buf2 = new byte[fraglen];
+ transformRC4 (buf, off, len, buf2, 0, outRandom);
+ transformRC4 (mac, 0, mac.length, buf2, len, outRandom);
+ return buf2;
+ }
+ else
+ {
+ if (mac.length == 0)
+ {
+ return Util.trim (buf, off, len);
+ }
+ else
+ {
+ return Util.concat (Util.trim (buf, off, len), mac);
+ }
+ }
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Encrypt/decrypt a byte array with the RC4 stream cipher.
+ *
+ * @param in The input data.
+ * @param off The input offset.
+ * @param len The number of bytes to transform.
+ * @param out The output buffer.
+ * @param outOffset The offest into the output buffer.
+ * @param random The ARCFOUR PRNG.
+ */
+ private static void transformRC4(byte[] in, int off, int len,
+ byte[] out, int outOffset, IRandom random)
+ {
+ if (random == null)
+ {
+ throw new IllegalStateException();
+ }
+ if (in == null || out == null)
+ {
+ throw new NullPointerException();
+ }
+ if (off < 0 || off + len > in.length ||
+ outOffset < 0 || outOffset + len > out.length)
+ {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ try
+ {
+ for (int i = 0; i < len; i++)
+ {
+ out[outOffset+i] = (byte) (in[off+i] ^ random.nextByte());
+ }
+ }
+ catch (LimitReachedException cannotHappen)
+ {
+ throw new Error(cannotHappen.toString());
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Handshake.java b/gnu/javax/net/ssl/provider/Handshake.java
new file mode 100644
index 000000000..ef9e72381
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Handshake.java
@@ -0,0 +1,440 @@
+/* Handshake.java -- SSL handshake message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import java.security.PublicKey;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import javax.net.ssl.SSLProtocolException;
+
+final class Handshake implements Constructed
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private static final buffer BUF = new buffer();
+
+ private final Type type;
+ private final Body body;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ Handshake(Type type, Body body)
+ {
+ this.type = type;
+ this.body = body;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static Handshake read(byte[] buffer) throws IOException
+ {
+ return read(new ByteArrayInputStream(buffer));
+ }
+
+ static Handshake read(byte[] buffer, CipherSuite suite, PublicKey key)
+ throws IOException
+ {
+ return read(new ByteArrayInputStream(buffer), suite, key);
+ }
+
+ static Handshake read(InputStream in) throws IOException
+ {
+ return read(in, null, null);
+ }
+
+ static Handshake read(InputStream in, CipherSuite suite, PublicKey key)
+ throws IOException
+ {
+ return read(in, suite, key, null);
+ }
+
+ static Handshake read(InputStream in, CertificateType certType)
+ throws IOException
+ {
+ return read(in, null, null, certType);
+ }
+
+ static Handshake read(InputStream in, CipherSuite suite, PublicKey key,
+ CertificateType certType)
+ throws IOException
+ {
+ Type type = Type.read(in);
+ byte[] lenbuf = new byte[3];
+ in.read(lenbuf);
+ int len = (lenbuf[0] & 0xFF) << 16 | (lenbuf[1] & 0xFF) << 8
+ | (lenbuf[2] & 0xFF);
+ Body body = null;
+ if (type == Type.HELLO_REQUEST)
+ {
+ body = null;
+ }
+ else if (type == Type.CLIENT_HELLO)
+ {
+ // Most likely a V2 hello. If the first byte is 0x30, and if this
+ // is not a V2 client hello, then it is a V3 client hello with
+ // at least 1.5 million cipher specs, which is unlikely.
+ if (lenbuf[0] == 3 && (lenbuf[1] >= 0 && lenbuf[1] <= 2))
+ {
+ ProtocolVersion vers = null;
+ switch (lenbuf[1])
+ {
+ case 0:
+ vers = ProtocolVersion.SSL_3;
+ break;
+ case 1:
+ vers = ProtocolVersion.TLS_1;
+ break;
+ case 2:
+ vers = ProtocolVersion.TLS_1_1;
+ break;
+ }
+ int specLen = (lenbuf[2] & 0xFF) << 8 | (in.read() & 0xFF);
+ int idLen = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
+ int chalLen = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
+
+ ArrayList suites = new ArrayList(specLen / 3);
+ for (int i = 0; i < specLen; i += 3)
+ {
+ if (in.read() == 0)
+ {
+ suites.add(CipherSuite.read(in).resolve(vers));
+ }
+ else
+ {
+ in.read();
+ in.read();
+ }
+ }
+ byte[] id = new byte[idLen];
+ in.read(id);
+ byte[] challenge = new byte[chalLen];
+ in.read(challenge);
+ if (challenge.length > 32)
+ challenge = Util.trim(challenge, 32);
+ else if (challenge.length < 32)
+ {
+ byte[] b = new byte[32];
+ System.arraycopy(challenge, 0, b, b.length - challenge.length,
+ challenge.length);
+ challenge = b;
+ }
+ int time = (challenge[0] & 0xFF) << 24 | (challenge[1] & 0xFF) << 16
+ | (challenge[2] & 0xFF) << 8 | (challenge[3] & 0xFF);
+ Random rand = new Random(time, Util.trim(challenge, 4, 28));
+ return new Handshake(Handshake.Type.CLIENT_HELLO,
+ new ClientHello(vers, rand, id, suites,
+ Collections.singletonList(CompressionMethod.NULL)));
+ }
+ // Since hello messages may contain extensions, we read the whole
+ // thing here.
+ byte[] buf = new byte[len];
+ int count = 0;
+ while (count < len)
+ {
+ int l = in.read(buf, count, len - count);
+ if (l == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ count += l;
+ }
+ body = ClientHello.read(new ByteArrayInputStream(buf));
+ }
+ else if (type == Type.SERVER_HELLO)
+ {
+ byte[] buf = new byte[len];
+ int count = 0;
+ while (count < len)
+ {
+ int l = in.read(buf, count, len - count);
+ if (l == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ count += l;
+ }
+ body = ServerHello.read(new ByteArrayInputStream(buf));
+ }
+ else if (type == Type.CERTIFICATE)
+ {
+ body = Certificate.read(in, certType);
+ }
+ else if (type == Type.SERVER_KEY_EXCHANGE)
+ {
+ body = ServerKeyExchange.read(in, suite, key);
+ }
+ else if (type == Type.CERTIFICATE_REQUEST)
+ {
+ body = CertificateRequest.read(in);
+ }
+ else if (type == Type.CERTIFICATE_VERIFY)
+ {
+ body = (CertificateVerify) CertificateVerify.read(in, suite, key);
+ }
+ else if (type == Type.CLIENT_KEY_EXCHANGE)
+ {
+ body = ClientKeyExchange.read(in, suite, key);
+ }
+ else if (type == Type.SERVER_HELLO_DONE)
+ {
+ body = null;
+ }
+ else if (type == Type.FINISHED)
+ {
+ body = Finished.read(in, suite);
+ }
+ else
+ {
+ throw new SSLProtocolException("unknown HandshakeType: " +
+ type.getValue());
+ }
+
+ return new Handshake(type, body);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int write(OutputStream out, ProtocolVersion version)
+ throws IOException
+ {
+ out.write(type.getValue());
+ if (body == null)
+ {
+ out.write(0);
+ out.write(0);
+ out.write(0);
+ return 4;
+ }
+ else
+ {
+ ByteArrayOutputStream bout = BUF.getBuffer();
+ bout.reset();
+ if (body instanceof ServerKeyExchange)
+ {
+ ((ServerKeyExchange) body).write(bout, version);
+ }
+ else if (body instanceof ClientKeyExchange)
+ {
+ ((ClientKeyExchange) body).write(bout, version);
+ }
+ else if (body instanceof CertificateVerify)
+ {
+ ((CertificateVerify) body).write(bout, version);
+ }
+ else
+ {
+ body.write(bout);
+ }
+ out.write(bout.size() >>> 16 & 0xFF);
+ out.write(bout.size() >>> 8 & 0xFF);
+ out.write(bout.size() & 0xFF);
+ bout.writeTo(out);
+ return 4 + bout.size();
+ }
+ }
+
+ Type getType()
+ {
+ return type;
+ }
+
+ Body getBody()
+ {
+ return body;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ String nl = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+ out.println("struct {");
+ out.println(" type = " + type + ";");
+ if (body != null)
+ {
+ BufferedReader r = new BufferedReader(new StringReader(body.toString()));
+ String s;
+ try
+ {
+ while ((s = r.readLine()) != null)
+ {
+ out.print(" ");
+ out.println(s);
+ }
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ out.println("} Handshake;");
+ return str.toString();
+ }
+
+ // Inner class.
+ // -------------------------------------------------------------------------
+
+ static interface Body extends Constructed
+ {
+ }
+
+ static class Type implements Enumerated
+ {
+
+ // Constants and fields.
+ // -----------------------------------------------------------------------
+
+ public static final Type
+ HELLO_REQUEST = new Type( 0), CLIENT_HELLO = new Type( 1),
+ SERVER_HELLO = new Type( 2), CERTIFICATE = new Type(11),
+ SERVER_KEY_EXCHANGE = new Type(12), CERTIFICATE_REQUEST = new Type(13),
+ SERVER_HELLO_DONE = new Type(14), CERTIFICATE_VERIFY = new Type(15),
+ CLIENT_KEY_EXCHANGE = new Type(16), FINISHED = new Type(20),
+ CERTIFICATE_URL = new Type(21), CERTIFICATE_STATUS = new Type(22);
+
+ private final int value;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ private Type(int value)
+ {
+ this.value = value;
+ }
+
+ // Class methods.
+ // -----------------------------------------------------------------------
+
+ public static Type read(InputStream in) throws IOException
+ {
+ int i = in.read();
+ if (i == -1)
+ {
+ throw new EOFException("unexpected end of input stream");
+ }
+ switch (i & 0xFF)
+ {
+ case 0: return HELLO_REQUEST;
+ case 1: return CLIENT_HELLO;
+ case 2: return SERVER_HELLO;
+ case 11: return CERTIFICATE;
+ case 12: return SERVER_KEY_EXCHANGE;
+ case 13: return CERTIFICATE_REQUEST;
+ case 14: return SERVER_HELLO_DONE;
+ case 15: return CERTIFICATE_VERIFY;
+ case 16: return CLIENT_KEY_EXCHANGE;
+ case 20: return FINISHED;
+ case 21: return CERTIFICATE_URL;
+ case 22: return CERTIFICATE_STATUS;
+ default: return new Type(i);
+ }
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return new byte[] { (byte) value };
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ switch (value)
+ {
+ case 0: return "hello_request";
+ case 1: return "client_hello";
+ case 2: return "server_hello";
+ case 11: return "certificate";
+ case 12: return "server_key_exchange";
+ case 13: return "certificate_request";
+ case 14: return "server_hello_done";
+ case 15: return "certificate_verify";
+ case 16: return "client_key_exchange";
+ case 20: return "finished";
+ case 21: return "certificate_url";
+ case 22: return "certificate_status";
+ default: return "unknown(" + value + ")";
+ }
+ }
+ }
+
+ private static class buffer extends ThreadLocal
+ {
+ static final int SIZE = 2048;
+
+ protected Object initialValue()
+ {
+ return new ByteArrayOutputStream(SIZE);
+ }
+
+ ByteArrayOutputStream getBuffer()
+ {
+ return (ByteArrayOutputStream) get();
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/JCESecurityParameters.java b/gnu/javax/net/ssl/provider/JCESecurityParameters.java
new file mode 100644
index 000000000..6663c97b5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/JCESecurityParameters.java
@@ -0,0 +1,307 @@
+/* JCESecurityParameters.java -- JCE-based security parameters.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.ByteArrayOutputStream;
+
+import java.util.Arrays;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.Mac;
+
+import javax.net.ssl.SSLException;
+
+class JCESecurityParameters implements SecurityParameters
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private Cipher inCipher, outCipher;
+ private Mac inMac, outMac;
+ private Inflater inflater;
+ private Deflater deflater;
+ private int fragmentLength;
+ private long inSequence, outSequence;
+ private ProtocolVersion version;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ JCESecurityParameters ()
+ {
+ fragmentLength = 16384;
+ inSequence = 0L;
+ outSequence = 0L;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void reset()
+ {
+ inCipher = null;
+ outCipher = null;
+ inMac = null;
+ outMac = null;
+ deflater = null;
+ inflater = null;
+ }
+
+ public void setInCipher (Object inCipher)
+ {
+ this.inCipher = (Cipher) inCipher;
+ }
+
+ public void setOutCipher (Object outCipher)
+ {
+ this.outCipher = (Cipher) outCipher;
+ }
+
+ public void setInMac (Object inMac)
+ {
+ this.inMac = (Mac) inMac;
+ inSequence = 0L;
+ }
+
+ public void setOutMac (Object outMac)
+ {
+ this.outMac = (Mac) outMac;
+ outSequence = 0L;
+ }
+
+ public void setDeflating (boolean deflate)
+ {
+ if (deflate)
+ {
+ if (deflater == null)
+ deflater = new Deflater();
+ }
+ else
+ deflater = null;
+ }
+
+ public void setInflating (boolean inflate)
+ {
+ if (inflate)
+ {
+ if (inflater == null)
+ inflater = new Inflater();
+ }
+ else
+ inflater = null;
+ }
+
+ public int getFragmentLength()
+ {
+ return fragmentLength;
+ }
+
+ public void setFragmentLength (int fragmentLength)
+ {
+ this.fragmentLength = fragmentLength;
+ }
+
+ public ProtocolVersion getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion (ProtocolVersion version)
+ {
+ this.version = version;
+ }
+
+ public synchronized byte[] decrypt (byte[] fragment, ProtocolVersion version,
+ ContentType type)
+ throws MacException, OverflowException, SSLException
+ {
+ boolean badpad = false;
+ if (inCipher != null)
+ {
+ // We imagine that the JCE would be used in cases where hardware
+ // acceleration is available, since it isn't really that useful for
+ // pure Java crypto. We decrypt (and encrypt, below) in one go
+ // to minimize (potential) calls to native methods.
+ try
+ {
+ fragment = inCipher.doFinal (fragment);
+ }
+ catch (BadPaddingException bpe)
+ {
+ badpad = true;
+ }
+ catch (IllegalBlockSizeException ibse)
+ {
+ badpad = true;
+ }
+ }
+
+ if (inMac != null)
+ {
+ int macLen = inMac.getMacLength();
+ int fragLen = fragment.length - macLen;
+ byte[] mac = Util.trim (fragment, fragLen, macLen);
+ fragment = Util.trim (fragment, fragLen);
+ inMac.update ((byte) (inSequence >>> 56));
+ inMac.update ((byte) (inSequence >>> 48));
+ inMac.update ((byte) (inSequence >>> 40));
+ inMac.update ((byte) (inSequence >>> 32));
+ inMac.update ((byte) (inSequence >>> 24));
+ inMac.update ((byte) (inSequence >>> 16));
+ inMac.update ((byte) (inSequence >>> 8));
+ inMac.update ((byte) inSequence);
+ inMac.update ((byte) type.getValue());
+ if (version != ProtocolVersion.SSL_3)
+ {
+ inMac.update ((byte) version.getMajor());
+ inMac.update ((byte) version.getMinor());
+ }
+ inMac.update ((byte) (fragLen >>> 8));
+ inMac.update ((byte) fragLen);
+ inMac.update (fragment);
+ if (!Arrays.equals (mac, inMac.doFinal()) || badpad)
+ throw new MacException();
+ }
+
+ if (inflater != null)
+ {
+ byte[] buf = new byte[1024];
+ ByteArrayOutputStream bout = new ByteArrayOutputStream (fragment.length << 1);
+ inflater.setInput (fragment);
+ int len;
+ try
+ {
+ while ((len = inflater.inflate (buf)) > 0)
+ {
+ bout.write (buf, 0, len);
+ if (bout.size() > fragmentLength + 1024)
+ throw new OverflowException ("inflated data too large");
+ }
+ }
+ catch (DataFormatException dfe)
+ {
+ throw new SSLException (String.valueOf (dfe));
+ }
+ fragment = bout.toByteArray();
+ inflater.reset();
+ }
+
+ inSequence++;
+ return fragment;
+ }
+
+ public synchronized byte[] encrypt (byte[] fragment, int off, int len,
+ ContentType type)
+ throws OverflowException, SSLException
+ {
+ if (deflater != null)
+ {
+ byte[] buf = new byte[1024];
+ ByteArrayOutputStream bout = new ByteArrayOutputStream (len >>> 1);
+ deflater.setInput (fragment, off, len);
+ deflater.finish();
+ len = 0;
+ while ((len = deflater.deflate (buf)) > 0)
+ bout.write (buf, 0, len);
+ // This should technically never happen for zlib.
+ if (bout.size() > fragmentLength + 1024)
+ throw new OverflowException ("deflated data too large");
+ fragment = bout.toByteArray();
+ off = 0;
+ len = fragment.length;
+ deflater.reset();
+ }
+
+ if (outMac != null)
+ {
+ outMac.update ((byte) (inSequence >>> 56));
+ outMac.update ((byte) (inSequence >>> 48));
+ outMac.update ((byte) (inSequence >>> 40));
+ outMac.update ((byte) (inSequence >>> 32));
+ outMac.update ((byte) (inSequence >>> 24));
+ outMac.update ((byte) (inSequence >>> 16));
+ outMac.update ((byte) (inSequence >>> 8));
+ outMac.update ((byte) inSequence);
+ outMac.update ((byte) type.getValue());
+ if (version != ProtocolVersion.SSL_3)
+ {
+ outMac.update ((byte) version.getMajor());
+ outMac.update ((byte) version.getMinor());
+ }
+ outMac.update ((byte) (len >>> 8));
+ outMac.update ((byte) len);
+ outMac.update (fragment, off, len);
+ fragment = Util.concat (fragment, outMac.doFinal());
+ off = 0;
+ len = fragment.length;
+ }
+
+ if (outCipher != null)
+ {
+ try
+ {
+ fragment = outCipher.doFinal (fragment, off, len);
+ }
+ catch (BadPaddingException shouldNeverHappen)
+ {
+ // This is nonsensical. Don't even pretend that we can handle this.
+ throw new RuntimeException ("bad padding thrown while encrypting");
+ }
+ catch (IllegalBlockSizeException ibse)
+ {
+ // Ditto.
+ throw new RuntimeException ("illegal block size thrown while encrypting");
+ }
+ off = 0;
+ len = fragment.length;
+ }
+
+ outSequence++;
+ if (off == 0 && len == fragment.length)
+ return fragment;
+ else
+ return Util.trim (fragment, off, len);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/JDBCSessionContext.java b/gnu/javax/net/ssl/provider/JDBCSessionContext.java
new file mode 100644
index 000000000..2b9b14034
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/JDBCSessionContext.java
@@ -0,0 +1,356 @@
+/* JDBCSessionContext.java -- database persistent sessions.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.sql.Types;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Enumeration;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import javax.net.ssl.SSLSession;
+
+/**
+ * The SQL table this class stores sessions in, called <tt>SESSIONS</tt>,
+ * looks like this:
+ *
+ * <blockquote><pre>
+ * TABLE SESSIONS (
+ * ID VARBINARY(32) PRIMARY KEY UNIQUE NOT NULL,
+ * CREATED TIMESTAMP NOT NULL,
+ * LAST_ACCESSED TIMESTAMP NOT NULL,
+ * PROTOCOL VARCHAR(7) NOT NULL,
+ * SUITE VARCHAR(255) NOT NULL,
+ * PEER_HOST TEXT NOT NULL,
+ * PEER_CERT_TYPE VARCHAR(32),
+ * PEER_CERTS BLOB,
+ * CERT_TYPE VARCHAR(32),
+ * CERTS BLOB,
+ * SECRET VARBINARY(48) NOT NULL
+ * )
+ * </pre></blockquote>
+ *
+ * <p>Note that the master secret for sessions is not protected before
+ * being inserted into the database; it is up to the system to protect
+ * the stored data from unauthorized access.
+ */
+class JDBCSessionContext extends SessionContext
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ protected Connection connection;
+ protected PreparedStatement selectById;
+ protected PreparedStatement insert;
+ protected PreparedStatement selectTimestamp;
+ protected PreparedStatement updateTimestamp;
+ protected PreparedStatement deleteSession;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ JDBCSessionContext() throws SQLException
+ {
+ String url = Util.getSecurityProperty("jessie.SessionContext.jdbc.url");
+ String user = Util.getSecurityProperty("jessie.SessionContext.jdbc.user");
+ String passwd = Util.getSecurityProperty("jessie.SessionContext.jdbc.password");
+ if (url == null)
+ {
+ throw new IllegalArgumentException("no JDBC URL");
+ }
+ if (user == null || passwd == null)
+ {
+ connection = DriverManager.getConnection(url);
+ }
+ else
+ {
+ connection = DriverManager.getConnection(url, user, passwd);
+ }
+ selectById =
+ connection.prepareStatement("SELECT * FROM SESSIONS WHERE ID = ?");
+ insert = connection.prepareStatement("INSERT INTO SESSIONS VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ selectTimestamp =
+ connection.prepareStatement("SELECT CREATED FROM SESSIONS WHERE ID = ?");
+ updateTimestamp =
+ connection.prepareStatement("UPDATE SESSIONS SET LAST_ACCESSED = ? WHERE ID = ?");
+ deleteSession =
+ connection.prepareStatement("DELETE FROM SESSIONS WHERE ID = ?");
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public synchronized Enumeration getIds()
+ {
+ Vector ids = new Vector();
+ try
+ {
+ Statement stmt = connection.createStatement();
+ ResultSet rs = stmt.executeQuery("SELECT ID FROM SESSIONS");
+ while (rs.next())
+ {
+ byte[] id = rs.getBytes("ID");
+ ids.add(id);
+ }
+ }
+ catch (SQLException sqle)
+ {
+ }
+ return ids.elements();
+ }
+
+ public synchronized SSLSession getSession(byte[] sessionId)
+ {
+ Session session = (Session) super.getSession(sessionId);
+ if (session == null)
+ {
+ try
+ {
+ selectById.setBytes(1, sessionId);
+ ResultSet rs = selectById.executeQuery();
+ if (rs.next())
+ {
+ session = new Session(rs.getTimestamp("CREATED").getTime());
+ session.enabledSuites = new ArrayList(SSLSocket.supportedSuites);
+ session.enabledProtocols = new TreeSet(SSLSocket.supportedProtocols);
+ session.random = new SecureRandom();
+ session.context = this;
+ session.sessionId = new Session.ID(rs.getBytes("ID"));
+ session.setLastAccessedTime(rs.getTimestamp("LAST_ACCESSED").getTime());
+ long elapsed = System.currentTimeMillis() - session.getLastAccessedTime();
+ if ((int) (elapsed / 1000L) > timeout)
+ {
+ removeSession(session.sessionId);
+ return null;
+ }
+ session.peerHost = rs.getString("PEER_HOST");
+ String protocol = rs.getString("PROTOCOL");
+ if (protocol.equals("SSLv3"))
+ {
+ session.protocol = ProtocolVersion.SSL_3;
+ }
+ else if (protocol.equals("TLSv1"))
+ {
+ session.protocol = ProtocolVersion.TLS_1;
+ }
+ else if (protocol.equals("TLSv1.1"))
+ {
+ session.protocol = ProtocolVersion.TLS_1_1;
+ }
+ else
+ {
+ return null;
+ }
+ session.cipherSuite = CipherSuite.forName(rs.getString("SUITE"));
+ String type = rs.getString("PEER_CERT_TYPE");
+ boolean wasNull = rs.wasNull();
+ InputStream certs = null;
+ if (!wasNull)
+ {
+ certs = rs.getBinaryStream("PEER_CERTS");
+ wasNull = rs.wasNull();
+ }
+ if (!wasNull)
+ {
+ CertificateFactory cf = CertificateFactory.getInstance(type);
+ session.peerCerts = (Certificate[])
+ cf.generateCertificates(certs).toArray(new Certificate[0]);
+ session.peerVerified = true;
+ }
+ type = rs.getString("CERT_TYPE");
+ wasNull = rs.wasNull();
+ if (!wasNull)
+ {
+ certs = rs.getBinaryStream("CERTS");
+ wasNull = rs.wasNull();
+ }
+ if (!wasNull)
+ {
+ CertificateFactory cf = CertificateFactory.getInstance(type);
+ session.localCerts = (Certificate[])
+ cf.generateCertificates(certs).toArray(new Certificate[0]);
+ }
+ session.masterSecret = rs.getBytes("SECRET");
+ if (cacheSize == 0 || sessions.size() < cacheSize)
+ {
+ sessions.put(session.sessionId, session);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ return session;
+ }
+
+ synchronized boolean addSession(Session.ID id, Session s)
+ {
+ if (containsSessionID(id))
+ {
+ return false;
+ }
+ try
+ {
+ insert.setBytes(1, id.getId());
+ insert.setTimestamp(2, new Timestamp(s.getCreationTime()));
+ insert.setTimestamp(3, new Timestamp(s.getLastAccessedTime()));
+ insert.setString(4, s.getProtocol());
+ insert.setString(5, s.getCipherSuite());
+ insert.setString(6, s.peerHost);
+ if (s.peerCerts != null && s.peerCerts.length > 0)
+ {
+ insert.setString(7, s.peerCerts[0].getType());
+ insert.setBytes(8, certs(s.peerCerts));
+ }
+ else
+ {
+ insert.setNull(7, Types.VARCHAR);
+ insert.setNull(8, Types.LONGVARBINARY);
+ }
+ if (s.localCerts != null && s.localCerts.length > 0)
+ {
+ insert.setString(9, s.localCerts[0].getType());
+ insert.setBytes(10, certs(s.localCerts));
+ }
+ else
+ {
+ insert.setNull(9, Types.VARCHAR);
+ insert.setNull(10, Types.LONGVARBINARY);
+ }
+ insert.setBytes(11, s.masterSecret);
+ insert.executeUpdate();
+ super.addSession(id, s);
+ }
+ catch (SQLException sqle)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ synchronized boolean containsSessionID(Session.ID sessionId)
+ {
+ try
+ {
+ selectTimestamp.setBytes(1, sessionId.getId());
+ ResultSet rs = selectTimestamp.executeQuery();
+ if (!rs.next())
+ {
+ return false;
+ }
+ Timestamp ts = rs.getTimestamp("CREATED");
+ if (rs.wasNull())
+ {
+ return false;
+ }
+ long elapsed = System.currentTimeMillis() - ts.getTime();
+ if ((int) (elapsed / 1000) > timeout)
+ {
+ removeSession(sessionId);
+ return false;
+ }
+ return true;
+ }
+ catch (SQLException sqle)
+ {
+ return false;
+ }
+ }
+
+ protected boolean removeSession(Session.ID sessionId)
+ {
+ super.removeSession(sessionId);
+ try
+ {
+ deleteSession.setBytes(1, sessionId.getId());
+ return deleteSession.executeUpdate() > 0;
+ }
+ catch (SQLException sqle)
+ {
+ }
+ return false;
+ }
+
+ synchronized void notifyAccess(Session session)
+ {
+ try
+ {
+ updateTimestamp.setTimestamp(1, new Timestamp(session.getLastAccessedTime()));
+ updateTimestamp.setBytes(2, session.getId());
+ updateTimestamp.executeUpdate();
+ }
+ catch (SQLException sqle)
+ {
+ }
+ }
+
+ private byte[] certs(Certificate[] certs)
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
+ for (int i = 0; i < certs.length; i++)
+ {
+ try
+ {
+ out.write(certs[i].getEncoded());
+ }
+ catch (Exception x)
+ {
+ }
+ }
+ return out.toByteArray();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Jessie.java b/gnu/javax/net/ssl/provider/Jessie.java
new file mode 100644
index 000000000..14b671d02
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Jessie.java
@@ -0,0 +1,91 @@
+/* Jessie.java -- JESSIE's JSSE provider.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+
+/**
+ * This is the security provider for Jessie. It implements the following
+ * algorithms:
+ *
+ * <pre>
+ * {@link javax.net.ssl.SSLContext}.SSLv3
+ * {@link javax.net.ssl.SSLContext}.SSL
+ * {@link javax.net.ssl.SSLContext}.TLSv1
+ * {@link javax.net.ssl.SSLContext}.TLS
+ * {@link javax.net.ssl.KeyManagerFactory}.JessieX509
+ * {@link javax.net.ssl.TrustManagerFactory}.JessieX509
+ * {@link javax.net.ssl.TrustManagerFactory}.SRP
+ * </pre>
+ *
+ */
+public class Jessie extends Provider
+{
+
+ public static final String VERSION = "1.0.0";
+ public static final double VERSION_DOUBLE = 1.0;
+
+ public Jessie()
+ {
+ super("Jessie", VERSION_DOUBLE,
+ "Implementing SSLv3, TLSv1 SSL Contexts; X.509 Key Manager Factories;" +
+ System.getProperty("line.separator") +
+ "X.509 and SRP Trust Manager Factories, continuously-seeded secure random." );
+
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ put("SSLContext.SSLv3", Context.class.getName());
+ put("Alg.Alias.SSLContext.SSL", "SSLv3");
+ put("Alg.Alias.SSLContext.TLSv1", "SSLv3");
+ put("Alg.Alias.SSLContext.TLS", "SSLv3");
+ //put("Alg.Alias.SSLContext.TLSv1.1", "SSLv3");
+
+ put("KeyManagerFactory.JessieX509", X509KeyManagerFactory.class.getName());
+ put("TrustManagerFactory.JessieX509", X509TrustManagerFactory.class.getName());
+ put("TrustManagerFactory.SRP", SRPTrustManagerFactory.class.getName());
+
+ return null;
+ }
+ });
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java b/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java
new file mode 100644
index 000000000..1997458dd
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java
@@ -0,0 +1,99 @@
+/* JessieDHPrivateKey.java -- simple DH private key.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.math.BigInteger;
+
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.spec.DHParameterSpec;
+
+class JessieDHPrivateKey implements DHPrivateKey
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final DHParameterSpec params;
+ private final BigInteger x;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ JessieDHPrivateKey(DHParameterSpec params, BigInteger x)
+ {
+ this.params = params;
+ this.x = x;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String getAlgorithm()
+ {
+ return "Diffie-Hellman";
+ }
+
+ public String getFormat()
+ {
+ return "NONE";
+ }
+
+ public byte[] getEncoded()
+ {
+ return null;
+ }
+
+ public DHParameterSpec getParams()
+ {
+ return params;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ public String toString()
+ {
+ String nl = System.getProperty("line.separator");
+ return "P: " + params.getP() + nl +
+ "G: " + params.getG() + nl +
+ "X: " + x;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/JessieDHPublicKey.java b/gnu/javax/net/ssl/provider/JessieDHPublicKey.java
new file mode 100644
index 000000000..dc6587288
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/JessieDHPublicKey.java
@@ -0,0 +1,99 @@
+/* JessieDHPublicKey.java -- simple DH public key.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.math.BigInteger;
+
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+
+class JessieDHPublicKey implements DHPublicKey
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final DHParameterSpec params;
+ private final BigInteger y;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ JessieDHPublicKey(DHParameterSpec params, BigInteger y)
+ {
+ this.params = params;
+ this.y = y;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String getAlgorithm()
+ {
+ return "Diffie-Hellman";
+ }
+
+ public String getFormat()
+ {
+ return "NONE";
+ }
+
+ public byte[] getEncoded()
+ {
+ return null;
+ }
+
+ public DHParameterSpec getParams()
+ {
+ return params;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ public String toString()
+ {
+ String nl = System.getProperty("line.separator");
+ return "P: " + params.getP() + nl +
+ "G: " + params.getG() + nl +
+ "Y: " + y;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java b/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java
new file mode 100644
index 000000000..4ec71a7aa
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java
@@ -0,0 +1,98 @@
+/* JessieRSAPrivateKey.java -- simple RSA private key.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.math.BigInteger;
+import java.security.interfaces.RSAPrivateKey;
+
+class JessieRSAPrivateKey implements RSAPrivateKey
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final BigInteger modulus;
+ private final BigInteger exponent;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ JessieRSAPrivateKey(BigInteger modulus, BigInteger exponent)
+ {
+ this.modulus = modulus;
+ this.exponent = exponent;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String getAlgorithm()
+ {
+ return "RSA";
+ }
+
+ public String getFormat()
+ {
+ return "NONE";
+ }
+
+ public byte[] getEncoded()
+ {
+ return null;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPrivateExponent()
+ {
+ return exponent;
+ }
+
+ public String toString()
+ {
+ String nl = System.getProperty("line.separator");
+ return "RSAPrivateKey {" + nl +
+ " modulus = " + modulus.toString(16) + ";" + nl +
+ " exponent = " + exponent.toString(16) + ";" + nl +
+ "};";
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java b/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java
new file mode 100644
index 000000000..19921d98c
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java
@@ -0,0 +1,98 @@
+/* JessieRSAPublicKey.java -- simple RSA public key.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.math.BigInteger;
+import java.security.interfaces.RSAPublicKey;
+
+class JessieRSAPublicKey implements RSAPublicKey
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final BigInteger modulus;
+ private final BigInteger exponent;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ JessieRSAPublicKey(BigInteger modulus, BigInteger exponent)
+ {
+ this.modulus = modulus;
+ this.exponent = exponent;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String getAlgorithm()
+ {
+ return "RSA";
+ }
+
+ public String getFormat()
+ {
+ return "NONE";
+ }
+
+ public byte[] getEncoded()
+ {
+ return null;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return exponent;
+ }
+
+ public String toString()
+ {
+ String nl = System.getProperty("line.separator");
+ return "RSAPublicKey {" + nl +
+ " modulus = " + modulus.toString(16) + ";" + nl +
+ " exponent = " + exponent.toString(16) + ";" + nl +
+ "};";
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/KeyPool.java b/gnu/javax/net/ssl/provider/KeyPool.java
new file mode 100644
index 000000000..e342700c2
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/KeyPool.java
@@ -0,0 +1,119 @@
+/* KeyPool.java -- A set of ephemeral key pairs.
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.util.LinkedList;
+import javax.crypto.spec.DHParameterSpec;
+
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.Prime2;
+
+final class KeyPool
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private static final BigInteger ONE = BigInteger.ONE;
+ private static final BigInteger TWO = BigInteger.valueOf(2L);
+ private static final BigInteger E = BigInteger.valueOf(65537L);
+ private static final SecureRandom RANDOM = new SecureRandom ();
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ private KeyPool()
+ {
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Generate an export-class (512 bit) RSA key pair.
+ *
+ * @return The new key pair.
+ */
+ static KeyPair generateRSAKeyPair()
+ {
+ BigInteger p, q, n, d;
+
+ // Simplified version of GNU Crypto's RSAKeyPairGenerator.
+
+ int M = 256;
+ BigInteger lower = TWO.pow(255);
+ BigInteger upper = TWO.pow(256).subtract(ONE);
+ byte[] kb = new byte[32];
+ while (true)
+ {
+ nextBytes(kb);
+ p = new BigInteger(1, kb).setBit(0);
+ if (p.compareTo(lower) >= 0 && p.compareTo(upper) <= 0 &&
+ Prime2.isProbablePrime(p) && p.gcd(E).equals(ONE))
+ break;
+ }
+
+ while (true)
+ {
+ nextBytes(kb);
+ q = new BigInteger(1, kb).setBit(0);
+ n = q.multiply(p);
+ if (n.bitLength() == 512 && Prime2.isProbablePrime(q) &&
+ q.gcd(E).equals(ONE))
+ break;
+ }
+
+ d = E.modInverse(p.subtract(ONE).multiply(q.subtract(ONE)));
+
+ return new KeyPair(new JessieRSAPublicKey(n, E),
+ new JessieRSAPrivateKey(n, d));
+ }
+
+ private static void nextBytes(byte[] buf)
+ {
+ RANDOM.nextBytes (buf);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/MacException.java b/gnu/javax/net/ssl/provider/MacException.java
new file mode 100644
index 000000000..b8c479fdb
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/MacException.java
@@ -0,0 +1,53 @@
+/* MacException.java -- signals a bad record MAC.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+
+class MacException extends IOException
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ MacException()
+ {
+ super();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/OverflowException.java b/gnu/javax/net/ssl/provider/OverflowException.java
new file mode 100644
index 000000000..93bdcaec5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/OverflowException.java
@@ -0,0 +1,57 @@
+/* OverflowException.java -- signals an input overflow.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+
+class OverflowException extends IOException
+{
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ OverflowException()
+ {
+ }
+
+ OverflowException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/PRNG.java b/gnu/javax/net/ssl/provider/PRNG.java
new file mode 100644
index 000000000..8145fcd17
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/PRNG.java
@@ -0,0 +1,41 @@
+/* PRNG.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.security.SecureRandom; \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/ProtocolVersion.java b/gnu/javax/net/ssl/provider/ProtocolVersion.java
new file mode 100644
index 000000000..5f5d1d979
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ProtocolVersion.java
@@ -0,0 +1,180 @@
+/* ProtocolVersion.java -- An SSL version number.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+final class ProtocolVersion implements Comparable, Constructed
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ static final ProtocolVersion SSL_3 = new ProtocolVersion(3, 0);
+ static final ProtocolVersion TLS_1 = new ProtocolVersion(3, 1);
+ static final ProtocolVersion TLS_1_1 = new ProtocolVersion(3, 2);
+
+ private final int major;
+ private final int minor;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ private ProtocolVersion(int major, int minor)
+ {
+ this.major = major;
+ this.minor = minor;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static ProtocolVersion read(InputStream in) throws IOException
+ {
+ int major = in.read() & 0xFF;
+ int minor = in.read() & 0xFF;
+ return getInstance(major, minor);
+ }
+
+ static ProtocolVersion getInstance(int major, int minor)
+ {
+ if (major == 3)
+ {
+ switch (minor)
+ {
+ case 0: return SSL_3;
+ case 1: return TLS_1;
+ case 2: return TLS_1_1;
+ }
+ }
+ return new ProtocolVersion(major, minor);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ out.write(major);
+ out.write(minor);
+ }
+
+ byte[] getEncoded()
+ {
+ return new byte[] {
+ (byte) major, (byte) minor
+ };
+ }
+
+ int getMajor()
+ {
+ return major;
+ }
+
+ int getMinor()
+ {
+ return minor;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (o == null || !(o instanceof ProtocolVersion))
+ {
+ return false;
+ }
+ return ((ProtocolVersion) o).major == this.major
+ && ((ProtocolVersion) o).minor == this.minor;
+ }
+
+ public int hashCode()
+ {
+ return major << 8 | minor;
+ }
+
+ public int compareTo(Object o)
+ {
+ if (o == null || !(o instanceof ProtocolVersion))
+ {
+ return 1;
+ }
+ if (this.equals(o))
+ {
+ return 0;
+ }
+ if (major > ((ProtocolVersion) o).major)
+ {
+ return 1;
+ }
+ else if (major < ((ProtocolVersion) o).major)
+ {
+ return -1;
+ }
+ if (minor > ((ProtocolVersion) o).minor)
+ {
+ return 1;
+ }
+ else if (minor < ((ProtocolVersion) o).minor)
+ {
+ return -1;
+ }
+ return 0;
+ }
+
+ public String toString()
+ {
+ if (this == SSL_3)
+ {
+ return "SSLv3";
+ }
+ else if (this == TLS_1)
+ {
+ return "TLSv1";
+ }
+ else if (this == TLS_1_1)
+ {
+ return "TLSv1.1";
+ }
+ else
+ {
+ return "Unsupported; major=" + major + " minor=" + minor;
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Random.java b/gnu/javax/net/ssl/provider/Random.java
new file mode 100644
index 000000000..c42592b14
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Random.java
@@ -0,0 +1,124 @@
+/* Random.java -- SSL Random structure.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+class Random implements Constructed
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final int gmtUnixTime;
+ private final byte[] randomBytes;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ Random(int gmtUnixTime, byte[] randomBytes)
+ {
+ this.gmtUnixTime = gmtUnixTime;
+ this.randomBytes = (byte[]) randomBytes.clone();
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static Random read(InputStream in) throws IOException
+ {
+ int time = (in.read() & 0xFF) << 24 | (in.read() & 0xFF) << 16
+ | (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
+ byte[] buf = new byte[28];
+ in.read(buf);
+ return new Random(time, buf);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ out.write((gmtUnixTime >>> 24) & 0xFF);
+ out.write((gmtUnixTime >>> 16) & 0xFF);
+ out.write((gmtUnixTime >>> 8) & 0xFF);
+ out.write(gmtUnixTime & 0xFF);
+ out.write(randomBytes);
+ }
+
+ byte[] getEncoded()
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(32);
+ try
+ {
+ write(bout);
+ }
+ catch (IOException cantHappen)
+ {
+ throw new Error(cantHappen.toString());
+ }
+ return bout.toByteArray();
+ }
+
+ int getTime()
+ {
+ return gmtUnixTime;
+ }
+
+ byte[] getRandomBytes()
+ {
+ return randomBytes;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ out.println(" gmt_unix_time = " + gmtUnixTime + ";");
+ out.println(" random_bytes = " + Util.toHexString(randomBytes, ':') + ";");
+ out.println("} Random;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/RecordInput.java b/gnu/javax/net/ssl/provider/RecordInput.java
new file mode 100644
index 000000000..d4ba5b596
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/RecordInput.java
@@ -0,0 +1,232 @@
+/* RecordInput.java -- record layer input.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.SystemProperties;
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLProtocolException;
+
+class RecordInput
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private static final boolean DEBUG_RECORD_LAYER = true;
+ private static final Logger logger = SystemLogger.SYSTEM;
+
+ private byte[] fragment;
+ private int index;
+ private ContentType type;
+
+ private final DataInputStream in;
+ private Session session;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ RecordInput (final InputStream in, final Session session)
+ {
+ this.in = new DataInputStream (in);
+ this.session = session;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ synchronized int available (ContentType type) throws IOException
+ {
+ if (fragment == null)
+ {
+ readRecord ();
+ }
+ if (type != this.type)
+ {
+ return 0;
+ }
+ return fragment.length - index;
+ }
+
+ void setSession (Session session)
+ {
+ this.session = session;
+ }
+
+ synchronized int read (byte[] buf, int off, int len, ContentType type)
+ throws IOException
+ {
+ if (off < 0 || len < 0 || off + len > buf.length)
+ {
+ throw new ArrayIndexOutOfBoundsException ("size=" + buf.length +
+ " off=" + off + " len=" + len);
+ }
+ if (fragment == null || index >= fragment.length)
+ {
+ readRecord ();
+ }
+ if (type != this.type)
+ {
+ return 0;
+ }
+ len = Math.min (len, fragment.length - index);
+ System.arraycopy (fragment, index, buf, off, len);
+ index += len;
+ return len;
+ }
+
+ boolean pollClose () throws IOException
+ {
+ if (fragment == null || index >= fragment.length)
+ {
+ try
+ {
+ readRecord();
+ }
+ catch (AlertException ae)
+ {
+ Alert alert = ae.getAlert();
+ if (alert.getDescription() == Alert.Description.CLOSE_NOTIFY)
+ {
+ return true;
+ }
+ throw ae;
+ }
+ }
+ return false;
+ }
+
+ private void readRecord() throws IOException
+ {
+ type = ContentType.read (in);
+ if ((type.getValue() & 0x80) != 0 || (type.getValue() & 0x40) != 0)
+ {
+ in.read();
+ if ((type.getValue() & 0x40) != 0)
+ {
+ in.read();
+ }
+ type = ContentType.read(in);
+ if (type != ContentType.CLIENT_HELLO_V2)
+ {
+ throw new SSLProtocolException("unsupported V2 message");
+ }
+ type = ContentType.HANDSHAKE;
+ // Record this message, and re-present it as a normal handshake
+ // layer message. ClientHello will handle the real parsing.
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream (256);
+ buffer.write(1); // The type we just read.
+ RecordingInputStream in2 = new RecordingInputStream (in, buffer);
+ ProtocolVersion version = ProtocolVersion.read (in2);
+ if (version.compareTo (ProtocolVersion.SSL_3) < 0)
+ {
+ throw new SSLProtocolException("unsupported client version");
+ }
+ int len = (in2.read() & 0xFF) << 8 | (in2.read() & 0xFF);
+ len += (in2.read() & 0xFF) << 8 | (in2.read() & 0xFF);
+ len += (in2.read() & 0xFF) << 8 | (in2.read() & 0xFF);
+ int count = 0;
+ while (count < len)
+ {
+ int l = (int) in2.skip(len - count);
+ if (l > 0)
+ {
+ count += l;
+ }
+ }
+ fragment = buffer.toByteArray ();
+ index = 0;
+
+ // We can't be encrypted/MACed/compressed here, since a V2 message
+ // will only be sent as the first message, and only by the client.
+ return;
+ }
+ ProtocolVersion v = ProtocolVersion.read (in);
+ int len = in.readUnsignedShort ();
+ if (len > session.params.getFragmentLength() + 2048)
+ {
+ throw new OverflowException();
+ }
+ fragment = new byte [len];
+ in.readFully (fragment);
+
+ if (DEBUG_RECORD_LAYER)
+ {
+ logger.log (Component.SSL_RECORD_LAYER,
+ ">> READ RECORD <<{4}" +
+ "struct {{4}" +
+ " type = {0};{4}" +
+ " version = {1};{4}" +
+ " length = {2};{4}" +
+ "{3}{4}" +
+ "} TLSCiphertext;", new Object[]
+ {
+ type, v, new Integer (len),
+ Util.hexDump (fragment, " "),
+ SystemProperties.getProperty ("line.separator")
+ });
+ }
+
+ fragment = session.params.decrypt (fragment, v, type);
+ index = 0;
+
+ if (session.random != null)
+ session.random.setSeed (fragment);
+
+ if (type == ContentType.ALERT)
+ {
+ Alert alert = Alert.read (new ByteArrayInputStream (fragment));
+ session.currentAlert = alert;
+ }
+ if (session.currentAlert != null)
+ {
+ throw new AlertException (session.currentAlert, false);
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/RecordInputStream.java b/gnu/javax/net/ssl/provider/RecordInputStream.java
new file mode 100644
index 000000000..14cf829ac
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/RecordInputStream.java
@@ -0,0 +1,106 @@
+/* RecordInputStream.java -- record layer input stream interface.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+class RecordInputStream extends InputStream
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The record input instance.
+ */
+ private final RecordInput in;
+
+ /**
+ * The content type this stream is reading.
+ */
+ private final ContentType type;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ RecordInputStream (RecordInput in, ContentType type)
+ {
+ this.in = in;
+ this.type = type;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public int available () throws IOException
+ {
+ return in.available (type);
+ }
+
+ public int read () throws IOException
+ {
+ byte[] b = new byte[1];
+ int ret;
+ while ((ret = read (b)) != 1)
+ {
+ if (ret == -1)
+ {
+ return -1;
+ }
+ Thread.yield ();
+ }
+ return b[0] & 0xFF;
+ }
+
+ public int read (byte[] buf) throws IOException
+ {
+ return read (buf, 0, buf.length);
+ }
+
+ public int read (byte[] buf, int off, int len) throws IOException
+ {
+ return in.read (buf, off, len, type);
+ }
+
+ public String toString ()
+ {
+ return RecordInputStream.class.getName () + " [ type=" + type + " ]";
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/RecordOutputStream.java b/gnu/javax/net/ssl/provider/RecordOutputStream.java
new file mode 100644
index 000000000..3bf228f2d
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/RecordOutputStream.java
@@ -0,0 +1,189 @@
+/* RecordOutputStream.java -- record layer output.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.SystemProperties;
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import java.util.logging.Logger;
+
+/**
+ * An output stream for writing data to the record layer. All data written
+ * to this stream (through any of the write methods) is immediately sent
+ * as a full record, so it is advisable to write large arrays to the stream
+ * instead of one byte at a time (alternatively, a {@link
+ * java.io.BufferedOutputStream} can be used).
+ */
+class RecordOutputStream extends FilterOutputStream
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private static final boolean DEBUG_RECORD_LAYER = true;
+ private static final Logger logger = SystemLogger.SYSTEM;
+
+ /**
+ * The content type of this output stream.
+ */
+ private final ContentType type;
+
+ /**
+ * The security parameters.
+ */
+ private final SecurityParameters params;
+
+ private final boolean emitEmpty;
+
+ private static final byte[] ZERO = new byte[0];
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ RecordOutputStream (final OutputStream out, final ContentType type,
+ final SecurityParameters params)
+ {
+ super (out);
+ this.type = type;
+ this.params = params;
+ String empty = Util.getSecurityProperty ("jessie.emit.empty.records");
+ if (empty == null)
+ {
+ // IE panics if it gets an empty record; so, leave this false
+ // for the default.
+ empty = "false";
+ }
+ emitEmpty = Boolean.valueOf (empty).booleanValue () &&
+ type == ContentType.APPLICATION_DATA;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write (int b) throws IOException
+ {
+ write (new byte[] { (byte) b });
+ }
+
+ public void write (byte[] buf) throws IOException
+ {
+ write (buf, 0, buf.length);
+ }
+
+ public void write (byte[] buf, int off, int len) throws IOException
+ {
+ if (off < 0 || len < 0 || off + len > buf.length)
+ {
+ throw new ArrayIndexOutOfBoundsException ("size=" + buf.length +
+ " off=" + off + " len=" + len);
+ }
+
+ int count = 0;
+ int len2 = 0;
+ do
+ {
+ if (emitEmpty)
+ {
+ byte[] fragment = params.encrypt (ZERO, 0, 0, type);
+ if (DEBUG_RECORD_LAYER)
+ {
+ logger.log (Component.SSL_RECORD_LAYER,
+ ">> WRITING RECORD <<{4}" +
+ "struct {{4}" +
+ " type = {0};{4}" +
+ " version = {1};{4}" +
+ " length = {2};{4}" +
+ "{3}{4}" +
+ "} TLSCiphertext;", new Object[]
+ {
+ type, params.getVersion (), new Integer (fragment.length),
+ Util.hexDump (fragment, " "),
+ SystemProperties.getProperty ("line.separator")
+ });
+ }
+ out.write (type.getValue());
+ params.getVersion().write (out);
+ out.write ((fragment.length >>> 8) & 0xFF);
+ out.write ( fragment.length & 0xFF);
+ out.write (fragment);
+ out.flush ();
+ }
+ len2 = Math.min (len - count, params.getFragmentLength());
+ if (DEBUG_RECORD_LAYER)
+ {
+ logger.log (Component.SSL_RECORD_LAYER,
+ "writing chunk size={0}", new Integer (len2));
+ }
+ synchronized (out)
+ {
+ byte[] fragment = params.encrypt (buf, off + count, len2, type);
+ if (DEBUG_RECORD_LAYER)
+ {
+ logger.log (Component.SSL_RECORD_LAYER,
+ ">> WRITING RECORD <<{4}" +
+ "struct {{4}" +
+ " type = {0};{4}" +
+ " version = {1};{4}" +
+ " length = {2};{4}" +
+ "{3}{4}" +
+ "} TLSCiphertext;", new Object[]
+ {
+ type, params.getVersion (), new Integer (fragment.length),
+ Util.hexDump (fragment, " "),
+ SystemProperties.getProperty ("line.separator")
+ });
+ }
+ out.write (type.getValue());
+ params.getVersion().write (out);
+ out.write ((fragment.length >>> 8) & 0xFF);
+ out.write ( fragment.length & 0xFF);
+ out.write (fragment);
+ out.flush ();
+ }
+ count += len2;
+ }
+ while (count < len);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/RecordingInputStream.java b/gnu/javax/net/ssl/provider/RecordingInputStream.java
new file mode 100644
index 000000000..d81b652d5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/RecordingInputStream.java
@@ -0,0 +1,131 @@
+/* RecordingInputStream.java -- Input stream that records data.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * A filter input stream that records every byte read from the underlying
+ * input stream. This class is useful for protocols that require portions
+ * of the communication to be saved, such as the handshake and key
+ * derivation in SSL.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+class RecordingInputStream extends FilterInputStream
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ protected ByteArrayOutputStream sink;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ RecordingInputStream(InputStream in)
+ {
+ this(in, new ByteArrayOutputStream());
+ }
+
+ RecordingInputStream(InputStream in, ByteArrayOutputStream sink)
+ {
+ super(in);
+ this.sink = sink;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public synchronized int read() throws IOException
+ {
+ int i = in.read();
+ sink.write(i);
+ return i;
+ }
+
+ public synchronized int read(byte[] buf, int off, int len) throws IOException
+ {
+ int l = in.read(buf, off, len);
+ sink.write(buf, off, l);
+ return l;
+ }
+
+ public synchronized int read(byte[] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public synchronized long skip(long len) throws IOException
+ {
+ long l = 0;
+ int i = 0;
+ byte[] buf = new byte[1024];
+ while (l < len)
+ {
+ i = read(buf, 0, (int) Math.min((long) buf.length, len - l));
+ if (i == -1)
+ break;
+ l += i;
+ }
+ return l;
+ }
+
+ /**
+ * Returns all bytes recorded after this instance was created, or the last
+ * call to {@link resetSink()}.
+ *
+ * @return The recorded bytes.
+ */
+ byte[] getBytes()
+ {
+ return sink.toByteArray();
+ }
+
+ /**
+ * Clears the recording buffer off all previously-recorded bytes.
+ */
+ void resetSink()
+ {
+ sink.reset();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java b/gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java
new file mode 100644
index 000000000..5822afe05
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java
@@ -0,0 +1,225 @@
+/* SRPTrustManagerFactory.java -- trust manager for SRP.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.Security;
+
+import java.util.HashMap;
+
+import javax.net.ssl.ManagerFactoryParameters;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactorySpi;
+
+import gnu.java.security.key.IKeyPairGenerator;
+import gnu.javax.crypto.key.srp6.SRPKeyPairGenerator;
+import gnu.javax.crypto.sasl.srp.PasswordFile;
+import gnu.javax.crypto.sasl.srp.SRP;
+
+import gnu.javax.net.ssl.SRPManagerParameters;
+import gnu.javax.net.ssl.SRPTrustManager;
+
+/**
+ * This is an implementation of a {@link javax.net.ssl.TrustManagerFactory}
+ * engine for the ``SRP'' algorithm. You must initialize instances of this
+ * algorithm with {@link SRPManagerParameters}.
+ */
+public class SRPTrustManagerFactory extends TrustManagerFactorySpi
+{
+
+ // Field.
+ // -------------------------------------------------------------------------
+
+ private Manager current;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public SRPTrustManagerFactory()
+ {
+ super();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ protected TrustManager[] engineGetTrustManagers()
+ {
+ if (current == null)
+ throw new IllegalStateException("not initialized");
+ return new TrustManager[] { current };
+ }
+
+ protected void engineInit(KeyStore ks)
+ {
+ throw new IllegalArgumentException("only accepts SRPManagerParameters");
+ }
+
+ protected void engineInit(ManagerFactoryParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ if (params == null)
+ {
+ try
+ {
+ String srpPasswd = Util.getSecurityProperty("jessie.srp.password.file");
+ if (srpPasswd == null)
+ {
+ current = new Manager(new PasswordFile());
+ return;
+ }
+ String srpPasswd2 = Util.getSecurityProperty("jessie.srp.password.file2");
+ if (srpPasswd2 == null)
+ srpPasswd2 = srpPasswd + "2";
+ String srpConfig = Util.getSecurityProperty("jessie.srp.config");
+ if (srpConfig == null)
+ srpConfig = srpPasswd + ".conf";
+ current = new Manager(new PasswordFile(srpPasswd, srpPasswd2, srpConfig));
+ return;
+ }
+ catch (IOException ioe)
+ {
+ throw new InvalidAlgorithmParameterException("default initialization failed: "
+ + ioe.toString());
+ }
+ }
+ if (params instanceof SRPManagerParameters)
+ {
+ current = new Manager(((SRPManagerParameters) params).getPasswordFile());
+ return;
+ }
+ throw new InvalidAlgorithmParameterException();
+ }
+
+ // Inner class.
+ // -------------------------------------------------------------------------
+
+ private class Manager implements SRPTrustManager
+ {
+
+ // Field.
+ // -----------------------------------------------------------------------
+
+ private final PasswordFile file;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ Manager(PasswordFile file)
+ {
+ this.file = file;
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public boolean contains(String user)
+ {
+ try
+ {
+ return file.contains(user);
+ }
+ catch (IOException ioe) { }
+ return false;
+ }
+
+ public KeyPair getKeyPair(String user)
+ {
+ try
+ {
+ if (file.contains(user))
+ {
+ SRP srp = SRP.instance("SHA");
+ String[] ent = file.lookup(user, "SHA");
+ String[] cnf = file.lookupConfig(ent[2]);
+ BigInteger v, N, g;
+ v = new BigInteger(1, gnu.java.security.util.Util.fromBase64(ent[0]));
+ N = new BigInteger(1, gnu.java.security.util.Util.fromBase64(cnf[0]));
+ g = new BigInteger(1, gnu.java.security.util.Util.fromBase64(cnf[1]));
+ IKeyPairGenerator kpg = new SRPKeyPairGenerator();
+ HashMap attr = new HashMap();
+ attr.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
+ attr.put(SRPKeyPairGenerator.GENERATOR, g);
+ attr.put(SRPKeyPairGenerator.USER_VERIFIER, v);
+ kpg.setup(attr);
+ return kpg.generate();
+ }
+ }
+ catch (IOException ioe) { }
+ return null;
+ }
+
+ public byte[] getSalt(String user)
+ {
+ try
+ {
+ if (file.contains(user))
+ {
+ return gnu.java.security.util.Util.fromBase64(file.lookup(user, "SHA")[1]);
+ }
+ }
+ catch (IOException ioe) { }
+ return null;
+ }
+
+ public BigInteger getVerifier(String user)
+ {
+ try
+ {
+ if (file.contains(user))
+ {
+ return new BigInteger(1,
+ gnu.java.security.util.Util.fromBase64(file.lookup(user, "SHA")[0]));
+ }
+ }
+ catch (IOException ioe) { }
+ return null;
+ }
+
+ public PasswordFile getPasswordFile()
+ {
+ return file;
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLHMac.java b/gnu/javax/net/ssl/provider/SSLHMac.java
new file mode 100644
index 000000000..002b3077f
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLHMac.java
@@ -0,0 +1,158 @@
+/* SSLHMac.java -- SSLv3's MAC algorithm.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.javax.crypto.mac.IMac;
+
+/**
+ * The MAC function in SSLv3. This mac is defined as:
+ *
+ * <pre>
+ * hash(MAC_write_secret, pad_2 +
+ * hash(MAC_write_secret + pad_1 + data));</pre>
+ *
+ * <p><tt>hash</tt> is e.g. MD5 or SHA-1, <tt>pad_1</tt> is the value
+ * 0x36 48 times for MD5 and 40 times for SHA-1, and <tt>pad_2</tt> is
+ * the value 0x5c repeated similarly.
+ */
+class SSLHMac implements IMac, Cloneable
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ static final byte PAD1 = 0x36;
+ static final byte PAD2 = 0x5c;
+
+ protected IMessageDigest md;
+ protected byte[] key;
+ protected final byte[] pad1, pad2;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ SSLHMac(String mdName)
+ {
+ super();
+ this.md = HashFactory.getInstance(mdName);
+ if (mdName.equalsIgnoreCase("MD5"))
+ {
+ pad1 = new byte[48];
+ pad2 = new byte[48];
+ }
+ else
+ {
+ pad1 = new byte[40];
+ pad2 = new byte[40];
+ }
+ Arrays.fill(pad1, PAD1);
+ Arrays.fill(pad2, PAD2);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ throw new Error();
+ }
+ }
+
+ public String name()
+ {
+ return "SSLHMac-" + md.name();
+ }
+
+ public int macSize()
+ {
+ return md.hashSize();
+ }
+
+ public void init(Map attributes)
+ {
+ key = (byte[]) attributes.get(MAC_KEY_MATERIAL);
+ if (key == null)
+ throw new NullPointerException();
+ reset();
+ }
+
+ public void reset()
+ {
+ md.reset();
+ md.update(key, 0, key.length);
+ md.update(pad1, 0, pad1.length);
+ }
+
+ public byte[] digest()
+ {
+ byte[] h1 = md.digest();
+ md.update(key, 0, key.length);
+ md.update(pad2, 0, pad2.length);
+ md.update(h1, 0, h1.length);
+ byte[] result = md.digest();
+ reset();
+ return result;
+ }
+
+ public void update(byte b)
+ {
+ md.update(b);
+ }
+
+ public void update(byte[] buf, int off, int len)
+ {
+ md.update(buf, off, len);
+ }
+
+ public boolean selfTest()
+ {
+ return true; // XXX
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLRSASignature.java b/gnu/javax/net/ssl/provider/SSLRSASignature.java
new file mode 100644
index 000000000..2f8c6cfe6
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLRSASignature.java
@@ -0,0 +1,235 @@
+/* SSLRSASignature.java -- SSL's RSA signature algorithm.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.math.BigInteger;
+
+import java.security.InvalidKeyException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.sig.ISignature;
+import gnu.java.security.sig.rsa.RSA;
+
+/**
+ * The RSA signature algorithm as used in the SSL protocol. Note that this
+ * is different from the RSA signature used to verify certificates.
+ *
+ * <p>This signature scheme works as follows:</p>
+ *
+ * <blockquote><p><pre>digitally-signed struct {
+ * opaque md5_hash[16];
+ * opaque sha_hash[20];
+ * }</pre></p></blockquote>
+ *
+ * <p>Where a <code>digitally-signed struct</code> is RSA-encrypted with
+ * block type 0 or 1 according to PKCS #1, version 1.5.</p>
+ */
+final class SSLRSASignature implements ISignature
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private RSAPublicKey pubkey;
+ private RSAPrivateKey privkey;
+ private final IMessageDigest md5, sha;
+ private boolean initVerify = false, initSign = false;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ SSLRSASignature()
+ {
+ this(HashFactory.getInstance("MD5"), HashFactory.getInstance("SHA-1"));
+ }
+
+ SSLRSASignature(IMessageDigest md5, IMessageDigest sha)
+ {
+ this.md5 = md5;
+ this.sha = sha;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String name()
+ {
+ return "RSA/SSL";
+ }
+
+ public void setupVerify(Map attrib)
+ {
+ PublicKey key = (PublicKey) attrib.get(VERIFIER_KEY);
+ if (key == null)
+ {
+ if (initSign)
+ {
+ return; // re-use.
+ }
+ throw new IllegalArgumentException("no key supplied");
+ }
+ if (!(key instanceof RSAPublicKey))
+ {
+ throw new IllegalArgumentException("not an RSA key");
+ }
+ pubkey = (RSAPublicKey) key;
+ privkey = null;
+ initSign = false;
+ initVerify = true;
+ }
+
+ public void setupSign(Map attrib)
+ {
+ PrivateKey key = (PrivateKey) attrib.get(SIGNER_KEY);
+ if (key == null)
+ {
+ if (initVerify)
+ {
+ return; // re-use.
+ }
+ throw new IllegalArgumentException("no key supplied");
+ }
+ if (!(key instanceof RSAPrivateKey))
+ {
+ throw new IllegalArgumentException("not an RSA key");
+ }
+ privkey = (RSAPrivateKey) key;
+ pubkey = null;
+ initVerify = false;
+ initSign = true;
+ }
+
+ public void update(byte b)
+ {
+ if (!initVerify && !initSign)
+ {
+ throw new IllegalStateException();
+ }
+ md5.update(b);
+ sha.update(b);
+ }
+
+ public void update(byte[] buf, int off, int len)
+ {
+ if (!initVerify && !initSign)
+ {
+ throw new IllegalStateException();
+ }
+ md5.update(buf, off, len);
+ sha.update(buf, off, len);
+ }
+
+ public Object sign()
+ {
+ if (!initSign)
+ {
+ throw new IllegalStateException();
+ }
+ // Pad the hash results with RSA block type 1.
+ final int k = (privkey.getModulus().bitLength() + 7) >>> 3;
+ final byte[] d = Util.concat(md5.digest(), sha.digest());
+ if (k - 11 < d.length)
+ {
+ throw new IllegalArgumentException("message too long");
+ }
+ final byte[] eb = new byte[k];
+ eb[0] = 0x00;
+ eb[1] = 0x01;
+ for (int i = 2; i < k - d.length - 1; i++)
+ {
+ eb[i] = (byte) 0xFF;
+ }
+ System.arraycopy(d, 0, eb, k - d.length, d.length);
+ BigInteger EB = new BigInteger(eb);
+
+ // Private-key encrypt the padded hashes.
+ BigInteger EM = RSA.sign(privkey, EB);
+ return Util.trim(EM);
+ }
+
+ public boolean verify(Object signature)
+ {
+ if (!initVerify)
+ {
+ throw new IllegalStateException();
+ }
+ // Public-key decrypt the signature representative.
+ BigInteger EM = new BigInteger(1, (byte[]) signature);
+ BigInteger EB = RSA.verify(pubkey, EM);
+
+ // Unpad the decrypted message.
+ int i = 0;
+ final byte[] eb = EB.toByteArray();
+ if (eb[0] == 0x00)
+ {
+ for (i = 0; i < eb.length && eb[i] == 0x00; i++);
+ }
+ else if (eb[0] == 0x01)
+ {
+ for (i = 1; i < eb.length && eb[i] != 0x00; i++)
+ {
+ if (eb[i] != (byte) 0xFF)
+ {
+ throw new IllegalArgumentException("bad padding");
+ }
+ }
+ i++;
+ }
+ else
+ {
+ throw new IllegalArgumentException("decryption failed");
+ }
+ byte[] d1 = Util.trim(eb, i, eb.length - i);
+ byte[] d2 = Util.concat(md5.digest(), sha.digest());
+ return Arrays.equals(d1, d2);
+ }
+
+ public Object clone()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLRandom.java b/gnu/javax/net/ssl/provider/SSLRandom.java
new file mode 100644
index 000000000..0b28f1044
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLRandom.java
@@ -0,0 +1,165 @@
+/* SSLRandom.java -- SSLv3 pseudo-random function.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.util.Map;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+class SSLRandom implements IRandom
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ static final String SECRET = "jessie.sslprng.secret";
+ static final String SEED = "jessie.sslprng.seed";
+
+ private final IMessageDigest md5, sha;
+ private byte[] secret;
+ private byte[] buffer;
+ private byte pad;
+ private byte[] seed;
+ private int idx;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ SSLRandom()
+ {
+ md5 = HashFactory.getInstance("MD5");
+ sha = HashFactory.getInstance("SHA-1");
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void init(Map attrib)
+ {
+ secret = (byte[]) attrib.get(SECRET);
+ seed = (byte[]) attrib.get(SEED);
+
+ if (secret == null || seed == null)
+ throw new NullPointerException();
+
+ pad = (byte) 'A';
+ try { buffer = nextBlock(); }
+ catch (LimitReachedException cantHappen) { }
+ }
+
+ public String name()
+ {
+ return "SSLRandom";
+ }
+
+ public Object clone()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public byte nextByte() throws LimitReachedException
+ {
+ if (buffer == null)
+ throw new IllegalStateException();
+ if (idx >= buffer.length)
+ buffer = nextBlock();
+ return buffer[idx++];
+ }
+
+ public void nextBytes(byte[] buf, int off, int len)
+ throws LimitReachedException
+ {
+ if (buffer == null)
+ throw new IllegalStateException();
+ if (buf == null)
+ throw new NullPointerException();
+ if (off < 0 || len < 0 || off+len > buf.length)
+ throw new IndexOutOfBoundsException();
+ int count = 0;
+ while (count < len)
+ {
+ if (idx >= buffer.length)
+ buffer = nextBlock();
+ int l = Math.min(buffer.length-idx, len-count);
+ System.arraycopy(buffer, idx, buf, off+count, l);
+ count += l;
+ idx += l;
+ }
+ }
+
+ public boolean selfTest()
+ {
+ return true; // XXX
+ }
+
+ // For future versions of GNU Crypto. No-ops.
+ public void addRandomByte (byte b)
+ {
+ }
+
+ public void addRandomBytes(byte[] buffer) {
+ addRandomBytes(buffer, 0, buffer.length);
+ }
+
+ public void addRandomBytes (byte[] b, int i, int j)
+ {
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private byte[] nextBlock() throws LimitReachedException
+ {
+ int count = pad - 'A' + 1;
+ if (count > 26)
+ throw new LimitReachedException();
+ for (int i = 0; i < count; i++)
+ sha.update(pad);
+ sha.update(secret, 0, secret.length);
+ sha.update(seed, 0, seed.length);
+ byte[] b = sha.digest();
+ md5.update(secret, 0, secret.length);
+ md5.update(b, 0, b.length);
+ idx = 0;
+ pad++;
+ return md5.digest();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLServerSocket.java b/gnu/javax/net/ssl/provider/SSLServerSocket.java
new file mode 100644
index 000000000..ee96b8d1b
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLServerSocket.java
@@ -0,0 +1,283 @@
+/* SSLServerSocket.java -- SSL server socket.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+
+import java.net.InetAddress;
+import java.net.Socket;
+
+import java.security.SecureRandom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+
+import gnu.javax.net.ssl.SRPTrustManager;
+
+class SSLServerSocket extends javax.net.ssl.SSLServerSocket
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private SessionContext sessions;
+ private SortedSet enabledProtocols = new TreeSet(SSLSocket.supportedProtocols);
+ private List enabledSuites = new ArrayList(SSLSocket.supportedSuites);
+ private boolean clientMode = false;
+ private boolean needClientAuth = false;
+ private boolean wantClientAuth = false;
+ private boolean createSessions = true;
+ private SRPTrustManager srpTrustManager;
+ private X509TrustManager trustManager;
+ private X509KeyManager keyManager;
+ private SecureRandom random;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ SSLServerSocket() throws IOException
+ {
+ super();
+ }
+
+ SSLServerSocket(int port) throws IOException
+ {
+ super(port);
+ }
+
+ SSLServerSocket(int port, int backlog) throws IOException
+ {
+ super(port, backlog);
+ }
+
+ SSLServerSocket(int port, int backlog, InetAddress address)
+ throws IOException
+ {
+ super(port, backlog, address);
+ }
+
+ // SSL methods.
+ // -------------------------------------------------------------------------
+
+ public String[] getSupportedCipherSuites()
+ {
+ return (String[]) CipherSuite.availableSuiteNames().toArray(new String[0]);
+ }
+
+ public String[] getEnabledCipherSuites()
+ {
+ synchronized (enabledSuites)
+ {
+ String[] s = new String[enabledSuites.size()];
+ int i = 0;
+ for (Iterator it = enabledSuites.iterator(); it.hasNext(); )
+ s[i++] = it.next().toString();
+ return s;
+ }
+ }
+
+ public void setEnabledCipherSuites(String[] suites)
+ {
+ if (suites == null || suites.length == 0)
+ throw new IllegalArgumentException();
+ for (int i = 0; i < suites.length; i++)
+ if (CipherSuite.forName(suites[i]) == null)
+ throw new IllegalArgumentException("unsupported suite: " +
+ suites[i]);
+ synchronized (enabledSuites)
+ {
+ enabledSuites.clear();
+ for (int i = 0; i < suites.length; i++)
+ {
+ CipherSuite suite = CipherSuite.forName(suites[i]);
+ if (!enabledSuites.contains(suite))
+ enabledSuites.add(suite);
+ }
+ }
+ }
+
+ public String[] getSupportedProtocols()
+ {
+ return new String[] { "SSLv3", "TLSv1", "TLSv1.1" };
+ }
+
+ public String[] getEnabledProtocols()
+ {
+ synchronized (enabledProtocols)
+ {
+ String[] s = new String[enabledProtocols.size()];
+ int i = 0;
+ for (Iterator it = enabledProtocols.iterator(); it.hasNext(); )
+ s[i++] = it.next().toString();
+ return s;
+ }
+ }
+
+ public void setEnabledProtocols(String[] protocols)
+ {
+ if (protocols == null || protocols.length == 0)
+ throw new IllegalArgumentException();
+ for (int i = 0; i < protocols.length; i++)
+ {
+ if (!(protocols[i].equalsIgnoreCase("SSLv3") ||
+ protocols[i].equalsIgnoreCase("TLSv1") ||
+ protocols[i].equalsIgnoreCase("TLSv1.1")))
+ {
+ throw new
+ IllegalArgumentException("unsupported protocol: " +
+ protocols[i]);
+ }
+ }
+ synchronized (enabledProtocols)
+ {
+ enabledProtocols.clear();
+ for (int i = 0; i < protocols.length; i++)
+ {
+ if (protocols[i].equalsIgnoreCase("SSLv3"))
+ enabledProtocols.add(ProtocolVersion.SSL_3);
+ else if (protocols[i].equalsIgnoreCase("TLSv1"))
+ enabledProtocols.add(ProtocolVersion.TLS_1);
+ else
+ enabledProtocols.add(ProtocolVersion.TLS_1_1);
+ }
+ }
+ }
+
+ public void setUseClientMode(boolean clientMode)
+ {
+ this.clientMode = clientMode;
+ }
+
+ public boolean getUseClientMode()
+ {
+ return clientMode;
+ }
+
+ public void setNeedClientAuth(boolean needClientAuth)
+ {
+ this.needClientAuth = needClientAuth;
+ }
+
+ public boolean getNeedClientAuth()
+ {
+ return needClientAuth;
+ }
+
+ public void setWantClientAuth(boolean wantClientAuth)
+ {
+ this.wantClientAuth = wantClientAuth;
+ }
+
+ public boolean getWantClientAuth()
+ {
+ return wantClientAuth;
+ }
+
+ // I misspelled this method in javax.net.SSLServerSocket, and that version
+ // made it into kaffe 1.1.4.
+ public void setEnabledSessionCreation(boolean createSessions)
+ {
+ setEnableSessionCreation(createSessions);
+ }
+
+ public void setEnableSessionCreation(boolean createSessions)
+ {
+ this.createSessions = createSessions;
+ }
+
+ public boolean getEnableSessionCreation()
+ {
+ return createSessions;
+ }
+
+ // Socket methods.
+ // -------------------------------------------------------------------------
+
+ public Socket accept() throws IOException
+ {
+ SSLSocket socket = new SSLSocket();
+ implAccept(socket);
+ socket.setUseClientMode(clientMode);
+ socket.setNeedClientAuth(needClientAuth);
+ socket.setWantClientAuth(wantClientAuth);
+ socket.setEnableSessionCreation(createSessions);
+ socket.setSessionContext(sessions);
+ socket.setEnabledCipherSuites(new ArrayList(enabledSuites));
+ socket.setEnabledProtocols(new TreeSet(enabledProtocols));
+ socket.setSRPTrustManager(srpTrustManager);
+ socket.setTrustManager(trustManager);
+ socket.setKeyManager(keyManager);
+ socket.setRandom(random);
+ return socket;
+ }
+
+ // Package methods.
+ // -------------------------------------------------------------------------
+
+ void setSessionContext(SessionContext sessions)
+ {
+ this.sessions = sessions;
+ }
+
+ void setKeyManager(X509KeyManager keyManager)
+ {
+ this.keyManager = keyManager;
+ }
+
+ void setTrustManager(X509TrustManager trustManager)
+ {
+ this.trustManager = trustManager;
+ }
+
+ void setSRPTrustManager(SRPTrustManager srpTrustManager)
+ {
+ this.srpTrustManager = srpTrustManager;
+ }
+
+ void setRandom(SecureRandom random)
+ {
+ this.random = random;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java b/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java
new file mode 100644
index 000000000..72fb512c5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java
@@ -0,0 +1,136 @@
+/* SSLServerSocketFactory.java -- factory for SSL server sockets.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+
+import java.net.InetAddress;
+import java.net.ServerSocket;
+
+import java.security.SecureRandom;
+
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+
+import gnu.javax.net.ssl.SRPTrustManager;
+
+class SSLServerSocketFactory extends javax.net.ssl.SSLServerSocketFactory
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final SessionContext sessions;
+ private final X509KeyManager keyManager;
+ private final X509TrustManager trustManager;
+ private final SRPTrustManager srpTrustManager;
+ private final SecureRandom random;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ SSLServerSocketFactory(X509TrustManager trustManager,
+ SRPTrustManager srpTrustManager,
+ X509KeyManager keyManager,
+ SecureRandom random,
+ SessionContext sessions)
+ {
+ super();
+ this.trustManager = trustManager;
+ this.srpTrustManager = srpTrustManager;
+ this.keyManager = keyManager;
+ this.random = random;
+ this.sessions = sessions;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String[] getDefaultCipherSuites()
+ {
+ return getSupportedCipherSuites();
+ }
+
+ public String[] getSupportedCipherSuites()
+ {
+ return (String[]) CipherSuite.availableSuiteNames().toArray(new String[0]);
+ }
+
+ public ServerSocket createServerSocket() throws IOException
+ {
+ SSLServerSocket socket = new SSLServerSocket();
+ setup(socket);
+ return socket;
+ }
+
+ public ServerSocket createServerSocket(int port) throws IOException
+ {
+ SSLServerSocket socket = new SSLServerSocket(port);
+ setup(socket);
+ return socket;
+ }
+
+ public ServerSocket createServerSocket(int port, int backlog)
+ throws IOException
+ {
+ SSLServerSocket socket = new SSLServerSocket(port, backlog);
+ setup(socket);
+ return socket;
+ }
+
+ public ServerSocket createServerSocket(int port, int backlog, InetAddress addr)
+ throws IOException
+ {
+ SSLServerSocket socket = new SSLServerSocket(port, backlog, addr);
+ setup(socket);
+ return socket;
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private void setup(SSLServerSocket socket)
+ {
+ socket.setSessionContext(sessions);
+ socket.setKeyManager(keyManager);
+ socket.setTrustManager(trustManager);
+ socket.setSRPTrustManager(srpTrustManager);
+ socket.setRandom(random);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLSocket.java b/gnu/javax/net/ssl/provider/SSLSocket.java
new file mode 100644
index 000000000..a564659c0
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLSocket.java
@@ -0,0 +1,3530 @@
+/* SSLSocket.java -- the SSL socket class.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import java.math.BigInteger;
+
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+
+import java.nio.channels.SocketChannel;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import java.util.logging.Logger;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import javax.net.ssl.HandshakeCompletedEvent;
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLProtocolException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import gnu.java.security.Registry;
+import gnu.javax.security.auth.callback.DefaultCallbackHandler;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.javax.crypto.key.IKeyAgreementParty;
+import gnu.javax.crypto.key.KeyAgreementFactory;
+import gnu.javax.crypto.key.KeyAgreementException;
+import gnu.javax.crypto.key.OutgoingMessage;
+import gnu.javax.crypto.key.IncomingMessage;
+import gnu.javax.crypto.key.dh.DiffieHellmanKeyAgreement;
+import gnu.javax.crypto.key.dh.ElGamalKeyAgreement;
+import gnu.javax.crypto.key.dh.GnuDHPrivateKey;
+import gnu.javax.crypto.key.dh.GnuDHPublicKey;
+import gnu.javax.crypto.key.srp6.SRPPrivateKey;
+import gnu.javax.crypto.key.srp6.SRPPublicKey;
+import gnu.javax.crypto.key.srp6.SRP6KeyAgreement;
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.prng.ARCFour;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.javax.crypto.sasl.srp.SRPAuthInfoProvider;
+import gnu.javax.crypto.sasl.srp.SRPRegistry;
+import gnu.java.security.sig.ISignature;
+import gnu.java.security.sig.SignatureFactory;
+import gnu.java.security.sig.dss.DSSSignature;
+import gnu.java.security.sig.rsa.EME_PKCS1_V1_5;
+import gnu.java.security.sig.rsa.RSA;
+
+import gnu.javax.net.ssl.SRPTrustManager;
+
+/**
+ * This is the core of the Jessie SSL implementation; it implements the {@link
+ * javax.net.ssl.SSLSocket} for normal and "wrapped" sockets, and handles all
+ * protocols implemented by this library.
+ */
+final class SSLSocket extends javax.net.ssl.SSLSocket
+{
+
+ // This class is almost unbearably large and complex, but is laid out
+ // as follows:
+ //
+ // 1. Fields.
+ // 2. Constructors.
+ // 3. SSLSocket methods. These are the public methods defined in
+ // javax.net.ssl.SSLSocket.
+ // 4. Socket methods. These override the public methods of java.net.Socket,
+ // and delegate the method call to either the underlying socket if this is
+ // a wrapped socket, or to the superclass.
+ // 5. Package-private methods that various pieces of Jessie use.
+ // 6. Private methods. These compose the SSL handshake.
+ //
+ // Each part is preceeded by a form feed.
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ // Debuggery.
+ private static final boolean DEBUG_HANDSHAKE_LAYER = true;
+ private static final boolean DEBUG_KEY_EXCHANGE = false;
+ private static final Logger logger = SystemLogger.SYSTEM;
+
+ // Fields for using this class as a wrapped socket.
+ private Socket underlyingSocket;
+ private int underlyingPort;
+ private boolean autoClose;
+
+ // Cryptography fields.
+ SessionContext sessionContext;
+ Session session;
+ LinkedList handshakeListeners;
+ private boolean clientMode, wantClientAuth, needClientAuth, createSessions;
+ private boolean handshakeDone;
+
+ // I/O fields.
+ private String remoteHost;
+ private InputStream socketIn;
+ private OutputStream socketOut;
+ private InputStream applicationIn;
+ private OutputStream applicationOut;
+ private InputStream handshakeIn;
+ private OutputStream handshakeOut;
+// private ThreadGroup recordLayer;
+ RecordInput recordInput;
+// RecordOutput recordOutput;
+ private long handshakeTime;
+
+ private SocketChannel channel;
+
+ static SortedSet supportedProtocols = new TreeSet();
+ static List supportedSuites = new ArrayList(30);
+
+ // Static initializer.
+ // -------------------------------------------------------------------------
+
+ static
+ {
+ //supportedProtocols.add(ProtocolVersion.TLS_1_1);
+ supportedProtocols.add(ProtocolVersion.TLS_1);
+ supportedProtocols.add(ProtocolVersion.SSL_3);
+
+ // These are in preference order. It's my preference order, but I'm not
+ // a total idiot.
+ supportedSuites.add(CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_RSA_WITH_RC4_128_MD5);
+ supportedSuites.add(CipherSuite.TLS_RSA_WITH_RC4_128_SHA);
+ supportedSuites.add(CipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DHE_RSA_WITH_DES_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_RSA_WITH_DES_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_RSA_EXPORT_WITH_DES40_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5);
+ supportedSuites.add(CipherSuite.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA);
+ supportedSuites.add(CipherSuite.TLS_RSA_WITH_NULL_MD5);
+ supportedSuites.add(CipherSuite.TLS_RSA_WITH_NULL_SHA);
+ }
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ SSLSocket(Socket socket, String host, int port, boolean autoClose)
+ throws IOException
+ {
+ underlyingSocket = socket;
+ remoteHost = host;
+ underlyingPort = port;
+ this.autoClose = autoClose;
+ initialize();
+ }
+
+ SSLSocket (Socket socket, SocketChannel channel) throws IOException
+ {
+ underlyingSocket = socket;
+ this.channel = channel;
+ initialize ();
+ }
+
+ SSLSocket() throws IOException
+ {
+ super();
+ initialize();
+ }
+
+ SSLSocket(InetAddress addr, int port) throws IOException
+ {
+ super(addr, port);
+ initialize();
+ remoteHost = addr.getHostName();
+ if (remoteHost == null)
+ {
+ remoteHost = addr.getHostAddress();
+ }
+ }
+
+ SSLSocket(InetAddress addr, int port, InetAddress laddr, int lport)
+ throws IOException
+ {
+ super(addr, port, laddr, lport);
+ initialize();
+ remoteHost = addr.getHostName();
+ if (remoteHost == null)
+ remoteHost = addr.getHostAddress();
+ }
+
+ SSLSocket(String host, int port) throws IOException
+ {
+ super(host, port);
+ initialize();
+ remoteHost = host;
+ }
+
+ SSLSocket(String host, int port, InetAddress laddr, int lport)
+ throws IOException
+ {
+ super(host, port, laddr, lport);
+ initialize();
+ remoteHost = host;
+ }
+
+ private void initialize()
+ {
+ session = new Session();
+ session.enabledSuites = new ArrayList(supportedSuites);
+ session.enabledProtocols = new TreeSet(supportedProtocols);
+ session.protocol = ProtocolVersion.TLS_1;
+ session.params.setVersion (ProtocolVersion.TLS_1);
+ handshakeListeners = new LinkedList();
+ handshakeDone = false;
+ }
+
+ // SSL methods.
+ // -------------------------------------------------------------------------
+
+ public void addHandshakeCompletedListener(HandshakeCompletedListener l)
+ {
+ synchronized (handshakeListeners)
+ {
+ if (l == null)
+ throw new NullPointerException();
+ if (!handshakeListeners.contains(l))
+ handshakeListeners.add(l);
+ }
+ }
+
+ public void removeHandshakeCompletedListener(HandshakeCompletedListener l)
+ {
+ synchronized (handshakeListeners)
+ {
+ handshakeListeners.remove(l);
+ }
+ }
+
+ public String[] getEnabledProtocols()
+ {
+ synchronized (session.enabledProtocols)
+ {
+ try
+ {
+ return (String[]) Util.transform(session.enabledProtocols.toArray(),
+ String.class, "toString", null);
+ }
+ catch (Exception x)
+ {
+ RuntimeException re = new RuntimeException (x.getMessage());
+ re.initCause (x);
+ throw re;
+ }
+ }
+ }
+
+ public void setEnabledProtocols(String[] protocols)
+ {
+ if (protocols == null || protocols.length == 0)
+ throw new IllegalArgumentException();
+ for (int i = 0; i < protocols.length; i++)
+ {
+ if (!(protocols[i].equalsIgnoreCase("SSLv3") ||
+ protocols[i].equalsIgnoreCase("TLSv1") ||
+ protocols[i].equalsIgnoreCase("TLSv1.1")))
+ {
+ throw new
+ IllegalArgumentException("unsupported protocol: " +
+ protocols[i]);
+ }
+ }
+ synchronized (session.enabledProtocols)
+ {
+ session.enabledProtocols.clear();
+ for (int i = 0; i < protocols.length; i++)
+ {
+ if (protocols[i].equalsIgnoreCase("SSLv3"))
+ {
+ session.enabledProtocols.add(ProtocolVersion.SSL_3);
+ }
+ else if (protocols[i].equalsIgnoreCase("TLSv1"))
+ {
+ session.enabledProtocols.add(ProtocolVersion.TLS_1);
+ }
+ else
+ {
+ session.enabledProtocols.add(ProtocolVersion.TLS_1_1);
+ }
+ }
+ }
+ }
+
+ public String[] getSupportedProtocols()
+ {
+ return new String[] { /* "TLSv1.1", */ "TLSv1", "SSLv3" };
+ }
+
+ public String[] getEnabledCipherSuites()
+ {
+ synchronized (session.enabledSuites)
+ {
+ try
+ {
+ return (String[]) Util.transform(session.enabledSuites.toArray(),
+ String.class, "toString", null);
+ }
+ catch (Exception x)
+ {
+ RuntimeException re = new RuntimeException (x.getMessage());
+ re.initCause (x);
+ throw re;
+ }
+ }
+ }
+
+ public void setEnabledCipherSuites(String[] suites)
+ {
+ if (suites == null || suites.length == 0)
+ throw new IllegalArgumentException();
+ for (int i = 0; i < suites.length; i++)
+ if (CipherSuite.forName(suites[i]) == null)
+ throw new IllegalArgumentException("unsupported suite: " +
+ suites[i]);
+ synchronized (session.enabledSuites)
+ {
+ session.enabledSuites.clear();
+ for (int i = 0; i < suites.length; i++)
+ {
+ CipherSuite suite = CipherSuite.forName(suites[i]);
+ if (!session.enabledSuites.contains(suite))
+ {
+ session.enabledSuites.add(suite);
+ }
+ }
+ }
+ }
+
+ public String[] getSupportedCipherSuites()
+ {
+ return (String[]) CipherSuite.availableSuiteNames().toArray(new String[52]);
+ }
+
+ public SSLSession getSession()
+ {
+ return session;
+ }
+
+ public boolean getEnableSessionCreation()
+ {
+ return createSessions;
+ }
+
+ public void setEnableSessionCreation(boolean flag)
+ {
+ createSessions = flag;
+ }
+
+ public boolean getNeedClientAuth()
+ {
+ return needClientAuth;
+ }
+
+ public void setNeedClientAuth(boolean flag)
+ {
+ needClientAuth = flag;
+ }
+
+ public boolean getWantClientAuth()
+ {
+ return wantClientAuth;
+ }
+
+ public void setWantClientAuth(boolean flag)
+ {
+ wantClientAuth = flag;
+ }
+
+ public boolean getUseClientMode()
+ {
+ return clientMode;
+ }
+
+ public void setUseClientMode(boolean flag)
+ {
+ this.clientMode = flag;
+ }
+
+ public synchronized void startHandshake() throws IOException
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ {
+ logger.log (Component.SSL_HANDSHAKE, "startHandshake called in {0}",
+ Thread.currentThread());
+ handshakeTime = System.currentTimeMillis();
+ }
+ if (handshakeDone)
+ {
+ if (clientMode)
+ {
+ handshakeDone = false;
+ doClientHandshake();
+ }
+ else
+ {
+ Handshake req = new Handshake(Handshake.Type.HELLO_REQUEST, null);
+ req.write (handshakeOut, session.protocol);
+ handshakeOut.flush();
+// recordOutput.setHandshakeAvail(req.write(handshakeOut, session.protocol));
+ }
+ return;
+ }
+ if (recordInput == null)
+ {
+ setupIO();
+ }
+ if (clientMode)
+ {
+ doClientHandshake();
+ }
+ else
+ {
+ doServerHandshake();
+ }
+ }
+
+ // Socket methods.
+ // -------------------------------------------------------------------------
+
+ public InetAddress getInetAddress()
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getInetAddress();
+ }
+ else
+ {
+ return super.getInetAddress();
+ }
+ }
+
+ public InetAddress getLocalAddress()
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getLocalAddress();
+ }
+ else
+ {
+ return super.getLocalAddress();
+ }
+ }
+
+ public int getPort()
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getPort();
+ }
+ else
+ {
+ return super.getPort();
+ }
+ }
+
+ public int getLocalPort()
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getLocalPort();
+ }
+ else
+ {
+ return super.getLocalPort();
+ }
+ }
+
+ public InputStream getInputStream() throws IOException
+ {
+ if (applicationIn == null)
+ {
+ setupIO();
+ }
+ return applicationIn;
+ }
+
+ public OutputStream getOutputStream() throws IOException
+ {
+ if (applicationOut == null)
+ {
+ setupIO();
+ }
+ return applicationOut;
+ }
+
+ public void setTcpNoDelay(boolean flag) throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.setTcpNoDelay(flag);
+ }
+ else
+ {
+ super.setTcpNoDelay(flag);
+ }
+ }
+
+ public boolean getTcpNoDelay() throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getTcpNoDelay();
+ }
+ else
+ {
+ return super.getTcpNoDelay();
+ }
+ }
+
+ public void setSoLinger(boolean flag, int linger) throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.setSoLinger(flag, linger);
+ }
+ else
+ {
+ super.setSoLinger(flag, linger);
+ }
+ }
+
+ public int getSoLinger() throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getSoLinger();
+ }
+ else
+ {
+ return super.getSoLinger();
+ }
+ }
+
+ public void sendUrgentData(int data) throws IOException
+ {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public void setSoTimeout(int timeout) throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.setSoTimeout(timeout);
+ }
+ else
+ {
+ super.setSoTimeout(timeout);
+ }
+ }
+
+ public int getSoTimeout() throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getSoTimeout();
+ }
+ else
+ {
+ return super.getSoTimeout();
+ }
+ }
+
+ public void setSendBufferSize(int size) throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.setSendBufferSize(size);
+ }
+ else
+ {
+ super.setSendBufferSize(size);
+ }
+ }
+
+ public int getSendBufferSize() throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getSendBufferSize();
+ }
+ else
+ {
+ return super.getSendBufferSize();
+ }
+ }
+
+ public void setReceiveBufferSize(int size) throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.setReceiveBufferSize(size);
+ }
+ else
+ {
+ super.setReceiveBufferSize(size);
+ }
+ }
+
+ public int getReceiveBufferSize() throws SocketException
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getReceiveBufferSize();
+ }
+ else
+ {
+ return super.getReceiveBufferSize();
+ }
+ }
+
+ public synchronized void close() throws IOException
+ {
+ if (recordInput == null)
+ {
+ if (underlyingSocket != null)
+ {
+ if (autoClose)
+ underlyingSocket.close();
+ }
+ else
+ super.close();
+ return;
+ }
+// while (recordOutput.applicationDataPending()) Thread.yield();
+ Alert close = new Alert (Alert.Level.WARNING, Alert.Description.CLOSE_NOTIFY);
+ sendAlert (close);
+ long wait = System.currentTimeMillis() + 60000L;
+ while (session.currentAlert == null && !recordInput.pollClose())
+ {
+
+ Thread.yield();
+ if (wait <= System.currentTimeMillis())
+ {
+ break;
+ }
+ }
+ boolean gotClose = session.currentAlert != null &&
+ session.currentAlert.getDescription() == Alert.Description.CLOSE_NOTIFY;
+// recordInput.setRunning(false);
+// recordOutput.setRunning(false);
+// recordLayer.interrupt();
+ recordInput = null;
+// recordOutput = null;
+// recordLayer = null;
+ if (underlyingSocket != null)
+ {
+ if (autoClose)
+ underlyingSocket.close();
+ }
+ else
+ super.close();
+ if (!gotClose)
+ {
+ session.invalidate();
+ throw new SSLException("did not receive close notify");
+ }
+ }
+
+ public String toString()
+ {
+ if (underlyingSocket != null)
+ {
+ return SSLSocket.class.getName() + " [ " + underlyingSocket + " ]";
+ }
+ else
+ {
+ return SSLSocket.class.getName() + " [ " + super.toString() + " ]";
+ }
+ }
+
+ // Configuration insanity begins here.
+
+ public void connect(SocketAddress saddr) throws IOException
+ {
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.connect(saddr);
+ }
+ else
+ {
+ super.connect(saddr);
+ }
+ }
+
+ public void connect(SocketAddress saddr, int timeout) throws IOException
+ {
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.connect(saddr, timeout);
+ }
+ else
+ {
+ super.connect(saddr, timeout);
+ }
+ }
+
+ public void bind(SocketAddress saddr) throws IOException
+ {
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.bind(saddr);
+ }
+ else
+ {
+ super.bind(saddr);
+ }
+ }
+
+ public SocketAddress getLocalSocketAddress()
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.getLocalSocketAddress();
+ }
+ else
+ {
+ return super.getLocalSocketAddress();
+ }
+ }
+
+ public SocketChannel getChannel()
+ {
+ return channel;
+ }
+
+ public boolean isBound()
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.isBound();
+ }
+ else
+ {
+ return super.isBound();
+ }
+ //throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public boolean isClosed()
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.isClosed();
+ }
+ else
+ {
+ return super.isClosed();
+ }
+ //throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ //public SocketAddress getRemoteSocketAddress()
+ //{
+ // if (underlyingSocket != null)
+ // {
+ // return underlyingSocket.getRemoteSocketAddress();
+ // }
+ // else
+ // {
+ // return super.getRemoteSocketAddress();
+ // }
+ //}
+
+ public void setOOBInline(boolean flag) throws SocketException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // underlyingSocket.setOOBInline(flag);
+ // }
+ //else
+ // {
+ // super.setOOBInline(flag);
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public boolean getOOBInline() throws SocketException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // return underlyingSocket.getOOBInline();
+ // }
+ //else
+ // {
+ // return super.getOOBInline();
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public void setKeepAlive(boolean flag) throws SocketException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // underlyingSocket.setKeepAlive(flag);
+ // }
+ //else
+ // {
+ // super.setKeepAlive(flag);
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public boolean getKeepAlive() throws SocketException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // return underlyingSocket.getKeepAlive();
+ // }
+ //else
+ // {
+ // return super.getKeepAlive();
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public void setTrafficClass(int clazz) throws SocketException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // underlyingSocket.setTrafficClass(clazz);
+ // }
+ //else
+ // {
+ // super.setTrafficClass(clazz);
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public int getTrafficClass() throws SocketException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // return underlyingSocket.getTrafficClass();
+ // }
+ //else
+ // {
+ // return super.getTrafficClass();
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public void setReuseAddress(boolean flag) throws SocketException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // underlyingSocket.setReuseAddress(flag);
+ // }
+ //else
+ // {
+ // super.setReuseAddress(flag);
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public boolean getReuseAddress() throws SocketException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // return underlyingSocket.getReuseAddress();
+ // }
+ //else
+ // {
+ // return super.getReuseAddress();
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public void shutdownInput() throws IOException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // underlyingSocket.shutdownInput();
+ // }
+ //else
+ // {
+ // super.shutdownInput();
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public void shutdownOutput() throws IOException
+ {
+ //if (underlyingSocket != null)
+ // {
+ // underlyingSocket.shutdownOutput();
+ // }
+ //else
+ // {
+ // super.shutdownOutput();
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public boolean isConnected()
+ {
+ if (underlyingSocket != null)
+ {
+ return underlyingSocket.isConnected();
+ }
+ else
+ {
+ return super.isConnected();
+ }
+ //throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public boolean isInputShutdown()
+ {
+ //if (underlyingSocket != null)
+ // {
+ // return underlyingSocket.isInputShutdown();
+ // }
+ //else
+ // {
+ // return super.isInputShutdown();
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ public boolean isOutputShutdown()
+ {
+ //if (underlyingSocket != null)
+ // {
+ // return underlyingSocket.isOutputShutdown();
+ // }
+ //else
+ // {
+ // return super.isOutputShutdown();
+ // }
+ throw new UnsupportedOperationException("1.4 methods not enabled");
+ }
+
+ protected void finalize()
+ {
+ if (session.currentAlert == null)
+ {
+ try
+ {
+ close();
+ }
+ catch (Exception ignore) { }
+ }
+ }
+
+ // Package methods.
+ // -------------------------------------------------------------------------
+
+ void setSessionContext(SessionContext sessionContext)
+ {
+ this.sessionContext = sessionContext;
+ }
+
+ void setEnabledCipherSuites(List suites)
+ {
+ session.enabledSuites = suites;
+ }
+
+ void setEnabledProtocols(SortedSet protocols)
+ {
+ session.enabledProtocols = protocols;
+ }
+
+ void setSRPTrustManager(SRPTrustManager srpTrustManager)
+ {
+ session.srpTrustManager = srpTrustManager;
+ }
+
+ void setTrustManager(X509TrustManager trustManager)
+ {
+ session.trustManager = trustManager;
+ }
+
+ void setKeyManager(X509KeyManager keyManager)
+ {
+ session.keyManager = keyManager;
+ }
+
+ void setRandom(SecureRandom random)
+ {
+ session.random = random;
+ }
+
+ void sendAlert (Alert alert) throws IOException
+ {
+ RecordOutputStream out =
+ new RecordOutputStream (socketOut, ContentType.ALERT, session.params);
+ out.write (alert.getEncoded ());
+ }
+
+ /**
+ * Gets the most-recently-received alert message.
+ *
+ * @return The alert message.
+ */
+ Alert checkAlert()
+ {
+ return session.currentAlert;
+ }
+
+ synchronized void checkHandshakeDone() throws IOException
+ {
+ if (!handshakeDone)
+ {
+ startHandshake();
+ }
+ Alert alert = session.currentAlert;
+ if (alert != null && alert.getLevel() == Alert.Level.FATAL)
+ {
+ throw new AlertException(alert, false);
+ }
+ if (handshakeIn.available() > 0 && !clientMode)
+ {
+ handshakeDone = false;
+ startHandshake();
+ }
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private static final byte[] SENDER_CLIENT =
+ new byte[] { 0x43, 0x4C, 0x4E, 0x54 };
+ private static final byte[] SENDER_SERVER =
+ new byte[] { 0x53, 0x52, 0x56, 0x52 };
+
+ private void changeCipherSpec () throws IOException
+ {
+ RecordOutputStream out =
+ new RecordOutputStream (socketOut, ContentType.CHANGE_CIPHER_SPEC, session.params);
+ out.write (1);
+ }
+
+ private void readChangeCipherSpec () throws IOException
+ {
+ RecordInputStream in =
+ new RecordInputStream (recordInput, ContentType.CHANGE_CIPHER_SPEC);
+ if (in.read() != 1)
+ {
+ throw new SSLProtocolException ("bad change cipher spec message");
+ }
+ }
+
+ /**
+ * Initializes the application data streams and starts the record layer
+ * threads.
+ */
+ private synchronized void setupIO() throws IOException
+ {
+ if (recordInput != null)
+ {
+ return;
+ }
+ if (underlyingSocket != null)
+ {
+ socketIn = underlyingSocket.getInputStream();
+ socketOut = underlyingSocket.getOutputStream();
+ }
+ else
+ {
+ socketIn = super.getInputStream();
+ socketOut = super.getOutputStream();
+ }
+// recordLayer = new ThreadGroup("record_layer");
+// recordInput = new RecordInput(in, session, recordLayer);
+// recordOutput = new RecordOutput(out, session, recordLayer);
+// recordInput.setRecordOutput(recordOutput);
+// recordLayer.setDaemon(true);
+// recordInput.start();
+// recordOutput.start();
+ recordInput = new RecordInput (socketIn, session);
+ applicationIn = new SSLSocketInputStream(
+ new RecordInputStream (recordInput, ContentType.APPLICATION_DATA), this);
+ applicationOut = new SSLSocketOutputStream(
+ new RecordOutputStream (socketOut, ContentType.APPLICATION_DATA, session.params), this);
+ handshakeIn = new SSLSocketInputStream(
+ new RecordInputStream (recordInput, ContentType.HANDSHAKE), this, false);
+ handshakeOut = new BufferedOutputStream (new SSLSocketOutputStream(
+ new RecordOutputStream (socketOut, ContentType.HANDSHAKE, session.params), this, false), 8096);
+ }
+
+ private void handshakeCompleted ()
+ {
+ handshakeDone = true;
+ HandshakeCompletedEvent event = new HandshakeCompletedEvent (this, session);
+ for (Iterator it = handshakeListeners.iterator (); it.hasNext (); )
+ {
+ try
+ {
+ ((HandshakeCompletedListener) it.next ()).handshakeCompleted (event);
+ }
+ catch (Throwable t) { }
+ }
+ if (createSessions)
+ {
+ synchronized (session)
+ {
+ sessionContext.addSession (session.sessionId, session);
+ session.access ();
+ }
+ }
+
+ if (DEBUG_HANDSHAKE_LAYER)
+ {
+ logger.log (Component.SSL_HANDSHAKE, "Handshake finished in {0}",
+ Thread.currentThread());
+ handshakeTime = System.currentTimeMillis() - handshakeTime;
+ logger.log (Component.SSL_HANDSHAKE, "Elapsed time {0}s",
+ new Long (handshakeTime / 1000));
+ }
+ }
+
+ /*
+ * Perform the client handshake. The process looks like this:
+ *
+ * ClientHello -->
+ * ServerHello <--
+ * Certificate* <--
+ * ServerKeyExchange* <--
+ * CertificateRequest* <--
+ * ServerHelloDone* <--
+ * Certificate* -->
+ * ClientKeyExchange -->
+ * CertificateVerify* -->
+ * [ChangeCipherSpec] -->
+ * Finished -->
+ * [ChangeCipherSpec] <--
+ * Finished <--
+ *
+ * With --> denoting output and <-- denoting input. * denotes optional
+ * messages.
+ *
+ * Alternatively, this may be an abbreviated handshake if we are resuming
+ * a session:
+ *
+ * ClientHello -->
+ * ServerHello <--
+ * [ChangeCipherSpec] <--
+ * Finished <--
+ * [ChangeCipherSpec] -->
+ * Finished -->
+ */
+ private void doClientHandshake() throws IOException
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ {
+ logger.log (Component.SSL_HANDSHAKE, "starting client handshake in {0}",
+ Thread.currentThread());
+ }
+
+ IMessageDigest md5 = HashFactory.getInstance(Registry.MD5_HASH);
+ IMessageDigest sha = HashFactory.getInstance(Registry.SHA160_HASH);
+ DigestInputStream din = new DigestInputStream(handshakeIn, md5, sha);
+ DigestOutputStream dout = new DigestOutputStream(handshakeOut, md5, sha);
+ Session continuedSession = null;
+ byte[] sessionId = new byte[0];
+ List extensions = null;
+ String user = null;
+ CertificateType certType = CertificateType.X509;
+
+ // Look through the available sessions to see if an appropriate one is
+ // available.
+ for (Enumeration e = sessionContext.getIds(); e.hasMoreElements(); )
+ {
+ byte[] id = (byte[]) e.nextElement();
+ continuedSession = (Session) sessionContext.getSession(id);
+ if (continuedSession == null)
+ {
+ continue;
+ }
+ if (!session.enabledProtocols.contains(continuedSession.protocol))
+ {
+ continue;
+ }
+ if (continuedSession.getPeerHost().equals(remoteHost))
+ {
+ sessionId = id;
+ break;
+ }
+ }
+
+ // If a SRP suite is enabled, ask for a username so we can include it
+ // with our extensions list.
+ for (Iterator i = session.enabledSuites.iterator(); i.hasNext(); )
+ {
+ CipherSuite s = (CipherSuite) i.next();
+ if (s.getKeyExchange() == "SRP")
+ {
+ extensions = new LinkedList();
+ user = askUserName(remoteHost);
+ byte[] b = user.getBytes("UTF-8");
+ if (b.length > 255)
+ {
+ handshakeFailure();
+ throw new SSLException("SRP username too long");
+ }
+ extensions.add(new Extension(Extension.Type.SRP,
+ Util.concat(new byte[] { (byte) b.length }, b)));
+
+ break;
+ }
+ }
+
+ // If the jessie.fragment.length property is set, add the appropriate
+ // extension to the list. The fragment length is only actually set if
+ // the server responds with the same extension.
+ try
+ {
+ int flen = Integer.parseInt(Util.getSecurityProperty("jessie.fragment.length"));
+ byte[] ext = new byte[1];
+ if (flen == 512)
+ ext[0] = 1;
+ else if (flen == 1024)
+ ext[0] = 2;
+ else if (flen == 2048)
+ ext[0] = 3;
+ else if (flen == 4096)
+ ext[0] = 4;
+ else
+ throw new NumberFormatException();
+ if (extensions == null)
+ extensions = new LinkedList();
+ extensions.add(new Extension(Extension.Type.MAX_FRAGMENT_LENGTH, ext));
+ }
+ catch (NumberFormatException nfe) { }
+
+ // FIXME: set certificate types.
+
+ // Send the client hello.
+ ProtocolVersion version = session.protocol;
+ Random clientRandom =
+ new Random(Util.unixTime(), session.random.generateSeed(28));
+ session.protocol = (ProtocolVersion) session.enabledProtocols.last();
+ List comp = new ArrayList(2);
+ comp.add(CompressionMethod.ZLIB);
+ comp.add(CompressionMethod.NULL);
+ ClientHello clientHello =
+ new ClientHello(session.protocol, clientRandom, sessionId,
+ session.enabledSuites, comp, extensions);
+ Handshake msg = new Handshake(Handshake.Type.CLIENT_HELLO, clientHello);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write (dout, version);
+// recordOutput.setHandshakeAvail(msg.write(dout, version));
+ dout.flush();
+// try
+// {
+// Thread.sleep(150);
+// }
+// catch (InterruptedException ie)
+// {
+// }
+
+ // Receive the server hello.
+ msg = Handshake.read(din);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ if (msg.getType() != Handshake.Type.SERVER_HELLO)
+ {
+ throwUnexpectedMessage();
+ }
+ ServerHello serverHello = (ServerHello) msg.getBody();
+ Random serverRandom = serverHello.getRandom();
+ version = serverHello.getVersion();
+
+ // If we don't directly support the server's protocol version, choose
+ // the highest one we support that is less than the server's version.
+ if (!session.enabledProtocols.contains(version))
+ {
+ ProtocolVersion v1 = null, v2 = null;
+ for (Iterator it = session.enabledProtocols.iterator();
+ it.hasNext(); )
+ {
+ v1 = (ProtocolVersion) it.next();
+ if (v1.compareTo(version) > 0)
+ break;
+ v2 = v1;
+ }
+ version = v1;
+ }
+
+ // The server's version is either unsupported by us (unlikely) or the user
+ // has only enabled incompatible versions.
+ if (version == null)
+ {
+ Alert.Description desc = null;
+ if (serverHello.getVersion() == ProtocolVersion.SSL_3)
+ {
+ desc = Alert.Description.HANDSHAKE_FAILURE;
+ }
+ else
+ {
+ desc = Alert.Description.PROTOCOL_VERSION;
+ }
+ Alert alert = new Alert(Alert.Level.FATAL, desc);
+ sendAlert(alert);
+ session.currentAlert = alert;
+ fatal();
+ throw new AlertException(alert, true);
+ }
+
+ if (serverHello.getExtensions() != null)
+ {
+ for (Iterator it = serverHello.getExtensions().iterator();
+ it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (e.getType() == Extension.Type.MAX_FRAGMENT_LENGTH)
+ {
+ int len = Extensions.getMaxFragmentLength(e).intValue();
+ session.params.setFragmentLength(len);
+// recordOutput.setFragmentLength(len);
+// recordInput.setFragmentLength(len);
+ }
+ else if (e.getType() == Extension.Type.CERT_TYPE)
+ {
+ certType = Extensions.getServerCertType(e);
+ }
+ }
+ }
+
+ CipherSuite suite = serverHello.getCipherSuite().resolve(version);
+ boolean newSession = true;
+ if (sessionId.length > 0 &&
+ Arrays.equals(sessionId, serverHello.getSessionId()))
+ {
+ SecurityParameters params = session.params;
+ SecureRandom random = session.random;
+ session = (Session) continuedSession.clone();
+ session.params = params;
+ session.random = random;
+ recordInput.setSession(session);
+// recordOutput.setSession(session);
+ suite = session.cipherSuite;
+ newSession = false;
+ }
+ else
+ {
+ sessionContext.removeSession(new Session.ID(sessionId));
+ }
+ if (newSession)
+ {
+ session.peerHost = remoteHost;
+ session.sessionId = new Session.ID(serverHello.getSessionId());
+ session.cipherSuite = suite;
+ }
+ session.params.reset();
+// session.params.setInMac(null);
+// session.params.setOutMac(null);
+// session.params.setInRandom(null);
+// session.params.setOutRandom(null);
+// session.params.setInCipher(null);
+// session.params.setOutCipher(null);
+ session.currentAlert = null;
+ session.valid = true;
+ session.protocol = version;
+
+ // If the server responded with the same session id that we sent, we
+ // assume that the session will be continued, and skip the bulk of the
+ // handshake.
+ if (newSession)
+ {
+ PublicKey serverKey = null, serverKex = null;
+ KeyPair clientKeys = null, clientKex = null;
+ CertificateRequest certReq;
+ boolean sendKeyExchange = false;
+ BigInteger srp_x = null;
+ IKeyAgreementParty clientKA = null;
+ IncomingMessage in; // used for key agreement protocol exchange
+ OutgoingMessage out = null;
+
+ if (suite.getKeyExchange() == "SRP")
+ {
+ String password = askPassword(user);
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE,
+ "SRP: password read is ''{0}''", password);
+ }
+ byte[] userSrpPassword = password.getBytes("UTF-8");
+
+ // instantiate and setup client-side key agreement party
+ clientKA = KeyAgreementFactory.getPartyAInstance(Registry.SRP_TLS_KA);
+ Map clientAttributes = new HashMap();
+ clientAttributes.put(SRP6KeyAgreement.HASH_FUNCTION,
+ Registry.SHA160_HASH);
+ clientAttributes.put(SRP6KeyAgreement.USER_IDENTITY, user);
+ clientAttributes.put(SRP6KeyAgreement.USER_PASSWORD, userSrpPassword);
+ try
+ {
+ clientKA.init(clientAttributes);
+ // initiate the exchange
+ out = clientKA.processMessage(null);
+ }
+ catch (KeyAgreementException x)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
+ }
+ throwHandshakeFailure();
+ }
+ }
+
+ if (suite.getSignature() != "anon")
+ {
+ msg = Handshake.read(din, certType);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ if (msg.getType() != Handshake.Type.CERTIFICATE)
+ {
+ throwUnexpectedMessage();
+ }
+ Certificate serverCertificate = (Certificate) msg.getBody();
+ X509Certificate[] peerCerts = serverCertificate.getCertificates();
+ try
+ {
+ session.trustManager.checkServerTrusted(peerCerts,
+ suite.getAuthType());
+ if (suite.getSignature() == "RSA" &&
+ !(peerCerts[0].getPublicKey() instanceof RSAPublicKey))
+ throw new InvalidKeyException("improper public key");
+ if (suite.getKeyExchange() == "DH" &&
+ !(peerCerts[0].getPublicKey() instanceof DHPublicKey))
+ throw new InvalidKeyException("improper public key");
+ if (suite.getKeyExchange() == "DHE")
+ {
+ if (suite.getSignature() == "RSA" &&
+ !(peerCerts[0].getPublicKey() instanceof RSAPublicKey))
+ throw new InvalidKeyException("improper public key");
+ if (suite.getSignature() == "DSS" &&
+ !(peerCerts[0].getPublicKey() instanceof DSAPublicKey))
+ throw new InvalidKeyException("improper public key");
+ }
+ session.peerCerts = peerCerts;
+ session.peerVerified = true;
+ }
+ catch (InvalidKeyException ike)
+ {
+ throwHandshakeFailure();
+ }
+ catch (Exception x)
+ {
+ if (!checkCertificates(peerCerts))
+ {
+ peerUnverified(peerCerts);
+ SSLPeerUnverifiedException e =
+ new SSLPeerUnverifiedException ("could not verify peer certificate: "+
+ peerCerts[0].getSubjectDN());
+ e.initCause (x);
+ throw e;
+ }
+ session.peerCerts = peerCerts;
+ session.peerVerified = true;
+ }
+ serverKey = peerCerts[0].getPublicKey();
+ serverKex = serverKey;
+ }
+
+ msg = Handshake.read(din, suite, serverKey);
+
+ // Receive the server's key exchange.
+ if (msg.getType() == Handshake.Type.SERVER_KEY_EXCHANGE)
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ ServerKeyExchange skex = (ServerKeyExchange) msg.getBody();
+ serverKex = skex.getPublicKey();
+ if (suite.getSignature() != "anon")
+ {
+ ISignature sig = null;
+ if (suite.getSignature() == "RSA")
+ {
+ sig = new SSLRSASignature();
+ }
+ else if (suite.getSignature() == "DSS")
+ {
+ sig = SignatureFactory.getInstance(Registry.DSS_SIG);
+ }
+ sig.setupVerify(Collections.singletonMap(
+ ISignature.VERIFIER_KEY, serverKey));
+ byte[] buf = clientRandom.getEncoded();
+ sig.update(buf, 0, buf.length);
+ buf = serverRandom.getEncoded();
+ sig.update(buf, 0, buf.length);
+ if (suite.getKeyExchange() == "RSA")
+ {
+ updateSig(sig, ((RSAPublicKey) serverKex).getModulus());
+ updateSig(sig, ((RSAPublicKey) serverKex).getPublicExponent());
+ }
+ else if (suite.getKeyExchange() == "DHE")
+ {
+ updateSig(sig, ((DHPublicKey) serverKex).getParams().getP());
+ updateSig(sig, ((DHPublicKey) serverKex).getParams().getG());
+ updateSig(sig, ((DHPublicKey) serverKex).getY());
+ }
+ else if (suite.getKeyExchange() == "SRP")
+ {
+ updateSig(sig, ((SRPPublicKey) serverKex).getN());
+ updateSig(sig, ((SRPPublicKey) serverKex).getG());
+ byte[] srpSalt = skex.getSRPSalt();
+ sig.update((byte) srpSalt.length);
+ sig.update(srpSalt, 0, srpSalt.length);
+ updateSig(sig, ((SRPPublicKey) serverKex).getY());
+ }
+ if (!sig.verify(skex.getSignature().getSigValue()))
+ {
+ throwHandshakeFailure();
+ }
+ }
+
+ if (suite.getKeyExchange() == "SRP")
+ {
+ // use server's key exchange data to continue
+ // agreement protocol by faking a received incoming
+ // message. again the following code can be broken
+ // into multiple blocks for more accurate exception
+ // handling
+ try
+ {
+ out = new OutgoingMessage();
+ out.writeMPI(((SRPPublicKey) serverKex).getN());
+ out.writeMPI(((SRPPublicKey) serverKex).getG());
+ out.writeMPI(new BigInteger(1, skex.getSRPSalt()));
+ out.writeMPI(((SRPPublicKey) serverKex).getY());
+
+ in = new IncomingMessage(out.toByteArray());
+
+ out = clientKA.processMessage(in);
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "clientKA isComplete? {0}",
+ Boolean.valueOf (clientKA.isComplete()));
+ }
+ }
+ catch (KeyAgreementException x)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
+ }
+ throwHandshakeFailure();
+ }
+ }
+ msg = Handshake.read(din, suite, serverKey);
+ }
+
+ // See if the server wants us to send our certificates.
+ certReq = null;
+ if (msg.getType() == Handshake.Type.CERTIFICATE_REQUEST)
+ {
+ if (suite.getSignature() == "anon")
+ {
+ throwHandshakeFailure();
+ }
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ certReq = (CertificateRequest) msg.getBody();
+ msg = Handshake.read(din);
+ }
+
+ // Read ServerHelloDone.
+ if (msg.getType() != Handshake.Type.SERVER_HELLO_DONE)
+ {
+ throwUnexpectedMessage();
+ }
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+
+ // Send our certificate chain if the server asked for it.
+ if (certReq != null)
+ {
+ String alias = session.keyManager.chooseClientAlias(
+ certReq.getTypeStrings(), certReq.getAuthorities(), null);
+ if (alias == null && version == ProtocolVersion.SSL_3)
+ {
+ Alert alert =
+ new Alert(Alert.Level.WARNING, Alert.Description.NO_CERTIFICATE);
+ sendAlert(alert);
+ }
+ else
+ {
+ X509Certificate[] chain =
+ session.keyManager.getCertificateChain(alias);
+ PrivateKey key = session.keyManager.getPrivateKey(alias);
+ if (chain == null)
+ {
+ chain = new X509Certificate[0];
+ }
+ Certificate cert = new Certificate(chain);
+ msg = new Handshake(Handshake.Type.CERTIFICATE, cert);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+// recordOutput.setHandshakeAvail(msg.write(dout, version));;
+ dout.flush();
+ if (chain.length > 0)
+ {
+ session.localCerts = chain;
+ clientKeys = new KeyPair(chain[0].getPublicKey(), key);
+ }
+ }
+ }
+
+ // Send our key exchange.
+ byte[] preMasterSecret = null;
+ ClientKeyExchange ckex = null;
+ if (suite.getKeyExchange() == "RSA")
+ {
+ ProtocolVersion v =
+ (ProtocolVersion) session.enabledProtocols.last();
+ byte[] b = new byte[46];
+ session.random.nextBytes (b);
+ preMasterSecret = Util.concat(v.getEncoded(), b);
+ EME_PKCS1_V1_5 pkcs1 = EME_PKCS1_V1_5.getInstance((RSAPublicKey) serverKex);
+ BigInteger bi = new BigInteger(1,
+ pkcs1.encode(preMasterSecret, session.random));
+ bi = RSA.encrypt((RSAPublicKey) serverKex, bi);
+ ckex = new ClientKeyExchange(Util.trim(bi));
+ }
+ else if (suite.getKeyExchange().startsWith("DH"))
+ {
+ if (clientKeys == null ||
+ !(clientKeys.getPublic() instanceof DHPublicKey))
+ {
+ GnuDHPrivateKey tmpKey =
+ new GnuDHPrivateKey(null, ((DHPublicKey) serverKex).getParams().getP(),
+ ((DHPublicKey) serverKex).getParams().getG(), null);
+ clientKA = KeyAgreementFactory.getPartyBInstance(Registry.DH_KA);
+ Map attr = new HashMap();
+ attr.put(DiffieHellmanKeyAgreement.KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY,
+ tmpKey);
+ attr.put(DiffieHellmanKeyAgreement.SOURCE_OF_RANDOMNESS,
+ session.random);
+ try
+ {
+ clientKA.init(attr);
+ out = new OutgoingMessage();
+ out.writeMPI(((DHPublicKey) serverKex).getY());
+ in = new IncomingMessage(out.toByteArray());
+ out = clientKA.processMessage(in);
+ in = new IncomingMessage(out.toByteArray());
+ ckex = new ClientKeyExchange(in.readMPI());
+ }
+ catch (KeyAgreementException kae)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
+ }
+ internalError();
+ RuntimeException re = new RuntimeException (kae.getMessage());
+ re.initCause (kae);
+ throw re;
+ }
+ }
+ else
+ {
+ clientKA = KeyAgreementFactory.getPartyBInstance(Registry.ELGAMAL_KA);
+ Map attr = new HashMap();
+ attr.put(ElGamalKeyAgreement.KA_ELGAMAL_RECIPIENT_PRIVATE_KEY,
+ clientKeys.getPrivate());
+ try
+ {
+ // The key exchange is already complete here; our public
+ // value was sent with our certificate.
+ clientKA.init(attr);
+ }
+ catch (KeyAgreementException kae)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
+ internalError();
+ RuntimeException re = new RuntimeException (kae.getMessage());
+ re.initCause (kae);
+ throw re;
+ }
+ ckex = new ClientKeyExchange(new byte[0]);
+ }
+ }
+ else if (suite.getKeyExchange() == "SRP")
+ {
+ // at this point, out --the outgoing message-- already contains
+ // what we want. so...
+ BigInteger A = null;
+ try
+ {
+ in = new IncomingMessage(out.toByteArray());
+ A = in.readMPI();
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "client A:{0}", A);
+ }
+ }
+ catch (KeyAgreementException x)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
+ }
+ throwHandshakeFailure();
+ }
+ ckex = new ClientKeyExchange(A);
+ }
+ msg = new Handshake(Handshake.Type.CLIENT_KEY_EXCHANGE, ckex);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write (dout, version);
+// recordOutput.setHandshakeAvail(msg.write(dout, version));;
+
+ // Generate the master secret.
+ if (suite.getKeyExchange().startsWith("DH"))
+ {
+ try
+ {
+ preMasterSecret = clientKA.getSharedSecret();
+ }
+ catch (KeyAgreementException kae)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
+ }
+ internalError();
+ RuntimeException re = new RuntimeException (kae.getMessage());
+ re.initCause (kae);
+ throw re;
+ }
+ }
+ else if (suite.getKeyExchange() == "SRP")
+ {
+ try
+ {
+ preMasterSecret = clientKA.getSharedSecret();
+ }
+ catch (KeyAgreementException x)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
+ }
+ throwHandshakeFailure();
+ }
+ finally
+ {
+ clientKA = null;
+ }
+ }
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "preMasterSecret:\n{0}",
+ Util.toHexString (preMasterSecret, ':'));
+ logger.log (Component.SSL_KEY_EXCHANGE, "client.random:\n{0}",
+ Util.toHexString(clientRandom.getEncoded(), ':'));
+ logger.log (Component.SSL_KEY_EXCHANGE, "server.random:\n{0}",
+ Util.toHexString(serverRandom.getEncoded(), ':'));
+ }
+ IRandom genSecret = null;
+ if (version == ProtocolVersion.SSL_3)
+ {
+ genSecret = new SSLRandom();
+ HashMap attr = new HashMap();
+ attr.put(SSLRandom.SECRET, preMasterSecret);
+ attr.put(SSLRandom.SEED,
+ Util.concat(clientRandom.getEncoded(), serverRandom.getEncoded()));
+ genSecret.init(attr);
+ }
+ else
+ {
+ genSecret = new TLSRandom();
+ HashMap attr = new HashMap();
+ attr.put(TLSRandom.SECRET, preMasterSecret);
+ attr.put(TLSRandom.SEED,
+ Util.concat(("master secret").getBytes("UTF-8"),
+ Util.concat(clientRandom.getEncoded(), serverRandom.getEncoded())));
+ genSecret.init(attr);
+ }
+ session.masterSecret = new byte[48];
+ try
+ {
+ genSecret.nextBytes(session.masterSecret, 0, 48);
+ for (int i = 0; i < preMasterSecret.length; i++)
+ {
+ preMasterSecret[i] = 0;
+ }
+ }
+ catch (LimitReachedException shouldNotHappen)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException (shouldNotHappen.getMessage());
+ re.initCause (shouldNotHappen);
+ throw re;
+ }
+
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "masterSecret: {0}",
+ Util.toHexString(session.masterSecret, ':'));
+ }
+
+ // Send our certificate verify message.
+ if (certReq != null && clientKeys != null)
+ {
+ IMessageDigest vMD5 = (IMessageDigest) md5.clone();
+ IMessageDigest vSHA = (IMessageDigest) sha.clone();
+ PrivateKey key = clientKeys.getPrivate();
+ Object sig = null;
+ String sigAlg = null;
+ try
+ {
+ if (key instanceof DSAPrivateKey)
+ {
+ sig = DSSSignature.sign((DSAPrivateKey) key, vSHA.digest(),
+ session.random);
+ sigAlg = "DSS";
+ }
+ else if (key instanceof RSAPrivateKey)
+ {
+ SSLRSASignature rsa = new SSLRSASignature(vMD5, vSHA);
+ rsa.setupSign(Collections.singletonMap(ISignature.SIGNER_KEY, key));
+ sig = rsa.sign();
+ sigAlg = "RSA";
+ }
+ else
+ {
+ throw new InvalidKeyException("no appropriate key");
+ }
+ }
+ catch (Exception x)
+ {
+ throwHandshakeFailure();
+ }
+ CertificateVerify verify = new CertificateVerify(sig, sigAlg);
+ msg = new Handshake(Handshake.Type.CERTIFICATE_VERIFY, verify);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+// recordOutput.setHandshakeAvail(msg.write(dout, version));;
+ }
+ dout.flush();
+ }
+
+ byte[][] keys = null;
+ try
+ {
+ keys = generateKeys(serverRandom.getEncoded(),
+ clientRandom.getEncoded(), version);
+ }
+ catch (Exception x)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException (x.getMessage());
+ re.initCause (x);
+ throw re;
+ }
+
+ session.params.setVersion (version);
+
+ // Initialize the algorithms with the derived keys.
+ Object readMac = null, writeMac = null;
+ Object readCipher = null, writeCipher = null;
+ try
+ {
+ if (session.params instanceof GNUSecurityParameters)
+ {
+ HashMap attr = new HashMap();
+ writeMac = CipherSuite.getMac(suite.getMac());
+ readMac = CipherSuite.getMac(suite.getMac());
+ attr.put(IMac.MAC_KEY_MATERIAL, keys[0]);
+ ((IMac) writeMac).init(attr);
+ attr.put(IMac.MAC_KEY_MATERIAL, keys[1]);
+ ((IMac) readMac).init(attr);
+ if (suite.getCipher() == "RC4")
+ {
+ writeCipher = new ARCFour();
+ readCipher = new ARCFour();
+ attr.clear();
+ attr.put(ARCFour.ARCFOUR_KEY_MATERIAL, keys[2]);
+ ((ARCFour) writeCipher).init(attr);
+ attr.put(ARCFour.ARCFOUR_KEY_MATERIAL, keys[3]);
+ ((ARCFour) readCipher).init(attr);
+ }
+ else if (!suite.isStreamCipher())
+ {
+ writeCipher = CipherSuite.getCipher(suite.getCipher());
+ readCipher = CipherSuite.getCipher(suite.getCipher());
+ attr.clear();
+ attr.put(IMode.KEY_MATERIAL, keys[2]);
+ attr.put(IMode.IV, keys[4]);
+ attr.put(IMode.STATE, new Integer(IMode.ENCRYPTION));
+ ((IMode) writeCipher).init(attr);
+ attr.put(IMode.KEY_MATERIAL, keys[3]);
+ attr.put(IMode.IV, keys[5]);
+ attr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
+ ((IMode) readCipher).init(attr);
+ }
+ }
+ else // JCESecurityParameters
+ {
+ writeMac = CipherSuite.getJCEMac (suite.getMac());
+ readMac = CipherSuite.getJCEMac (suite.getMac());
+ writeCipher = CipherSuite.getJCECipher (suite.getCipher());
+ readCipher = CipherSuite.getJCECipher (suite.getCipher());
+ ((Mac) writeMac).init (new SecretKeySpec (keys[0], suite.getMac()));
+ ((Mac) readMac).init (new SecretKeySpec (keys[1], suite.getMac()));
+ if (!suite.isStreamCipher())
+ {
+ ((Cipher) writeCipher).init (Cipher.ENCRYPT_MODE,
+ new SecretKeySpec (keys[2], suite.getCipher()),
+ new IvParameterSpec (keys[4]));
+ ((Cipher) readCipher).init (Cipher.DECRYPT_MODE,
+ new SecretKeySpec (keys[3], suite.getCipher()),
+ new IvParameterSpec (keys[5]));
+ }
+ else
+ {
+ ((Cipher) writeCipher).init (Cipher.ENCRYPT_MODE,
+ new SecretKeySpec (keys[2], suite.getCipher()));
+ ((Cipher) readCipher).init (Cipher.DECRYPT_MODE,
+ new SecretKeySpec (keys[3], suite.getCipher()));
+ }
+ }
+ }
+ // These should technically never happen, if our key generation is not
+ // broken.
+ catch (InvalidKeyException ike)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException (ike.getMessage());
+ re.initCause(ike);
+ throw re;
+ }
+ catch (InvalidAlgorithmParameterException iape)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException (iape.getMessage());
+ re.initCause (iape);
+ throw re;
+ }
+ // These indicate a configuration error with the JCA.
+ catch (NoSuchAlgorithmException nsae)
+ {
+ session.enabledSuites.remove (suite);
+ internalError();
+ SSLException x = new SSLException ("suite " + suite + " not available in this configuration");
+ x.initCause (nsae);
+ throw x;
+ }
+ catch (NoSuchPaddingException nspe)
+ {
+ session.enabledSuites.remove (suite);
+ internalError();
+ SSLException x = new SSLException ("suite " + suite + " not available in this configuration");
+ x.initCause (nspe);
+ throw x;
+ }
+
+ Finished finis = null;
+
+ if (newSession)
+ {
+ changeCipherSpec();
+ session.params.setDeflating(serverHello.getCompressionMethod() == CompressionMethod.ZLIB);
+ session.params.setOutMac(writeMac);
+ session.params.setOutCipher(writeCipher);
+ finis = generateFinished(version, (IMessageDigest) md5.clone(),
+ (IMessageDigest) sha.clone(), true);
+ msg = new Handshake(Handshake.Type.FINISHED, finis);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+ dout.flush();
+ }
+
+ if (session.currentAlert != null &&
+ session.currentAlert.getLevel() == Alert.Level.FATAL)
+ {
+ fatal();
+ throw new AlertException(session.currentAlert, false);
+ }
+
+ synchronized (session.params)
+ {
+ readChangeCipherSpec ();
+ session.params.setInflating(serverHello.getCompressionMethod() == CompressionMethod.ZLIB);
+ session.params.setInMac(readMac);
+ session.params.setInCipher(readCipher);
+ session.params.notifyAll();
+ }
+
+ Finished verify = generateFinished(version, (IMessageDigest) md5.clone(),
+ (IMessageDigest) sha.clone(), false);
+
+ msg = Handshake.read(din, suite, null);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ if (msg.getType() != Handshake.Type.FINISHED)
+ {
+ throwUnexpectedMessage();
+ }
+ finis = (Finished) msg.getBody();
+ if (version == ProtocolVersion.SSL_3)
+ {
+ if (!Arrays.equals(finis.getMD5Hash(), verify.getMD5Hash()) ||
+ !Arrays.equals(finis.getSHAHash(), verify.getSHAHash()))
+ {
+ throwHandshakeFailure();
+ }
+ }
+ else
+ {
+ if (!Arrays.equals(finis.getVerifyData(), verify.getVerifyData()))
+ {
+ throwHandshakeFailure();
+ }
+ }
+
+ if (!newSession)
+ {
+ changeCipherSpec();
+ session.params.setDeflating(serverHello.getCompressionMethod() == CompressionMethod.ZLIB);
+ session.params.setOutMac(writeMac);
+ session.params.setOutCipher(writeCipher);
+ finis = generateFinished(version, md5, sha, true);
+ msg = new Handshake(Handshake.Type.FINISHED, finis);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+ dout.flush();
+ }
+
+ handshakeCompleted();
+ }
+
+ /**
+ * Perform the server handshake.
+ */
+ private void doServerHandshake() throws IOException
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ {
+ logger.log (Component.SSL_HANDSHAKE, "doing server handshake in {0}",
+ Thread.currentThread());
+ }
+
+ if (remoteHost == null)
+ {
+ remoteHost = getInetAddress().getHostName();
+ }
+ if (remoteHost == null)
+ {
+ remoteHost = getInetAddress().getHostAddress();
+ }
+
+ IMessageDigest md5 = HashFactory.getInstance(Registry.MD5_HASH);
+ IMessageDigest sha = HashFactory.getInstance(Registry.SHA160_HASH);
+ DigestInputStream din = new DigestInputStream(handshakeIn, md5, sha);
+ DigestOutputStream dout = new DigestOutputStream(handshakeOut, md5, sha);
+
+ // Read the client hello.
+ Handshake msg = Handshake.read(din);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ if (msg.getType() != Handshake.Type.CLIENT_HELLO)
+ {
+ throwUnexpectedMessage();
+ }
+ ClientHello clientHello = (ClientHello) msg.getBody();
+ Random clientRandom = clientHello.getRandom();
+ ProtocolVersion version = clientHello.getVersion();
+ ProtocolVersion server =
+ (ProtocolVersion) session.enabledProtocols.last();
+ CompressionMethod comp;
+ if (clientHello.getCompressionMethods().contains(CompressionMethod.ZLIB))
+ comp = CompressionMethod.ZLIB;
+ else
+ comp = CompressionMethod.NULL;
+ if (!session.enabledProtocols.contains(version)
+ && version.compareTo(server) < 0)
+ {
+ Alert alert = new Alert(Alert.Level.FATAL,
+ Alert.Description.PROTOCOL_VERSION);
+ sendAlert(alert);
+ session.currentAlert = alert;
+ throw new AlertException(alert, true);
+ }
+
+ // Look through the extensions sent by the client (if any), and react to
+ // them appropriately.
+ List extensions = null;
+ String remoteUser = null;
+ if (clientHello.getExtensions() != null)
+ {
+ for (Iterator it = clientHello.getExtensions().iterator(); it.hasNext();)
+ {
+ Extension ex = (Extension) it.next();
+ if (ex.getType() == Extension.Type.SERVER_NAME)
+ {
+ if (extensions == null)
+ {
+ extensions = new LinkedList();
+ }
+ extensions.add(ex);
+ }
+ else if (ex.getType() == Extension.Type.MAX_FRAGMENT_LENGTH)
+ {
+ int maxLen = Extensions.getMaxFragmentLength(ex).intValue();
+// recordInput.setFragmentLength(maxLen);
+// recordOutput.setFragmentLength(maxLen);
+ session.params.setFragmentLength(maxLen);
+ if (extensions == null)
+ {
+ extensions = new LinkedList();
+ }
+ extensions.add(ex);
+ }
+ else if (ex.getType() == Extension.Type.SRP)
+ {
+ if (extensions == null)
+ {
+ extensions = new LinkedList();
+ }
+ byte[] b = ex.getValue();
+ remoteUser = new String(ex.getValue(), 1, b[0] & 0xFF, "UTF-8");
+ session.putValue("srp-username", remoteUser);
+ }
+ }
+ }
+
+ CipherSuite suite = selectSuite(clientHello.getCipherSuites(), version);
+ if (suite == null)
+ {
+ return;
+ }
+
+ // If the selected suite turns out to be SRP, set up the key exchange
+ // objects.
+ IKeyAgreementParty serverKA = null;
+ IncomingMessage in;
+ OutgoingMessage out = null;
+ if (suite.getKeyExchange() == "SRP")
+ {
+ // FIXME
+ // Uhm, I don't think this can happen, because if remoteUser is null
+ // we cannot choose an SRP ciphersuite...
+ if (remoteUser == null)
+ {
+ Alert alert = new Alert(Alert.Level.FATAL,
+ Alert.Description.MISSING_SRP_USERNAME);
+ sendAlert(alert);
+ throw new AlertException(alert, true);
+ }
+
+ SRPAuthInfoProvider srpDB = new SRPAuthInfoProvider();
+ Map dbAttributes = new HashMap();
+ dbAttributes.put(SRPRegistry.PASSWORD_DB,
+ session.srpTrustManager.getPasswordFile());
+ srpDB.activate(dbAttributes);
+
+ // FIXME
+ // We can also fake that the user exists, and generate a dummy (and
+ // invalid) master secret, and let the handshake fail at the Finished
+ // message. This is better than letting the connecting side know that
+ // the username they sent isn't valid.
+ //
+ // But how to implement this?
+ if (!srpDB.contains(remoteUser))
+ {
+ Alert alert = new Alert(Alert.Level.FATAL,
+ Alert.Description.UNKNOWN_SRP_USERNAME);
+ sendAlert(alert);
+ throw new AlertException(alert, true);
+ }
+
+ serverKA = KeyAgreementFactory.getPartyBInstance(Registry.SRP_TLS_KA);
+ Map serverAttributes = new HashMap();
+ serverAttributes.put(SRP6KeyAgreement.HASH_FUNCTION,
+ Registry.SHA160_HASH);
+ serverAttributes.put(SRP6KeyAgreement.HOST_PASSWORD_DB, srpDB);
+
+ try
+ {
+ serverKA.init(serverAttributes);
+ out = new OutgoingMessage();
+ out.writeString(remoteUser);
+ in = new IncomingMessage(out.toByteArray());
+ out = serverKA.processMessage(in);
+ }
+ catch (KeyAgreementException x)
+ {
+ throwHandshakeFailure();
+ }
+ }
+
+ // Check if the session specified by the client's ID corresponds
+ // to a saved session, and if so, continue it.
+ boolean newSession = true;
+ if (DEBUG_HANDSHAKE_LAYER)
+ {
+ logger.log (Component.SSL_HANDSHAKE, "saved sessions: {0}", sessionContext);
+ }
+ if (sessionContext.containsSessionID(
+ new Session.ID(clientHello.getSessionId())))
+ {
+ Session old = session;
+ session = (Session) sessionContext.getSession(clientHello.getSessionId());
+ if (!clientHello.getCipherSuites().contains(session.cipherSuite))
+ {
+ throwHandshakeFailure();
+ }
+ if (session.getPeerHost().equals(remoteHost) &&
+ old.enabledProtocols.contains(session.protocol))
+ {
+ session = (Session) session.clone();
+ suite = session.cipherSuite;
+ newSession = false;
+ recordInput.setSession(session);
+ session.currentAlert = null;
+ session.params = old.params;
+ session.random = old.random;
+ }
+ else
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ {
+ logger.log (Component.SSL_HANDSHAKE, "rejected section; hosts equal? {0}, same suites? {1}",
+ new Object[] { Boolean.valueOf (session.getPeerHost().equals(remoteHost)),
+ Boolean.valueOf (old.enabledProtocols.contains(session.protocol)) });
+ }
+ session = old;
+ session.peerHost = remoteHost;
+ newSession = true;
+ }
+ }
+ else if (DEBUG_HANDSHAKE_LAYER)
+ {
+ logger.log (Component.SSL_HANDSHAKE, "rejected session; have session id? {0}, saved sessions: {1}",
+ new Object[] { Boolean.valueOf (sessionContext.containsSessionID(new Session.ID(clientHello.getSessionId()))),
+ sessionContext });
+ }
+ if (newSession)
+ {
+ byte[] buf = new byte[32];
+ Session.ID sid = null;
+ do
+ {
+ session.random.nextBytes(buf);
+ sid = new Session.ID(buf);
+ }
+ while (sessionContext.containsSessionID(sid));
+ session.sessionId = sid;
+ }
+ session.valid = true;
+ session.peerHost = remoteHost;
+ session.cipherSuite = suite;
+ session.protocol = version;
+ session.params.setVersion (version);
+
+ // Send the server hello.
+ Random serverRandom = new Random(Util.unixTime(),
+ session.random.generateSeed(28));
+ ServerHello serverHello = new ServerHello(version, serverRandom,
+ session.getId(), suite,
+ comp, extensions);
+ msg = new Handshake(Handshake.Type.SERVER_HELLO, serverHello);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+// recordOutput.setHandshakeAvail(msg.write(dout, version));
+ dout.flush();
+
+ if (newSession)
+ {
+ X509Certificate[] certs = null;
+ PrivateKey serverKey = null;
+ if (suite.getSignature() != "anon")
+ {
+ // Send our CA-issued certificate to the client.
+ String alias = session.keyManager.chooseServerAlias(suite.getAuthType(),
+ null, null);
+ certs = session.keyManager.getCertificateChain(alias);
+ serverKey = session.keyManager.getPrivateKey(alias);
+ if (certs == null || serverKey == null)
+ {
+ throwHandshakeFailure();
+ }
+ session.localCerts = certs;
+ Certificate serverCert = new Certificate(certs);
+ msg = new Handshake(Handshake.Type.CERTIFICATE, serverCert);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+// recordOutput.setHandshakeAvail(msg.write(dout, version));;
+ dout.flush();
+ }
+
+ // If the certificate we sent does not contain enough information to
+ // do the key exchange (in the case of ephemeral Diffie-Hellman,
+ // export RSA, and SRP) we send a signed public key to be used for the
+ // key exchange.
+ KeyPair signPair = null;
+ if (certs != null)
+ {
+ signPair = new KeyPair(certs[0].getPublicKey(), serverKey);
+ }
+ KeyPair kexPair = signPair;
+ ServerKeyExchange skex = null;
+
+ // Set up our key exchange, and/or prepare our ServerKeyExchange
+ // message.
+ if ((suite.getKeyExchange() == "RSA" && suite.isExportable() &&
+ ((RSAPrivateKey) serverKey).getModulus().bitLength() > 512))
+ {
+ kexPair = KeyPool.generateRSAKeyPair();
+ RSAPublicKey pubkey = (RSAPublicKey) kexPair.getPublic();
+ Signature s = null;
+ if (suite.getSignature() != "anon")
+ {
+ SSLRSASignature sig = new SSLRSASignature();
+ sig.setupSign(Collections.singletonMap(ISignature.SIGNER_KEY,
+ signPair.getPrivate()));
+ byte[] buf = clientRandom.getEncoded();
+ sig.update(buf, 0, buf.length);
+ buf = serverRandom.getEncoded();
+ sig.update(buf, 0, buf.length);
+ updateSig(sig, pubkey.getModulus());
+ updateSig(sig, pubkey.getPublicExponent());
+ s = new Signature(sig.sign(), "RSA");
+ }
+ skex = new ServerKeyExchange(pubkey, s);
+ }
+ else if (suite.getKeyExchange() == "DH")
+ {
+ serverKA = KeyAgreementFactory.getPartyBInstance(Registry.ELGAMAL_KA);
+ Map attr = new HashMap();
+ attr.put(ElGamalKeyAgreement.KA_ELGAMAL_RECIPIENT_PRIVATE_KEY,
+ serverKey);
+ try
+ {
+ serverKA.init(attr);
+ }
+ catch (KeyAgreementException kae)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
+ internalError();
+ RuntimeException re = new RuntimeException (kae.getMessage());
+ re.initCause (kae);
+ throw re;
+ }
+ // We don't send a ServerKeyExchange for this suite.
+ }
+ else if (suite.getKeyExchange() == "DHE")
+ {
+ serverKA = KeyAgreementFactory.getPartyAInstance(Registry.DH_KA);
+ Map attr = new HashMap();
+ GnuDHPrivateKey servParams = DiffieHellman.getParams();
+ attr.put(DiffieHellmanKeyAgreement.KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY,
+ servParams);
+ attr.put(DiffieHellmanKeyAgreement.SOURCE_OF_RANDOMNESS,
+ session.random);
+ BigInteger serv_y = null;
+ try
+ {
+ serverKA.init(attr);
+ out = serverKA.processMessage(null);
+ in = new IncomingMessage(out.toByteArray());
+ serv_y = in.readMPI();
+ }
+ catch (KeyAgreementException kae)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "DHE exception", kae);
+ }
+ internalError();
+ RuntimeException re = new RuntimeException (kae.getMessage());
+ re.initCause (kae);
+ throw re;
+ }
+ GnuDHPublicKey pubkey =
+ new GnuDHPublicKey(null, servParams.getParams().getP(),
+ servParams.getParams().getG(), serv_y);
+ Signature s = null;
+ if (suite.getSignature() != "anon")
+ {
+ ISignature sig = null;
+ if (suite.getSignature() == "RSA")
+ {
+ sig = new SSLRSASignature();
+ }
+ else
+ {
+ sig = SignatureFactory.getInstance(Registry.DSS_SIG);
+ }
+ sig.setupSign(Collections.singletonMap(ISignature.SIGNER_KEY,
+ signPair.getPrivate()));
+ byte[] buf = clientRandom.getEncoded();
+ sig.update(buf, 0, buf.length);
+ buf = serverRandom.getEncoded();
+ sig.update(buf, 0, buf.length);
+ updateSig(sig, pubkey.getParams().getP());
+ updateSig(sig, pubkey.getParams().getG());
+ updateSig(sig, pubkey.getY());
+ s = new Signature(sig.sign(), suite.getSignature());
+ }
+ skex = new ServerKeyExchange(pubkey, s);
+ }
+ else if (suite.getKeyExchange() == "SRP")
+ {
+ BigInteger N = null;
+ BigInteger g = null;
+ BigInteger salt = null;
+ BigInteger B = null;
+ try
+ {
+ in = new IncomingMessage(out.toByteArray());
+ N = in.readMPI();
+ g = in.readMPI();
+ salt = in.readMPI();
+ B = in.readMPI();
+ }
+ catch (KeyAgreementException x)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
+ }
+ throwHandshakeFailure();
+ }
+ Signature s = null;
+ final byte[] srpSalt = Util.trim(salt);
+ if (suite.getSignature() != "anon")
+ {
+ ISignature sig = null;
+ if (suite.getSignature() == "RSA")
+ {
+ sig = new SSLRSASignature();
+ }
+ else
+ {
+ sig = SignatureFactory.getInstance(Registry.DSS_SIG);
+ }
+ sig.setupSign(Collections.singletonMap(ISignature.SIGNER_KEY,
+ signPair.getPrivate()));
+ byte[] buf = clientRandom.getEncoded();
+ sig.update(buf, 0, buf.length);
+ buf = serverRandom.getEncoded();
+ sig.update(buf, 0, buf.length);
+ updateSig(sig, N);
+ updateSig(sig, g);
+ sig.update((byte) srpSalt.length);
+ sig.update(srpSalt, 0, srpSalt.length);
+ updateSig(sig, B);
+ s = new Signature(sig.sign(), suite.getSignature());
+ }
+ final SRPPublicKey pubkey = new SRPPublicKey(N, g, B);
+ skex = new ServerKeyExchange(pubkey, s, srpSalt);
+ }
+ if (skex != null)
+ {
+ msg = new Handshake(Handshake.Type.SERVER_KEY_EXCHANGE, skex);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+// recordOutput.setHandshakeAvail(msg.write(dout, version));;
+ dout.flush();
+ }
+
+ // If we are configured to want or need client authentication, then
+ // ask for it.
+ if (wantClientAuth || needClientAuth)
+ {
+ Principal[] auths = null;
+ CertificateRequest.ClientType[] types =
+ new CertificateRequest.ClientType[] {
+ CertificateRequest.ClientType.RSA_SIGN,
+ CertificateRequest.ClientType.DSS_SIGN,
+ CertificateRequest.ClientType.RSA_FIXED_DH,
+ CertificateRequest.ClientType.DSS_FIXED_DH
+ };
+ try
+ {
+ auths = (Principal[])
+ Util.transform(session.trustManager.getAcceptedIssuers(),
+ Principal.class, "getSubjectDN", null);
+ }
+ catch (Exception x)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException (x.getMessage());
+ re.initCause (x);
+ throw re;
+ }
+ CertificateRequest req = new CertificateRequest(types, auths);
+ msg = new Handshake(Handshake.Type.CERTIFICATE_REQUEST, req);
+ msg.write(dout, version);
+ dout.flush();
+ }
+
+ // Send our server hello done.
+ msg = new Handshake(Handshake.Type.SERVER_HELLO_DONE, null);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+ dout.flush();
+
+ if (suite.getKeyExchange() == "RSA")
+ {
+ msg = Handshake.read(din, suite, kexPair.getPublic());
+ }
+ else
+ {
+ msg = Handshake.read(din, suite, null);
+ }
+ boolean clientCertOk = false;
+ boolean clientCanSign = false;
+ X509Certificate[] clientChain = null;
+ PublicKey clientKey = null;
+
+ // Read the client's certificate, if sent.
+ if (msg.getType() == Handshake.Type.CERTIFICATE)
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ Certificate cliCert = (Certificate) msg.getBody();
+ clientChain = cliCert.getCertificates();
+ try
+ {
+ session.trustManager.checkClientTrusted(clientChain,
+ suite.getAuthType());
+ session.peerCerts = clientChain;
+ session.peerVerified = true;
+ clientKey = clientChain[0].getPublicKey();
+ }
+ catch (Exception x)
+ {
+ }
+ clientCanSign = ((clientKey instanceof DSAPublicKey) ||
+ (clientKey instanceof RSAPublicKey));
+ if (suite.getKeyExchange().startsWith("DH"))
+ {
+ msg = Handshake.read(din, suite, clientKey);
+ }
+ else
+ {
+ msg = Handshake.read(din, suite, kexPair.getPublic());
+ }
+ }
+
+ // If we require client authentication, and the client sent an
+ // unverifiable certificate or no certificate at all, drop the
+ // connection.
+ if (!session.peerVerified && needClientAuth)
+ {
+ throwHandshakeFailure();
+ }
+
+ // Read the client key exchange.
+ if (msg.getType() != Handshake.Type.CLIENT_KEY_EXCHANGE)
+ {
+ throwUnexpectedMessage();
+ }
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ ClientKeyExchange ckex = (ClientKeyExchange) msg.getBody();
+ byte[] preMasterSecret = null;
+ if (suite.getKeyExchange() == "RSA")
+ {
+ byte[] enc = (byte[]) ckex.getExchangeObject();
+ BigInteger bi = new BigInteger(1, enc);
+ try
+ {
+ bi = RSA.decrypt(kexPair.getPrivate(), bi);
+ EME_PKCS1_V1_5 pkcs1 = EME_PKCS1_V1_5.getInstance(
+ (RSAPrivateKey) kexPair.getPrivate());
+ preMasterSecret = pkcs1.decode(Util.concat(new byte[1], bi.toByteArray()));
+ //rsa.init(kexPair);
+ //preMasterSecret = rsa.decrypt(enc);
+ }
+ catch (Exception x)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "RSA exception", x);
+ }
+ // Generate a fake pre-master secret if the RSA decryption
+ // fails.
+ byte[] b = new byte[46];
+ session.random.nextBytes (b);
+ preMasterSecret = Util.concat(version.getEncoded(), b);
+ }
+ }
+ else if (suite.getKeyExchange().startsWith("DH"))
+ {
+ try
+ {
+ out = new OutgoingMessage();
+ if (clientKey == null)
+ out.writeMPI((BigInteger) ckex.getExchangeObject());
+ else
+ out.writeMPI(((DHPublicKey) clientKey).getY());
+ in = new IncomingMessage(out.toByteArray());
+ serverKA.processMessage(in);
+ preMasterSecret = serverKA.getSharedSecret();
+ }
+ catch (KeyAgreementException kae)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
+ }
+ internalError();
+ RuntimeException re = new RuntimeException (kae.getMessage());
+ re.initCause (kae);
+ throw re;
+ }
+ }
+ else if (suite.getKeyExchange() == "SRP")
+ {
+ BigInteger A = (BigInteger) ckex.getExchangeObject();
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "SRP: client A: {0}", A);
+ }
+ try
+ {
+ out = new OutgoingMessage();
+ out.writeMPI(A);
+ in = new IncomingMessage(out.toByteArray());
+ out = serverKA.processMessage(in);
+ preMasterSecret = serverKA.getSharedSecret();
+ }
+ catch (KeyAgreementException x)
+ {
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
+ }
+ throwHandshakeFailure();
+ }
+ finally
+ {
+ serverKA = null;
+ }
+ }
+
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "preMasterSecret:\n{0}",
+ Util.toHexString(preMasterSecret, ':'));
+ logger.log (Component.SSL_KEY_EXCHANGE, "client.random:\n{0}",
+ Util.toHexString(clientRandom.getEncoded(), ':'));
+ logger.log (Component.SSL_KEY_EXCHANGE, "server.random:\n{0}",
+ Util.toHexString(serverRandom.getEncoded(), ':'));
+ }
+
+ // Generate the master secret.
+ IRandom genSecret = null;
+ if (version == ProtocolVersion.SSL_3)
+ {
+ genSecret = new SSLRandom();
+ HashMap attr = new HashMap();
+ attr.put(SSLRandom.SECRET, preMasterSecret);
+ attr.put(SSLRandom.SEED, Util.concat(clientRandom.getEncoded(),
+ serverRandom.getEncoded()));
+ genSecret.init(attr);
+ }
+ else
+ {
+ genSecret = new TLSRandom();
+ HashMap attr = new HashMap();
+ attr.put(TLSRandom.SECRET, preMasterSecret);
+ attr.put(TLSRandom.SEED,
+ Util.concat(("master secret").getBytes("UTF-8"),
+ Util.concat(clientRandom.getEncoded(),
+ serverRandom.getEncoded())));
+ genSecret.init(attr);
+ }
+ session.masterSecret = new byte[48];
+ try
+ {
+ genSecret.nextBytes(session.masterSecret, 0, 48);
+ for (int i = 0; i < preMasterSecret.length; i++)
+ {
+ preMasterSecret[i] = 0;
+ }
+ }
+ catch (LimitReachedException shouldNotHappen)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException();
+ re.initCause (shouldNotHappen);
+ throw re;
+ }
+
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "masterSecret: {0}",
+ Util.toHexString(session.masterSecret, ':'));
+ }
+
+ // Read the client's certificate verify message, if needed.
+ if (clientCanSign && (wantClientAuth || needClientAuth))
+ {
+ msg = Handshake.read(din);
+ if (msg.getType() != Handshake.Type.CERTIFICATE_VERIFY)
+ {
+ throwUnexpectedMessage();
+ }
+ CertificateVerify verify = (CertificateVerify) msg.getBody();
+ if (clientChain != null && clientChain.length > 0)
+ {
+ IMessageDigest cvMD5 = (IMessageDigest) md5.clone();
+ IMessageDigest cvSHA = (IMessageDigest) sha.clone();
+ clientKey = clientChain[0].getPublicKey();
+ if (clientKey instanceof RSAPublicKey)
+ {
+ SSLRSASignature sig = new SSLRSASignature(cvMD5, cvSHA);
+ sig.setupVerify(Collections.singletonMap(ISignature.VERIFIER_KEY, clientKey));
+ if (!sig.verify(verify.getSigValue()))
+ {
+ handshakeFailure();
+ throw new SSLHandshakeException("client certificate verify failed");
+ }
+ }
+ else if (clientKey instanceof DSAPublicKey)
+ {
+ try
+ {
+ if (!DSSSignature.verify((DSAPublicKey) clientKey, cvSHA.digest(),
+ (BigInteger[]) verify.getSigValue()))
+ {
+ throw new Exception("client's certificate could not be verified");
+ }
+ }
+ catch (Exception x)
+ {
+ handshakeFailure();
+ SSLHandshakeException e = new SSLHandshakeException (x.getMessage());
+ e.initCause (x);
+ throw e;
+ }
+ }
+ }
+ }
+ }
+
+ // Generate the session keys.
+ byte[][] keys = null;
+ try
+ {
+ keys = generateKeys(serverRandom.getEncoded(),
+ clientRandom.getEncoded(), version);
+ }
+ catch (Exception x)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException (x.getMessage());
+ re.initCause (x);
+ throw re;
+ }
+
+ // Initialize the algorithms with the derived keys.
+ Object readMac = null, writeMac = null;
+ Object readCipher = null, writeCipher = null;
+ try
+ {
+ if (session.params instanceof GNUSecurityParameters)
+ {
+ HashMap attr = new HashMap();
+ writeMac = CipherSuite.getMac(suite.getMac());
+ readMac = CipherSuite.getMac(suite.getMac());
+ attr.put(IMac.MAC_KEY_MATERIAL, keys[1]);
+ ((IMac) writeMac).init(attr);
+ attr.put(IMac.MAC_KEY_MATERIAL, keys[0]);
+ ((IMac) readMac).init(attr);
+ if (suite.getCipher() == "RC4")
+ {
+ writeCipher = new ARCFour();
+ readCipher = new ARCFour();
+ attr.clear();
+ attr.put(ARCFour.ARCFOUR_KEY_MATERIAL, keys[3]);
+ ((ARCFour) writeCipher).init(attr);
+ attr.put(ARCFour.ARCFOUR_KEY_MATERIAL, keys[2]);
+ ((ARCFour) readCipher).init(attr);
+ }
+ else if (!suite.isStreamCipher())
+ {
+ writeCipher = CipherSuite.getCipher(suite.getCipher());
+ readCipher = CipherSuite.getCipher(suite.getCipher());
+ attr.clear();
+ attr.put(IMode.KEY_MATERIAL, keys[3]);
+ attr.put(IMode.IV, keys[5]);
+ attr.put(IMode.STATE, new Integer(IMode.ENCRYPTION));
+ ((IMode) writeCipher).init(attr);
+ attr.put(IMode.KEY_MATERIAL, keys[2]);
+ attr.put(IMode.IV, keys[4]);
+ attr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
+ ((IMode) readCipher).init(attr);
+ }
+ }
+ else // JCESecurityParameters
+ {
+ writeMac = CipherSuite.getJCEMac (suite.getMac());
+ readMac = CipherSuite.getJCEMac (suite.getMac());
+ writeCipher = CipherSuite.getJCECipher (suite.getCipher());
+ readCipher = CipherSuite.getJCECipher (suite.getCipher());
+ ((Mac) writeMac).init (new SecretKeySpec (keys[1], suite.getMac()));
+ ((Mac) readMac).init (new SecretKeySpec (keys[0], suite.getMac()));
+ if (!suite.isStreamCipher())
+ {
+ ((Cipher) writeCipher).init (Cipher.ENCRYPT_MODE,
+ new SecretKeySpec (keys[3], suite.getCipher()),
+ new IvParameterSpec (keys[5]));
+ ((Cipher) readCipher).init (Cipher.DECRYPT_MODE,
+ new SecretKeySpec (keys[2], suite.getCipher()),
+ new IvParameterSpec (keys[4]));
+ }
+ else
+ {
+ ((Cipher) writeCipher).init (Cipher.ENCRYPT_MODE,
+ new SecretKeySpec (keys[3], suite.getCipher()));
+ ((Cipher) readCipher).init (Cipher.DECRYPT_MODE,
+ new SecretKeySpec (keys[2], suite.getCipher()));
+ }
+ }
+ }
+ // These should technically never happen, if our key generation is not
+ // broken.
+ catch (InvalidKeyException ike)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException (ike.getMessage());
+ re.initCause (ike);
+ throw new RuntimeException (String.valueOf (ike));
+ }
+ catch (InvalidAlgorithmParameterException iape)
+ {
+ internalError();
+ RuntimeException re = new RuntimeException (iape.getMessage());
+ re.initCause (iape);
+ throw re;
+ }
+ // These indicate a configuration error with the JCA.
+ catch (NoSuchAlgorithmException nsae)
+ {
+ session.enabledSuites.remove (suite);
+ internalError();
+ SSLException e = new SSLException ("suite " + suite + " not available in this configuration");
+ e.initCause (nsae);
+ throw e;
+ }
+ catch (NoSuchPaddingException nspe)
+ {
+ session.enabledSuites.remove (suite);
+ internalError();
+ SSLException e = new SSLException ("suite " + suite + " not available in this configuration");
+ e.initCause (nspe);
+ throw e;
+ }
+
+ Finished finis = null;
+ // If we are continuing a session, we send our Finished message first.
+ if (!newSession)
+ {
+ changeCipherSpec();
+ session.params.setDeflating(comp == CompressionMethod.ZLIB);
+ session.params.setOutMac(writeMac);
+ session.params.setOutCipher(writeCipher);
+ finis = generateFinished(version, (IMessageDigest) md5.clone(),
+ (IMessageDigest) sha.clone(), false);
+ msg = new Handshake(Handshake.Type.FINISHED, finis);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+ dout.flush();
+ }
+
+ if (session.currentAlert != null &&
+ session.currentAlert.getLevel() == Alert.Level.FATAL)
+ {
+ fatal();
+ throw new AlertException(session.currentAlert, false);
+ }
+
+ // Wait until we receive a ChangeCipherSpec, then change the crypto
+ // algorithms for the incoming side.
+ synchronized (session.params)
+ {
+ readChangeCipherSpec ();
+ session.params.setInflating(comp == CompressionMethod.ZLIB);
+ session.params.setInMac(readMac);
+ session.params.setInCipher(readCipher);
+ session.params.notifyAll();
+ }
+
+ // Receive and verify the client's finished message.
+ Finished verify = generateFinished(version, (IMessageDigest) md5.clone(),
+ (IMessageDigest) sha.clone(), true);
+ msg = Handshake.read(din, suite, null);
+ if (msg.getType() != Handshake.Type.FINISHED)
+ {
+ throwUnexpectedMessage();
+ }
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ finis = (Finished) msg.getBody();
+ if (version == ProtocolVersion.SSL_3)
+ {
+ if (!Arrays.equals(finis.getMD5Hash(), verify.getMD5Hash()) ||
+ !Arrays.equals(finis.getSHAHash(), verify.getSHAHash()))
+ {
+ throwHandshakeFailure();
+ }
+ }
+ else
+ {
+ if (!Arrays.equals(finis.getVerifyData(), verify.getVerifyData()))
+ {
+ throwHandshakeFailure();
+ }
+ }
+
+ // Send our Finished message last for new sessions.
+ if (newSession)
+ {
+ changeCipherSpec();
+ session.params.setDeflating(comp == CompressionMethod.ZLIB);
+ session.params.setOutMac(writeMac);
+ session.params.setOutCipher(writeCipher);
+ finis = generateFinished(version, md5, sha, false);
+ msg = new Handshake(Handshake.Type.FINISHED, finis);
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
+ msg.write(dout, version);
+ dout.flush();
+ }
+
+ handshakeCompleted();
+ }
+
+ /**
+ * Generate the keys from the master secret.
+ *
+ * @param server The server's random value.
+ * @param client The client's random value.
+ * @param activeVersion The negotiated protocol version.
+ * @return The generated keys.
+ */
+ private byte[][] generateKeys(byte[] server, byte[] client,
+ ProtocolVersion activeVersion)
+ throws LimitReachedException, IOException
+ {
+ CipherSuite suite = session.cipherSuite;
+ int macLen = (suite.getMac().indexOf("MD5") >= 0) ? 16 : 20;
+ int keyLen = suite.getKeyLength();
+ int ivLen = 0;
+ if (suite.getCipher().indexOf("DES") >= 0)
+ {
+ ivLen = 8;
+ }
+ else if (suite.getCipher() == "AES")
+ {
+ ivLen = 16;
+ }
+ byte[][] keyMaterial = new byte[6][];
+ keyMaterial[0] = new byte[macLen]; // client_write_MAC_secret
+ keyMaterial[1] = new byte[macLen]; // server_write_MAC_secret
+ keyMaterial[2] = new byte[keyLen]; // client_write_key
+ keyMaterial[3] = new byte[keyLen]; // server_write_key
+ keyMaterial[4] = new byte[ivLen]; // client_write_IV
+ keyMaterial[5] = new byte[ivLen]; // server_write_IV
+ IRandom prf = null;
+ if (activeVersion == ProtocolVersion.SSL_3)
+ {
+ prf = new SSLRandom();
+ HashMap attr = new HashMap();
+ attr.put(SSLRandom.SECRET, session.masterSecret);
+ attr.put(SSLRandom.SEED, Util.concat(server, client));
+ prf.init(attr);
+ }
+ else
+ {
+ prf = new TLSRandom();
+ HashMap attr = new HashMap();
+ attr.put(TLSRandom.SECRET, session.masterSecret);
+ attr.put(TLSRandom.SEED, Util.concat("key expansion".getBytes("UTF-8"),
+ Util.concat(server, client)));
+ prf.init(attr);
+ }
+ for (int i = 0; i < keyMaterial.length; i++)
+ {
+ prf.nextBytes(keyMaterial[i], 0, keyMaterial[i].length);
+ }
+
+ // Exportable ciphers transform their keys once more, and use a
+ // nonsecret IV for block ciphers.
+ if (suite.isExportable())
+ {
+ int finalLen = suite.getCipher() == "DES" ? 8 : 16;
+ if (activeVersion == ProtocolVersion.SSL_3)
+ {
+ IMessageDigest md5 = HashFactory.getInstance(Registry.MD5_HASH);
+ md5.update(keyMaterial[2], 0, keyMaterial[2].length);
+ md5.update(client, 0, client.length);
+ md5.update(server, 0, server.length);
+ keyMaterial[2] = Util.trim(md5.digest(), finalLen);
+ md5.update(keyMaterial[3], 0, keyMaterial[3].length);
+ md5.update(server, 0, server.length);
+ md5.update(client, 0, client.length);
+ keyMaterial[3] = Util.trim(md5.digest(), finalLen);
+ if (!suite.isStreamCipher())
+ {
+ md5.update(client, 0, client.length);
+ md5.update(server, 0, server.length);
+ keyMaterial[4] = Util.trim(md5.digest(), ivLen);
+ md5.update(server, 0, server.length);
+ md5.update(client, 0, client.length);
+ keyMaterial[5] = Util.trim(md5.digest(), ivLen);
+ }
+ }
+ else
+ {
+ HashMap attr = new HashMap();
+ attr.put(TLSRandom.SECRET, keyMaterial[2]);
+ attr.put(TLSRandom.SEED,
+ Util.concat("client write key".getBytes("UTF-8"),
+ Util.concat(client, server)));
+ prf.init(attr);
+ keyMaterial[2] = new byte[finalLen];
+ prf.nextBytes(keyMaterial[2], 0, finalLen);
+ attr.put(TLSRandom.SECRET, keyMaterial[3]);
+ attr.put(TLSRandom.SEED,
+ Util.concat("server write key".getBytes("UTF-8"),
+ Util.concat(client, server)));
+ prf.init(attr);
+ keyMaterial[3] = new byte[finalLen];
+ prf.nextBytes(keyMaterial[3], 0, finalLen);
+ if (!suite.isStreamCipher())
+ {
+ attr.put(TLSRandom.SECRET, new byte[0]);
+ attr.put(TLSRandom.SEED, Util.concat("IV block".getBytes("UTF-8"),
+ Util.concat(client, server)));
+ prf.init(attr);
+ prf.nextBytes(keyMaterial[4], 0, keyMaterial[4].length);
+ prf.nextBytes(keyMaterial[5], 0, keyMaterial[5].length);
+ }
+ }
+ }
+
+ if (DEBUG_KEY_EXCHANGE)
+ {
+ logger.log (Component.SSL_KEY_EXCHANGE, "Generated keys:");
+ for (int i = 0; i < keyMaterial.length; i++)
+ logger.log (Component.SSL_KEY_EXCHANGE, "[{0}] {1}",
+ new Object[] { new Integer (i),
+ Util.toHexString(keyMaterial[i], ':') });
+ }
+
+ return keyMaterial;
+ }
+
+ /**
+ * Generate a "finished" message, based on the hashes of the handshake
+ * messages, the agreed version, and a label.
+ *
+ * @param version The agreed version.
+ * @param md5 The current state of the handshake MD5 hash.
+ * @param sha The current state of the handshake SHA hash.
+ * @param client Should be true if the message is generated by the client.
+ */
+ private Finished generateFinished(ProtocolVersion version, IMessageDigest md5,
+ IMessageDigest sha, boolean client)
+ {
+ if (version == ProtocolVersion.SSL_3)
+ {
+ if (client)
+ {
+ md5.update(SENDER_CLIENT, 0, 4);
+ }
+ else
+ {
+ md5.update(SENDER_SERVER, 0, 4);
+ }
+ byte[] ms = session.masterSecret;
+ md5.update(ms, 0, ms.length);
+ for (int i = 0; i < 48; i++)
+ {
+ md5.update(SSLHMac.PAD1);
+ }
+ byte[] b = md5.digest();
+ md5.update(ms, 0, ms.length);
+ for (int i = 0; i < 48; i++)
+ {
+ md5.update(SSLHMac.PAD2);
+ }
+ md5.update(b, 0, b.length);
+
+ if (client)
+ {
+ sha.update(SENDER_CLIENT, 0, 4);
+ }
+ else
+ {
+ sha.update(SENDER_SERVER, 0, 4);
+ }
+ sha.update(ms, 0, ms.length);
+ for (int i = 0; i < 40; i++)
+ {
+ sha.update(SSLHMac.PAD1);
+ }
+ b = sha.digest();
+ sha.update(ms, 0, ms.length);
+ for (int i = 0; i < 40; i++)
+ {
+ sha.update(SSLHMac.PAD2);
+ }
+ sha.update(b, 0, b.length);
+ return new Finished(md5.digest(), sha.digest());
+ }
+ else
+ {
+ byte[] h1 = md5.digest();
+ byte[] h2 = sha.digest();
+ String label = client ? "client finished" : "server finished";
+ byte[] seed = null;
+ try
+ {
+ seed = Util.concat(label.getBytes("UTF-8"), Util.concat(h1, h2));
+ }
+ catch (java.io.UnsupportedEncodingException uee)
+ {
+ RuntimeException re = new RuntimeException (uee.getMessage());
+ re.initCause (uee);
+ throw re;
+ }
+ IRandom prf = new TLSRandom();
+ HashMap attr = new HashMap();
+ attr.put(TLSRandom.SECRET, session.masterSecret);
+ attr.put(TLSRandom.SEED, seed);
+ prf.init(attr);
+ byte[] finishedValue = new byte[12];
+ try
+ {
+ prf.nextBytes(finishedValue, 0, 12);
+ }
+ catch (LimitReachedException lre)
+ {
+ RuntimeException re = new RuntimeException (lre.getMessage());
+ re.initCause (lre);
+ throw re;
+ }
+ return new Finished(finishedValue);
+ }
+ }
+
+ /**
+ * Send a fatal unexpected_message alert.
+ */
+ private Alert unexpectedMessage() throws IOException
+ {
+ Alert alert = new Alert(Alert.Level.FATAL,
+ Alert.Description.UNEXPECTED_MESSAGE);
+ sendAlert(alert);
+ fatal();
+ return alert;
+ }
+
+ private void throwUnexpectedMessage() throws IOException
+ {
+ throw new AlertException(unexpectedMessage(), true);
+ }
+
+ /**
+ * Send a fatal handshake_failure alert.
+ */
+ private Alert handshakeFailure() throws IOException
+ {
+ Alert alert = new Alert(Alert.Level.FATAL,
+ Alert.Description.HANDSHAKE_FAILURE);
+ sendAlert(alert);
+ fatal();
+ return alert;
+ }
+
+ private void throwHandshakeFailure() throws IOException
+ {
+ throw new AlertException(handshakeFailure(), true);
+ }
+
+ /**
+ * Send an internal_error alert.
+ */
+ private Alert internalError() throws IOException
+ {
+ Alert alert = new Alert(Alert.Level.FATAL,
+ Alert.Description.INTERNAL_ERROR);
+ sendAlert(alert);
+ fatal();
+ return alert;
+ }
+
+ private void throwInternalError() throws IOException
+ {
+ throw new AlertException(internalError(), true);
+ }
+
+ private Alert peerUnverified(X509Certificate[] chain) throws IOException
+ {
+ Alert alert = new Alert(Alert.Level.FATAL,
+ Alert.Description.HANDSHAKE_FAILURE);
+ sendAlert(alert);
+ fatal();
+ return alert;
+ }
+
+ private void throwPeerUnverified(X509Certificate[] chain) throws IOException
+ {
+ peerUnverified (chain);
+ throw new SSLPeerUnverifiedException("could not verify: "+
+ chain[0].getSubjectDN());
+ }
+
+ /**
+ * Grab the first suite that is both in the client's requested suites
+ * and in our enabled suites, and for which we have the proper
+ * credentials.
+ *
+ * @param suites The client's requested suites.
+ * @param version The version being negotiated.
+ * @return The selected cipher suite.
+ * @throws SSLException If no appropriate suite can be selected.
+ */
+ private CipherSuite selectSuite(List suites, ProtocolVersion version)
+ throws IOException
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "selectSuite req:{0} suites:{1}",
+ new Object[] { suites, session.enabledSuites });
+ boolean srpSuiteNoUser = false;
+ for (Iterator i = suites.iterator(); i.hasNext(); )
+ {
+ CipherSuite herSuite = (CipherSuite) i.next();
+ for (Iterator j = session.enabledSuites.iterator(); j.hasNext(); )
+ {
+ CipherSuite mySuite = (CipherSuite) j.next();
+ if (!mySuite.equals(herSuite))
+ {
+ continue;
+ }
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0} == {1}",
+ new Object[] { mySuite, herSuite });
+ if (mySuite.getSignature() != "anon" && session.keyManager != null &&
+ session.keyManager.chooseServerAlias(mySuite.getAuthType(), null, null) == null)
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "{0}: no certificate/private key",
+ mySuite);
+ continue;
+ }
+ if (mySuite.getKeyExchange() == "SRP")
+ {
+ if (session.getValue("srp-username") == null)
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "no SRP username");
+ srpSuiteNoUser = true;
+ continue;
+ }
+ if (session.srpTrustManager == null)
+ {
+ if (DEBUG_HANDSHAKE_LAYER)
+ logger.log (Component.SSL_HANDSHAKE, "no SRP password file");
+ continue;
+ }
+ }
+ return mySuite.resolve(version);
+ }
+ }
+ Alert alert = null;
+ if (srpSuiteNoUser)
+ {
+ alert = new Alert(Alert.Level.WARNING,
+ Alert.Description.MISSING_SRP_USERNAME);
+ sendAlert(alert);
+ return null;
+ }
+ else
+ alert = new Alert(Alert.Level.FATAL,
+ Alert.Description.INSUFFICIENT_SECURITY);
+ sendAlert(alert);
+ fatal();
+ throw new AlertException(alert, true);
+ }
+
+ /**
+ * Ask the user for their user name.
+ *
+ * @param remoteHost The remote host being connected to.
+ * @return The user name.
+ */
+ private String askUserName(String remoteHost)
+ {
+ CallbackHandler handler = new DefaultCallbackHandler();
+ try
+ {
+ Class c = Class.forName(Util.getSecurityProperty("jessie.srp.user.handler"));
+ handler = (CallbackHandler) c.newInstance();
+ }
+ catch (Exception x) { }
+ TextInputCallback user =
+ new TextInputCallback("User name for " + remoteHost + ": ",
+ Util.getProperty("user.name"));
+ try
+ {
+ handler.handle(new Callback[] { user });
+ }
+ catch (Exception x) { }
+ return user.getText();
+ }
+
+ /**
+ * Ask the user for a password.
+ *
+ * @param user The user name.
+ * @return The password.
+ */
+ private String askPassword(String user)
+ {
+ CallbackHandler handler = new DefaultCallbackHandler();
+ try
+ {
+ Class c = Class.forName(Util.getSecurityProperty("jessie.srp.password.handler"));
+ handler = (CallbackHandler) c.newInstance();
+ }
+ catch (Exception x) { }
+ PasswordCallback passwd = new PasswordCallback(user + "'s password: ", false);
+ try
+ {
+ handler.handle(new Callback[] { passwd });
+ }
+ catch (Exception x) { }
+ return new String(passwd.getPassword());
+ }
+
+ /**
+ * Ask the user (via a callback) if they will accept a certificate that
+ * could not be verified.
+ *
+ * @param chain The certificate chain in question.
+ * @return true if the user accepts the certificate chain.
+ */
+ private boolean checkCertificates(X509Certificate[] chain)
+ {
+ CallbackHandler handler = new DefaultCallbackHandler();
+ try
+ {
+ Class c = Class.forName(Util.getSecurityProperty("jessie.certificate.handler"));
+ handler = (CallbackHandler) c.newInstance();
+ }
+ catch (Exception x)
+ {
+ }
+ String nl = Util.getProperty("line.separator");
+ ConfirmationCallback confirm = new ConfirmationCallback(
+ "The server's certificate could not be verified. There is no proof" + nl +
+ "that this server is who it claims to be, or that their certificate" + nl +
+ "is valid. Do you wish to continue connecting?",
+ ConfirmationCallback.ERROR, ConfirmationCallback.YES_NO_OPTION,
+ ConfirmationCallback.NO);
+ try
+ {
+ handler.handle(new Callback[] { confirm });
+ }
+ catch (Exception x)
+ {
+ return false;
+ }
+ return confirm.getSelectedIndex() == ConfirmationCallback.YES;
+ }
+
+ /**
+ * Update a signature object with a BigInteger, trimming the leading
+ * "00" octet if present.
+ *
+ * @param sig The signature being updated.
+ * @param bi The integer to feed into the signature.
+ */
+ private void updateSig(ISignature sig, BigInteger bi)
+ {
+ byte[] buf = Util.trim(bi);
+ sig.update((byte) (buf.length >>> 8));
+ sig.update((byte) buf.length);
+ sig.update(buf, 0, buf.length);
+ }
+
+ /**
+ * Teardown everything on fatal errors.
+ */
+ private void fatal() throws IOException
+ {
+ if (session != null)
+ {
+ session.invalidate();
+ }
+// recordInput.setRunning(false);
+// recordOutput.setRunning(false);
+ if (underlyingSocket != null)
+ {
+ underlyingSocket.close();
+ }
+ else
+ {
+ super.close();
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLSocketFactory.java b/gnu/javax/net/ssl/provider/SSLSocketFactory.java
new file mode 100644
index 000000000..24a8389c1
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLSocketFactory.java
@@ -0,0 +1,133 @@
+/* SSLSocketFactory.java -- factory for SSL sockets.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.SecureRandom;
+
+import javax.net.ssl.X509TrustManager;
+import javax.net.ssl.X509KeyManager;
+
+class SSLSocketFactory extends javax.net.ssl.SSLSocketFactory
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final X509TrustManager trustManager;
+ private final X509KeyManager keyManager;
+ private final SecureRandom random;
+ private final SessionContext sessionContext;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ SSLSocketFactory(X509TrustManager trustManager, X509KeyManager keyManager,
+ SecureRandom random, SessionContext sessionContext)
+ {
+ this.trustManager = trustManager;
+ this.keyManager = keyManager;
+ this.random = random;
+ this.sessionContext = sessionContext;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String[] getDefaultCipherSuites()
+ {
+ return (String[]) CipherSuite.availableSuiteNames().toArray(new String[0]);
+ }
+
+ public String[] getSupportedCipherSuites()
+ {
+ return getDefaultCipherSuites();
+ }
+
+ public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
+ throws IOException
+ {
+ return setup(new SSLSocket(socket, host, port, autoClose));
+ }
+
+ public Socket createSocket() throws IOException
+ {
+ return setup(new SSLSocket());
+ }
+
+ public Socket createSocket(String host, int port)
+ throws IOException, UnknownHostException
+ {
+ return setup(new SSLSocket(host, port));
+ }
+
+ public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
+ throws IOException, UnknownHostException
+ {
+ return setup(new SSLSocket(host, port, localAddr, localPort));
+ }
+
+ public Socket createSocket(InetAddress address, int port) throws IOException
+ {
+ return setup(new SSLSocket(address, port));
+ }
+
+ public Socket createSocket(InetAddress address, int port,
+ InetAddress localAddr, int localPort)
+ throws IOException
+ {
+ return setup(new SSLSocket(address, port, localAddr, localPort));
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private SSLSocket setup(SSLSocket s)
+ {
+ s.setTrustManager(trustManager);
+ s.setKeyManager(keyManager);
+ s.setRandom(random);
+ s.setSessionContext(sessionContext);
+ s.setUseClientMode(true);
+ return s;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLSocketInputStream.java b/gnu/javax/net/ssl/provider/SSLSocketInputStream.java
new file mode 100644
index 000000000..69202ca33
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLSocketInputStream.java
@@ -0,0 +1,181 @@
+/* SSLSocketInputStream.java -- InputStream for SSL sockets.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import javax.net.ssl.SSLException;
+
+class SSLSocketInputStream extends FilterInputStream
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final SSLSocket socket;
+ private final boolean checkHandshake;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ SSLSocketInputStream(InputStream in, SSLSocket socket)
+ {
+ this(in, socket, true);
+ }
+
+ SSLSocketInputStream(InputStream in, SSLSocket socket, boolean checkHandshake)
+ {
+ super(in);
+ this.socket = socket;
+ this.checkHandshake = checkHandshake;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public int available() throws IOException
+ {
+ if (checkHandshake)
+ {
+ socket.checkHandshakeDone();
+ }
+ int ret = 0;
+ try
+ {
+ ret = super.available();
+ }
+ catch (AlertException ae)
+ {
+ Alert alert = ae.getAlert ();
+ if (alert.getDescription () == Alert.Description.CLOSE_NOTIFY)
+ {
+ return -1;
+ }
+ else
+ {
+ throw ae;
+ }
+ }
+ return ret;
+ }
+
+ public int read() throws IOException
+ {
+ if (checkHandshake)
+ {
+ socket.checkHandshakeDone();
+ }
+ int ret = 0;
+ try
+ {
+ ret = in.read();
+ }
+ catch (AlertException ae)
+ {
+ Alert alert = ae.getAlert ();
+ if (alert.getDescription () == Alert.Description.CLOSE_NOTIFY)
+ {
+ return -1;
+ }
+ else
+ {
+ throw ae;
+ }
+ }
+ return ret;
+ }
+
+ public int read(byte[] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public int read(byte[] buf, int off, int len) throws IOException
+ {
+ if (checkHandshake)
+ {
+ socket.checkHandshakeDone();
+ }
+ if (buf == null)
+ {
+ throw new NullPointerException();
+ }
+ if (off < 0 || len < 0 || off + len > buf.length)
+ {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ int ret = 0;
+ try
+ {
+ ret = in.read(buf, off, len);
+ }
+ catch (AlertException ae)
+ {
+ Alert alert = ae.getAlert ();
+ if (alert.getDescription () == Alert.Description.CLOSE_NOTIFY)
+ {
+ return -1;
+ }
+ else
+ {
+ throw ae;
+ }
+ }
+ return ret;
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private boolean checkAlert() throws IOException
+ {
+ Alert alert = socket.checkAlert();
+ if (alert == null) return false;
+ if (alert.getLevel().equals(Alert.Level.FATAL))
+ throw new AlertException(alert, false);
+ if (alert.getDescription().equals(Alert.Description.CLOSE_NOTIFY))
+ {
+ try { return (in.available() <= 0); }
+ catch (IOException ioe) { }
+ }
+ return false;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java b/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java
new file mode 100644
index 000000000..fe769a85f
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java
@@ -0,0 +1,115 @@
+/* SSLSocketOutputStream.java -- output stream for SSL sockets.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.net.ssl.SSLException;
+
+class SSLSocketOutputStream extends FilterOutputStream
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final SSLSocket socket;
+ private final boolean checkHandshake;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ SSLSocketOutputStream(OutputStream out, SSLSocket socket)
+ {
+ this(out, socket, true);
+ }
+
+ SSLSocketOutputStream(OutputStream out, SSLSocket socket,
+ boolean checkHandshake)
+ {
+ super(out);
+ this.socket = socket;
+ this.checkHandshake = checkHandshake;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(int b) throws IOException
+ {
+ if (checkHandshake)
+ {
+ socket.checkHandshakeDone();
+ }
+ checkAlert();
+ out.write(b);
+ checkAlert();
+ }
+
+ public void write(byte[] buf) throws IOException
+ {
+ write(buf, 0, buf.length);
+ }
+
+ public void write(byte[] buf, int off, int len) throws IOException
+ {
+ if (checkHandshake)
+ {
+ socket.checkHandshakeDone();
+ }
+ if (buf == null)
+ throw new NullPointerException();
+ if (off < 0 || len < 0 || off + len > buf.length)
+ throw new ArrayIndexOutOfBoundsException();
+ checkAlert();
+ out.write(buf, off, len);
+ checkAlert();
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private synchronized void checkAlert() throws SSLException
+ {
+ Alert alert = socket.checkAlert();
+ if (alert == null) return;
+ if (alert.getLevel().equals(Alert.Level.FATAL))
+ throw new AlertException(alert, false);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SecurityParameters.java b/gnu/javax/net/ssl/provider/SecurityParameters.java
new file mode 100644
index 000000000..aa06680e2
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SecurityParameters.java
@@ -0,0 +1,178 @@
+/* SecurityParameters.java -- SSL security parameters.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import javax.net.ssl.SSLException;
+
+/**
+ * The interface that all security parameters used by Jessie must implement.
+ * Security parameters handle all transforming of data, including encryption,
+ * authentication, and compression.
+ */
+interface SecurityParameters
+{
+
+ // Methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Decrypts, verifies, and inflates a fragment received. The fragment is
+ * just the data field of a text object, without the version, type, and
+ * length fields. An exception is thrown if any step fails.
+ *
+ * @param fragment The fragment being decrypted.
+ * @param version The version field of the received text.
+ * @param type The type field of the received text.
+ * @return The decrypted fragment.
+ * @throws MacException If the MAC could not be verified, or if the padding
+ * on the decrypted fragment is incorrect.
+ * @throws OverflowException If the processed text overflows the configured
+ * maximum fragment size.
+ * @throws SSLException If any other error occurs.
+ */
+ byte[] decrypt (byte[] fragment, ProtocolVersion version, ContentType type)
+ throws MacException, OverflowException, SSLException;
+
+ /**
+ * Deflates, authenticates, and encrypts a fragment to be sent.
+ *
+ * @param buf The fragment being encrypted.
+ * @param off The offset into the buffer to start at.
+ * @param len The number of bytes in this fragment.
+ * @param type The content type of this text.
+ * @return The encrypted fragment.
+ * @throws OverflowException If deflating increases the size of the fragment
+ * too much.
+ * @throws SSLException If any other error occurs.
+ */
+ byte[] encrypt (byte[] buf, int off, int len, ContentType type)
+ throws OverflowException, SSLException;
+
+ /**
+ * Set all crypto primitives to <code>null</code>, meaning that any calls
+ * to {@link #encrypt(byte[],int,int,org.metastatic.jessie.provider.ContentType)} or
+ * {@link #decrypt(byte[],org.metastatic.jessie.provider.ProtocolVersion,org.metastatic.jessie.provider.ContentType})
+ * will perform the identity transformation.
+ */
+ void reset();
+
+ /**
+ * Returns the version of texts being sent.
+ *
+ * @return The version.
+ */
+ ProtocolVersion getVersion();
+
+ /**
+ * Sets the version of texts being sent. This affects the {@link
+ * #encrypt(byte[],int,int,org.metastatic.jessie.provider.ContentType)}
+ * method.
+ *
+ * @param version The version to set.
+ */
+ void setVersion (ProtocolVersion version);
+
+ /**
+ * Turns zlib deflating on or off.
+ *
+ * @param deflate Whether or not to deflate outgoing fragments.
+ */
+ void setDeflating (boolean deflate);
+
+ /**
+ * Turns zlib inflating on or off.
+ *
+ * @param inflate Whether or not to inflate incoming fragments.
+ */
+ void setInflating (boolean inflate);
+
+ /**
+ * Returns the maximum size that plaintext fragments may be.
+ *
+ * @return The fragment length.
+ */
+ int getFragmentLength();
+
+ /**
+ * Sets the maximum size that plaintext fragments may be.
+ *
+ * @param fragmentLength The new fragment length.
+ */
+ void setFragmentLength (int fragmentLength);
+
+ /**
+ * Set the cipher used to decrypt incoming fragments. The parameter must be
+ * appropriate for the implementation.
+ *
+ * @param cipher The cipher.
+ * @throws ClassCastException If the argument is not appropriate for the
+ * implementation.
+ */
+ void setInCipher (Object cipher);
+
+ /**
+ * Set the cipher used to encrypt outgoing fragments. The parameter must be
+ * appropriate for the implementation.
+ *
+ * @param cipher The cipher.
+ * @throws ClassCastException If the argument is not appropriate for the
+ * implementation.
+ */
+ void setOutCipher (Object cipher);
+
+ /**
+ * Set the MAC used to verify incoming fragments. The parameter must be
+ * appropriate for the implementation.
+ *
+ * @param mac The MAC.
+ * @throws ClassCastException If the argument is not appropriate for the
+ * implementation.
+ */
+ void setInMac (Object mac);
+
+ /**
+ * Set the MAC used to authenticating outgoinging fragments. The parameter
+ * must be appropriate for the implementation.
+ *
+ * @param mac The MAC.
+ * @throws ClassCastException If the argument is not appropriate for the
+ * implementation.
+ */
+ void setOutMac (Object mac);
+}
diff --git a/gnu/javax/net/ssl/provider/ServerHello.java b/gnu/javax/net/ssl/provider/ServerHello.java
new file mode 100644
index 000000000..8b7853c7f
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerHello.java
@@ -0,0 +1,216 @@
+/* ServerHello.java -- SSL ServerHello message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.net.ssl.SSLProtocolException;
+
+class ServerHello implements Handshake.Body
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final ProtocolVersion version;
+ private final Random random;
+ private final byte[] sessionId;
+ private final CipherSuite suite;
+ private final CompressionMethod comp;
+ private final List extensions;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ ServerHello(ProtocolVersion version, Random random,
+ byte[] sessionId, CipherSuite suite,
+ CompressionMethod comp)
+ {
+ this(version, random, sessionId, suite, comp, null);
+ }
+
+ ServerHello(ProtocolVersion version, Random random,
+ byte[] sessionId, CipherSuite suite,
+ CompressionMethod comp, List extensions)
+ {
+ this.version = version;
+ this.random = random;
+ this.sessionId = sessionId;
+ this.suite = suite;
+ this.comp = comp;
+ this.extensions = extensions;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static ServerHello read(InputStream in) throws IOException
+ {
+ ProtocolVersion vers = ProtocolVersion.read(in);
+ Random rand = Random.read(in);
+ byte[] id = new byte[in.read() & 0xFF];
+ in.read(id);
+ CipherSuite suite = CipherSuite.read(in).resolve(vers);
+ CompressionMethod comp = CompressionMethod.read(in);
+ List ext = null;
+ if (in.available() > 0)
+ {
+ ext = new LinkedList();
+ int len = (in.read() >>> 8 & 0xFF) | (in.read() & 0xFF);
+ int count = 0;
+ while (count < len)
+ {
+ Extension e = Extension.read(in);
+ ext.add(e);
+ count += e.getValue().length + 4;
+ }
+ }
+ return new ServerHello(vers, rand, id, suite, comp, ext);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ version.write(out);
+ random.write(out);
+ out.write(sessionId.length);
+ out.write(sessionId);
+ suite.write(out);
+ out.write(comp.getValue());
+ if (extensions != null)
+ {
+ ByteArrayOutputStream out2 = new ByteArrayOutputStream();
+ for (Iterator i = extensions.iterator(); i.hasNext(); )
+ ((Extension) i.next()).write(out2);
+ out.write(out2.size() >>> 8 & 0xFF);
+ out.write(out2.size() & 0xFF);
+ out2.writeTo(out);
+ }
+ }
+
+ ProtocolVersion getVersion()
+ {
+ return version;
+ }
+
+ Random getRandom()
+ {
+ return random;
+ }
+
+ byte[] getSessionId()
+ {
+ return (byte[]) sessionId.clone();
+ }
+
+ CipherSuite getCipherSuite()
+ {
+ return suite;
+ }
+
+ CompressionMethod getCompressionMethod()
+ {
+ return comp;
+ }
+
+ List getExtensions()
+ {
+ return extensions;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ out.println(" version = " + version + ";");
+ BufferedReader r = new BufferedReader(new StringReader(random.toString()));
+ String s;
+ try
+ {
+ while ((s = r.readLine()) != null)
+ {
+ out.print(" ");
+ out.println(s);
+ }
+ }
+ catch (IOException ignored)
+ {
+ }
+ out.println(" sessionId = " + Util.toHexString(sessionId, ':') + ";");
+ out.println(" cipherSuite = " + suite + ";");
+ out.println(" compressionMethod = " + comp + ";");
+ if (extensions != null)
+ {
+ out.println(" extensions = {");
+ for (Iterator i = extensions.iterator(); i.hasNext(); )
+ {
+ r = new BufferedReader(new StringReader(i.next().toString()));
+ try
+ {
+ while ((s = r.readLine()) != null)
+ {
+ out.print(" ");
+ out.println(s);
+ }
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ out.println(" };");
+ }
+ out.println("} ServerHello;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ServerKeyExchange.java b/gnu/javax/net/ssl/provider/ServerKeyExchange.java
new file mode 100644
index 000000000..583041593
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerKeyExchange.java
@@ -0,0 +1,286 @@
+/* ServerKeyExchange.java -- SSL ServerKeyExchange message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import java.math.BigInteger;
+
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+
+import javax.net.ssl.SSLProtocolException;
+
+import gnu.javax.crypto.key.dh.GnuDHPublicKey;
+import gnu.javax.crypto.key.srp6.SRPPublicKey;
+
+class ServerKeyExchange implements Handshake.Body
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private PublicKey publicKey;
+ private Signature signature;
+ private byte[] srpSalt;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ ServerKeyExchange(PublicKey publicKey, Signature signature)
+ {
+ this(publicKey, signature, null);
+ }
+
+ ServerKeyExchange(PublicKey publicKey, Signature signature, byte[] srpSalt)
+ {
+ this.publicKey = publicKey;
+ this.signature = signature;
+ this.srpSalt = srpSalt;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ static ServerKeyExchange read(InputStream in, CipherSuite suite,
+ PublicKey serverKey)
+ throws IOException
+ {
+ DataInputStream din = new DataInputStream(in);
+ PublicKey key = null;
+ byte[] salt = null;
+ String kex = suite.getKeyExchange();
+ if (kex.equals("DHE"))
+ {
+ BigInteger p, g, y;
+ byte[] buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ p = new BigInteger(1, buf);
+ buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ g = new BigInteger(1, buf);
+ buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ y = new BigInteger(1, buf);
+ key = new GnuDHPublicKey(null, p, g, y);
+ }
+ else if (kex.equals("RSA"))
+ {
+ BigInteger n, e;
+ byte[] buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ n = new BigInteger(1, buf);
+ buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ e = new BigInteger(1, buf);
+ key = new JessieRSAPublicKey(n, e);
+ }
+ else if (kex.equals("SRP"))
+ {
+ BigInteger N, g, B;
+ byte[] buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ N = new BigInteger(1, buf);
+ buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ g = new BigInteger(1, buf);
+ salt = new byte[din.readUnsignedByte()];
+ din.readFully(salt);
+ buf = new byte[din.readUnsignedShort()];
+ din.readFully(buf);
+ B = new BigInteger(1, buf);
+ try
+ {
+ key = new SRPPublicKey(N, g, B);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ throw new SSLProtocolException(iae.getMessage());
+ }
+ }
+ else
+ {
+ throw new SSLProtocolException("invalid kex algorithm");
+ }
+
+ Signature sig = null;
+ if (!suite.getSignature().equals("anon"))
+ {
+ sig = Signature.read(in, suite, serverKey);
+ }
+ return new ServerKeyExchange(key, sig, salt);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ write(out, ProtocolVersion.TLS_1);
+ }
+
+ public void write(OutputStream out, ProtocolVersion version)
+ throws IOException
+ {
+ if (publicKey instanceof DHPublicKey)
+ {
+ writeBigint(out, ((DHPublicKey) publicKey).getParams().getP());
+ writeBigint(out, ((DHPublicKey) publicKey).getParams().getG());
+ writeBigint(out, ((DHPublicKey) publicKey).getY());
+ }
+ else if (publicKey instanceof RSAPublicKey)
+ {
+ writeBigint(out, ((RSAPublicKey) publicKey).getModulus());
+ writeBigint(out, ((RSAPublicKey) publicKey).getPublicExponent());
+ }
+ else if (publicKey instanceof SRPPublicKey)
+ {
+ writeBigint(out, ((SRPPublicKey) publicKey).getN());
+ writeBigint(out, ((SRPPublicKey) publicKey).getG());
+ out.write(srpSalt.length);
+ out.write(srpSalt);
+ writeBigint(out, ((SRPPublicKey) publicKey).getY());
+ }
+ if (signature != null)
+ {
+ signature.write(out, version);
+ }
+ }
+
+ PublicKey getPublicKey()
+ {
+ return publicKey;
+ }
+
+ Signature getSignature()
+ {
+ return signature;
+ }
+
+ byte[] getSRPSalt()
+ {
+ return srpSalt;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ out.println(" publicKey = struct {");
+ if (publicKey instanceof DHPublicKey)
+ {
+ out.println(" p = " +
+ ((DHPublicKey) publicKey).getParams().getP().toString(16) +
+ ";");
+ out.println(" g = " +
+ ((DHPublicKey) publicKey).getParams().getG().toString(16) +
+ ";");
+ out.println(" y = " + ((DHPublicKey) publicKey).getY().toString(16) +
+ ";");
+ out.println(" } DHPublicKey;");
+ }
+ else if (publicKey instanceof RSAPublicKey)
+ {
+ out.println(" modulus = " +
+ ((RSAPublicKey) publicKey).getModulus().toString(16) +
+ ";");
+ out.println(" exponent = " +
+ ((RSAPublicKey) publicKey).getPublicExponent().toString(16) +
+ ";");
+ out.println(" } RSAPublicKey;");
+ }
+ else if (publicKey instanceof SRPPublicKey)
+ {
+ out.println(" N = "+((SRPPublicKey) publicKey).getN().toString(16)+";");
+ out.println(" g = "+((SRPPublicKey) publicKey).getG().toString(16)+";");
+ out.println(" salt = " + Util.toHexString(srpSalt, ':') + ";");
+ out.println(" B = "+((SRPPublicKey) publicKey).getY().toString(16)+";");
+ out.println(" } SRPPublicKey;");
+ }
+ if (signature != null)
+ {
+ out.println(" signature =");
+ BufferedReader r = new BufferedReader(new StringReader(signature.toString()));
+ String s;
+ try
+ {
+ while ((s = r.readLine()) != null)
+ {
+ out.print(" ");
+ out.println(s);
+ }
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ out.println("} ServerKeyExchange;");
+ return str.toString();
+ }
+
+ private void writeBigint(OutputStream out, BigInteger bigint)
+ throws IOException
+ {
+ byte[] b = bigint.toByteArray();
+ if (b[0] == 0x00)
+ {
+ out.write((b.length - 1) >>> 8 & 0xFF);
+ out.write((b.length - 1) & 0xFF);
+ out.write(b, 1, b.length - 1);
+ }
+ else
+ {
+ out.write(b.length >>> 8 & 0xFF);
+ out.write(b.length & 0xFF);
+ out.write(b);
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Session.java b/gnu/javax/net/ssl/provider/Session.java
new file mode 100644
index 000000000..e13758b03
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Session.java
@@ -0,0 +1,381 @@
+/* Session.java -- SSL and TLS session data.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLPermission;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionBindingEvent;
+import javax.net.ssl.SSLSessionBindingListener;
+import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+import javax.security.cert.X509Certificate;
+
+import gnu.javax.net.ssl.SRPTrustManager;
+
+/**
+ * A generic SSL session implementation for SSL and TLS.
+ */
+final class Session implements SSLSession
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ private static final SSLPermission GET_SESSION_CONTEXT_PERMISSION =
+ new SSLPermission("getSSLSessionContext");
+
+ private final long creationTime;
+ private Date lastAccessedTime;
+ ID sessionId;
+ Certificate[] localCerts;
+ Certificate[] peerCerts;
+ X509Certificate[] peerCertChain;
+ String peerHost;
+ boolean peerVerified;
+ SessionContext context;
+ HashMap values;
+ boolean valid;
+ List enabledSuites;
+ CipherSuite cipherSuite;
+ SortedSet enabledProtocols;
+ ProtocolVersion protocol;
+ byte[] masterSecret;
+ SRPTrustManager srpTrustManager;
+ X509TrustManager trustManager;
+ X509KeyManager keyManager;
+ SecureRandom random;
+ SecurityParameters params;
+ Alert currentAlert;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ Session()
+ {
+ this(System.currentTimeMillis());
+ }
+
+ Session(long creationTime)
+ {
+ peerVerified = false;
+ valid = true;
+ this.creationTime = creationTime;
+ lastAccessedTime = new Date(0L);
+ values = new HashMap();
+ if (("true").equalsIgnoreCase (Util.getSecurityProperty ("jessie.with.jce")))
+ params = new JCESecurityParameters();
+ else
+ params = new GNUSecurityParameters (this);
+ }
+
+ // Public instance methods.
+ // -------------------------------------------------------------------------
+
+ protected Object clone()
+ {
+ Session result = new Session(creationTime);
+ result.lastAccessedTime = lastAccessedTime;
+ result.sessionId = sessionId;
+ result.localCerts = (localCerts != null ? (Certificate[]) localCerts.clone() : null);
+ result.peerCerts = (peerCerts != null ? (Certificate[]) peerCerts.clone() : null);
+ result.peerHost = peerHost;
+ result.peerVerified = peerVerified;
+ result.context = context;
+ result.values = values;
+ result.enabledSuites = new ArrayList(enabledSuites);
+ result.cipherSuite = cipherSuite;
+ result.enabledProtocols = new TreeSet(enabledProtocols);
+ result.protocol = protocol;
+ result.masterSecret = masterSecret;
+ result.keyManager = keyManager;
+ result.srpTrustManager = srpTrustManager;
+ result.trustManager = trustManager;
+ result.random = random;
+ return result;
+ }
+
+ public String getCipherSuite()
+ {
+ return cipherSuite.toString();
+ }
+
+ public long getCreationTime()
+ {
+ return creationTime;
+ }
+
+ public byte[] getId()
+ {
+ return (sessionId != null ? sessionId.getId() : null);
+ }
+
+ public long getLastAccessedTime()
+ {
+ return lastAccessedTime.getTime();
+ }
+
+ public Certificate[] getLocalCertificates()
+ {
+ return (Certificate[]) (localCerts != null ? localCerts.clone() : null);
+ }
+
+ public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException
+ {
+ if (!peerVerified)
+ {
+ throw new SSLPeerUnverifiedException("peer not verified");
+ }
+ return (Certificate[]) (peerCerts != null ? peerCerts.clone() : null);
+ }
+
+ public X509Certificate[] getPeerCertificateChain()
+ throws SSLPeerUnverifiedException
+ {
+ if (!peerVerified)
+ {
+ throw new SSLPeerUnverifiedException("peer not verified");
+ }
+ if (peerCerts == null)
+ {
+ return null;
+ }
+ if (peerCertChain != null)
+ {
+ return (X509Certificate[]) peerCertChain.clone();
+ }
+ try
+ {
+ peerCertChain = new X509Certificate[peerCerts.length];
+ for (int i = 0; i < peerCerts.length; i++)
+ {
+ peerCertChain[i] = X509Certificate.getInstance(peerCerts[i].getEncoded());
+ }
+ return (X509Certificate[]) peerCertChain.clone();
+ }
+ catch (javax.security.cert.CertificateException ce)
+ {
+ return null;
+ }
+ catch (CertificateException ce2)
+ {
+ return null;
+ }
+ }
+
+ public String getPeerHost()
+ {
+ return peerHost;
+ }
+
+ public String getProtocol()
+ {
+ return protocol.toString();
+ }
+
+ public SSLSessionContext getSessionContext()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ sm.checkPermission(GET_SESSION_CONTEXT_PERMISSION);
+ }
+ return context;
+ }
+
+ public String[] getValueNames()
+ {
+ Set names = values.keySet();
+ return (String[]) names.toArray(new String[names.size()]);
+ }
+
+ public Object getValue(String name)
+ {
+ return values.get(name);
+ }
+
+ public void putValue(String name, Object value)
+ {
+ values.put(name, value);
+ if (value instanceof SSLSessionBindingListener)
+ {
+ ((SSLSessionBindingListener) value).valueBound(
+ new SSLSessionBindingEvent(this, name));
+ }
+ }
+
+ public void removeValue(String name)
+ {
+ Object value = values.remove(name);
+ if (value != null && (value instanceof SSLSessionBindingListener))
+ {
+ ((SSLSessionBindingListener) value).valueUnbound(
+ new SSLSessionBindingEvent(this, name));
+ }
+ }
+
+ public void invalidate()
+ {
+ if (masterSecret != null)
+ {
+ for (int i = 0; i < masterSecret.length; i++)
+ {
+ masterSecret[i] = 0;
+ }
+ masterSecret = null;
+ }
+ valid = false;
+ }
+
+ synchronized void access()
+ {
+ lastAccessedTime.setTime(System.currentTimeMillis());
+ context.notifyAccess(this);
+ }
+
+ void setLastAccessedTime(long lastAccessedTime)
+ {
+ this.lastAccessedTime.setTime(lastAccessedTime);
+ }
+
+ // Inner classes.
+ // -------------------------------------------------------------------------
+
+ /**
+ * A byte array with appropriate <code>equals()</code>,
+ * <code>hashCode()</code>, and <code>compareTo()</code> semantics.
+ */
+ static final class ID implements Comparable
+ {
+
+ // Fields.
+ // -----------------------------------------------------------------------
+
+ /** The ID itself. */
+ private final byte[] id;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Creates a new ID.
+ *
+ * @param id The ID. The array is not cloned.
+ */
+ ID(byte[] id)
+ {
+ if (id == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ this.id = id;
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public byte[] getId()
+ {
+ return (byte[]) id.clone();
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other == null || !(other instanceof ID))
+ {
+ return false;
+ }
+ return Arrays.equals(id, ((ID) other).id);
+ }
+
+ public int hashCode()
+ {
+ int code = 0;
+ for (int i = 0; i < id.length; i++)
+ {
+ code |= (id[i] & 0xFF) << ((i & 3) << 3);
+ }
+ return code;
+ }
+
+ public int compareTo(Object other)
+ {
+ if (other == null || !(other instanceof ID))
+ {
+ return 1;
+ }
+ byte[] id2 = ((ID) other).id;
+ if (id.length != id2.length)
+ {
+ return (id.length < id2.length) ? -1 : 1;
+ }
+ for (int i = 0; i < id.length; i++)
+ {
+ if (id[i] < id2[i])
+ {
+ return -1;
+ }
+ else if (id[i] > id2[i])
+ {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ public String toString()
+ {
+ return Util.toHexString(id, ':');
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SessionContext.java b/gnu/javax/net/ssl/provider/SessionContext.java
new file mode 100644
index 000000000..9e265429a
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SessionContext.java
@@ -0,0 +1,250 @@
+/* SessionContext.java -- Implementation of a session context.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.security.Security;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionContext;
+
+/**
+ * A collection of SSL sessions. This implementation is a memory-only
+ * store; subclasses may implement persistent storage.
+ */
+class SessionContext implements SSLSessionContext
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ /** The map of Session.ID objects to Sessions. */
+ protected final HashMap sessions;
+
+ /** The number of sessions to cache. */
+ protected int cacheSize;
+
+ /** The session timeout, in seconds. */
+ protected int timeout;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ SessionContext()
+ {
+ sessions = new HashMap();
+ cacheSize = 0;
+ try
+ {
+ timeout = Integer.parseInt(Util.getSecurityProperty("jessie.session.timeout"));
+ }
+ catch (Exception x)
+ {
+ // Default 24-hour timeout.
+ timeout = 86400;
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public synchronized Enumeration getIds()
+ {
+ Vector ids = new Vector();
+ for(Iterator i = sessions.keySet().iterator(); i.hasNext(); )
+ {
+ Session.ID id = (Session.ID) i.next();
+ ids.add(id.getId());
+ }
+ return ids.elements();
+ }
+
+ public synchronized SSLSession getSession(byte[] sessionId)
+ {
+ Session session = (Session) sessions.get(new Session.ID(sessionId));
+ if (session == null)
+ return null;
+ long elapsed = System.currentTimeMillis() - session.getLastAccessedTime();
+ if ((int) (elapsed / 1000) > timeout)
+ {
+ removeSession(session.sessionId);
+ session.invalidate();
+ return null;
+ }
+ if (!session.valid)
+ {
+ removeSession(session.sessionId);
+ session.invalidate();
+ return null;
+ }
+ return session;
+ }
+
+ public int getSessionCacheSize()
+ {
+ return cacheSize;
+ }
+
+ public void setSessionCacheSize(int cacheSize)
+ {
+ if (cacheSize < 0)
+ throw new IllegalArgumentException();
+ this.cacheSize = cacheSize;
+ }
+
+ public int getSessionTimeout()
+ {
+ return timeout;
+ }
+
+ public void setSessionTimeout(int timeout)
+ {
+ if (timeout <= 0)
+ throw new IllegalArgumentException();
+ this.timeout = timeout;
+ }
+
+ public String toString()
+ {
+ return sessions.keySet().toString();
+ }
+
+ // Package methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Adds a session to this context. This method:
+ *
+ * <ol>
+ * <li>Will do nothing if the cache already contains the given ID.</li>
+ * <li>Will do nothing if the cache limit has been reached (and is
+ * not zero).</li>
+ * <li>Will remove any invalid sessions in the cache before trying to insert
+ * the new one.</li>
+ * <li>Will remove any expired sessions before trying to insert the new
+ * one.</li>
+ * </ol>
+ *
+ * @param sessionId This session's ID.
+ * @param session The session to add.
+ * @return True if the session was added, false otherwise.
+ */
+ synchronized boolean addSession(Session.ID sessionId, Session session)
+ {
+ if (sessions.containsKey(sessionId))
+ return false;
+ if (cacheSize > 0 && sessions.size() > cacheSize)
+ {
+ boolean removed = false;
+ for (Iterator i = sessions.values().iterator(); i.hasNext(); )
+ {
+ Session s = (Session) i.next();
+ long elapsed = System.currentTimeMillis() - s.getCreationTime();
+ if (!s.valid)
+ {
+ removeSession(session.sessionId);
+ removed = true;
+ }
+ else if ((int) (elapsed / 1000) > timeout)
+ {
+ removeSession(session.sessionId);
+ removed = true;
+ }
+ }
+ if (removed)
+ {
+ sessions.put(sessionId, session);
+ session.context = this;
+ session.sessionId = sessionId;
+ return true;
+ }
+ return false;
+ }
+ else
+ {
+ sessions.put(sessionId, session);
+ session.context = this;
+ session.sessionId = sessionId;
+ return true;
+ }
+ }
+
+ /**
+ * Returns whether or not a session with the given ID is cached by this
+ * context.
+ */
+ synchronized boolean containsSessionID(Session.ID sessionId)
+ {
+ Session s = (Session) sessions.get(sessionId);
+ if (s == null)
+ {
+ return false;
+ }
+ long elapsed = System.currentTimeMillis() - s.getCreationTime();
+ if (!s.valid || (int) (elapsed / 1000) > timeout)
+ {
+ removeSession(sessionId);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Removes a session from this context.
+ *
+ * @param sessionId The ID of the session to remove.
+ */
+ synchronized boolean removeSession(Session.ID sessionId)
+ {
+ return sessions.remove(sessionId) != null;
+ }
+
+ /**
+ * Notifies this context of an access event on a session.
+ *
+ * @param session The session that was accessed.
+ */
+ void notifyAccess(Session session)
+ {
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Signature.java b/gnu/javax/net/ssl/provider/Signature.java
new file mode 100644
index 000000000..c9be64143
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Signature.java
@@ -0,0 +1,158 @@
+/* Signature.java -- SSL signature message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.math.BigInteger;
+
+import java.security.PublicKey;
+import java.security.interfaces.RSAKey;
+
+import java.util.Arrays;
+
+import gnu.java.security.der.*;
+
+class Signature implements Constructed
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final Object sigValue;
+ private final String sigAlg;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ Signature(Object sigValue, String sigAlg)
+ {
+ this.sigValue = sigValue;
+ this.sigAlg = sigAlg;
+ }
+
+ // Class method.
+ // -------------------------------------------------------------------------
+
+ static Signature read(InputStream in, CipherSuite suite, PublicKey key)
+ throws IOException
+ {
+ Object sigValue = null;
+ DataInputStream din = new DataInputStream(in);
+ int len = din.readUnsignedShort();
+ sigValue = new byte[len];
+ din.readFully((byte[]) sigValue);
+ if (suite.getSignature() == "DSS")
+ {
+ DERReader der = new DERReader(new ByteArrayInputStream((byte[]) sigValue));
+ if (der.read().getTag() != DER.SEQUENCE)
+ {
+ throw new IOException("expecting DER SEQUENCE");
+ }
+ BigInteger r = (BigInteger) der.read().getValue();
+ BigInteger s = (BigInteger) der.read().getValue();
+ sigValue = new BigInteger[] { r, s };
+ }
+ return new Signature(sigValue, suite.getSignature());
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void write(OutputStream out) throws IOException
+ {
+ write(out, ProtocolVersion.TLS_1);
+ }
+
+ public void write(OutputStream out, ProtocolVersion version)
+ throws IOException
+ {
+ byte[] result = null;
+ if (sigValue instanceof byte[])
+ {
+ result = (byte[]) sigValue;
+ }
+ else
+ {
+ DERValue r = new DERValue(DER.INTEGER, ((BigInteger[]) sigValue)[0]);
+ DERValue s = new DERValue(DER.INTEGER, ((BigInteger[]) sigValue)[1]);
+ DERValue sig = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED,
+ Arrays.asList(new Object[] { r, s }));
+ result = sig.getEncoded();
+ }
+ out.write(result.length >>> 8 & 0xFF);
+ out.write(result.length & 0xFF);
+ out.write(result);
+ }
+
+ Object getSigValue()
+ {
+ return sigValue;
+ }
+
+ String getSigAlg()
+ {
+ return sigAlg;
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println("struct {");
+ if (sigAlg.equals("RSA"))
+ {
+ out.print(Util.hexDump((byte[]) sigValue, " "));
+ }
+ else
+ {
+ out.println(" r = " + ((BigInteger[]) sigValue)[0].toString(16) + ";");
+ out.println(" s = " + ((BigInteger[]) sigValue)[1].toString(16) + ";");
+ }
+ out.println("} Signature;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SynchronizedRandom.java b/gnu/javax/net/ssl/provider/SynchronizedRandom.java
new file mode 100644
index 000000000..4e22f08be
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SynchronizedRandom.java
@@ -0,0 +1,104 @@
+/* SynchronizedRandom.java -- Thread-safe IRandom wrapper.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.util.Map;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+
+class SynchronizedRandom implements IRandom
+{
+
+ // Field.
+ // -------------------------------------------------------------------------
+
+ private final IRandom random;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ SynchronizedRandom(IRandom random)
+ {
+ this.random = random;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String name()
+ {
+ return random.name();
+ }
+
+ public synchronized void init(Map attrib)
+ {
+ random.init(attrib);
+ }
+
+ public synchronized byte nextByte()
+ throws IllegalStateException, LimitReachedException
+ {
+ return random.nextByte();
+ }
+
+ public synchronized void nextBytes(byte[] buf, int off, int len)
+ throws IllegalStateException, LimitReachedException
+ {
+ random.nextBytes(buf, off, len);
+ }
+
+ public synchronized Object clone()
+ throws CloneNotSupportedException
+ {
+ return new SynchronizedRandom((IRandom) random.clone());
+ }
+
+ // For future versions of GNU Crypto. No-ops.
+ public void addRandomByte (byte b)
+ {
+ }
+
+ public void addRandomBytes(byte[] buffer) {
+ addRandomBytes(buffer, 0, buffer.length);
+ }
+
+ public void addRandomBytes (byte[] b, int i, int j)
+ {
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/TLSHMac.java b/gnu/javax/net/ssl/provider/TLSHMac.java
new file mode 100644
index 000000000..18aa8f5f4
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/TLSHMac.java
@@ -0,0 +1,138 @@
+/* TLSHMac.java -- HMAC used in TLS.
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.security.InvalidKeyException;
+import java.util.HashMap;
+import java.util.Map;
+
+import gnu.java.security.hash.IMessageDigest;
+import gnu.javax.crypto.mac.HMac;
+
+/**
+ * The operation of this HMac is identical to normal HMacs, but this one
+ * allows keys with short lengths (including zero).
+ */
+class TLSHMac extends HMac
+{
+
+ // Constants.
+ // -------------------------------------------------------------------------
+
+ private static final byte IPAD_BYTE = 0x36;
+ private static final byte OPAD_BYTE = 0x5C;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ TLSHMac(IMessageDigest hash)
+ {
+ super(hash);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void init(Map attributes)
+ throws InvalidKeyException, IllegalStateException
+ {
+ Integer ts = (Integer) attributes.get(TRUNCATED_SIZE);
+ truncatedSize = (ts == null ? macSize : ts.intValue());
+ if (truncatedSize < (macSize / 2)) {
+ throw new IllegalArgumentException("Truncated size too small");
+ } else if (truncatedSize < 10) {
+ throw new IllegalArgumentException("Truncated size less than 80 bits");
+ }
+
+ // we dont use/save the key outside this method
+ byte[] K = (byte[]) attributes.get(MAC_KEY_MATERIAL);
+ if (K == null) { // take it as an indication to re-use previous key if set
+ if (ipadHash == null)
+ {
+ throw new InvalidKeyException("Null key");
+ }
+ // we already went through the motions; ie. up to step #4. re-use
+ underlyingHash = (IMessageDigest) ipadHash.clone();
+ return;
+ }
+
+ if (K.length > blockSize)
+ {
+ // (0) replace K with HASH(K) if K is larger than the hash's
+ // block size. Then pad with zeros until it is the correct
+ // size (the next `if').
+ underlyingHash.update(K, 0, K.length);
+ K = underlyingHash.digest();
+ }
+ if (K.length < blockSize)
+ {
+ // (1) append zeros to the end of K to create a B byte string
+ // (e.g., if K is of length 20 bytes and B=64, then K will be
+ // appended with 44 zero bytes 0x00)
+ int limit = (K.length > blockSize) ? blockSize : K.length;
+ byte[] newK = new byte[blockSize];
+ System.arraycopy(K, 0, newK, 0, limit);
+ K = newK;
+ }
+
+ underlyingHash.reset();
+ opadHash = (IMessageDigest) underlyingHash.clone();
+ if (ipad == null)
+ {
+ ipad = new byte[blockSize];
+ }
+ // (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+ // (1) with ipad
+ // (3) append the stream of data 'text' to the B byte string resulting
+ // from step (2)
+ // (4) apply H to the stream generated in step (3)
+ for (int i = 0; i < blockSize; i++)
+ {
+ ipad[i] = (byte)(K[i] ^ IPAD_BYTE);
+ }
+ for (int i = 0; i < blockSize; i++)
+ {
+ opadHash.update((byte)(K[i] ^ OPAD_BYTE));
+ }
+
+ underlyingHash.update(ipad, 0, blockSize);
+ ipadHash = (IMessageDigest) underlyingHash.clone();
+ K = null;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/TLSRandom.java b/gnu/javax/net/ssl/provider/TLSRandom.java
new file mode 100644
index 000000000..ded632928
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/TLSRandom.java
@@ -0,0 +1,252 @@
+/* TLSRandom.java -- The TLS pseudo-random function.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.security.InvalidKeyException;
+import java.util.HashMap;
+import java.util.Map;
+
+import gnu.java.security.hash.HashFactory;
+import gnu.javax.crypto.mac.IMac;
+import gnu.java.security.prng.IRandom;
+
+class TLSRandom implements IRandom
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Property name for the secret that will be used to initialize the HMACs.
+ */
+ static final String SECRET = "jessie.tls.prng.secret";
+
+ /**
+ * Property name for the seed.
+ */
+ static final String SEED = "jessie.tls.prng.seed";
+
+ private final IMac hmac_sha, hmac_md5;
+ private byte[] sha_a, md5_a;
+ private byte[] seed;
+ private final byte[] buffer;
+ private int idx;
+ private boolean init;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ TLSRandom()
+ {
+ hmac_sha = new TLSHMac(HashFactory.getInstance("SHA1"));
+ hmac_md5 = new TLSHMac(HashFactory.getInstance("MD5"));
+ buffer = new byte[80]; // 80 == LCM of 16 and 20.
+ idx = 0;
+ init = false;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException shouldNotHappen)
+ {
+ throw new Error();
+ }
+ }
+
+ public void init(Map attributes)
+ {
+ HashMap sha_attr = new HashMap();
+ HashMap md5_attr = new HashMap();
+ byte[] secret = (byte[]) attributes.get(SECRET);
+ if (secret != null)
+ {
+ int l = (secret.length >>> 1) + (secret.length & 1);
+ byte[] s1 = Util.trim(secret, 0, l);
+ byte[] s2 = Util.trim(secret, secret.length - l, l);
+ md5_attr.put(IMac.MAC_KEY_MATERIAL, s1);
+ sha_attr.put(IMac.MAC_KEY_MATERIAL, s2);
+ try
+ {
+ hmac_md5.init(md5_attr);
+ hmac_sha.init(sha_attr);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new Error(ike.toString());
+ }
+ }
+ else if (!init)
+ {
+ throw new IllegalArgumentException("no secret supplied");
+ }
+ // else re-use
+
+ byte[] seeed = (byte[]) attributes.get(SEED);
+ if (seeed != null)
+ {
+ seed = (byte[]) seeed.clone();
+ }
+ else if (!init)
+ {
+ throw new IllegalArgumentException("no seed supplied");
+ }
+ // else re-use
+
+ // A(0) is the seed, A(1) = HMAC_hash(secret, A(0)).
+ hmac_md5.update(seed, 0, seed.length);
+ md5_a = hmac_md5.digest();
+ hmac_md5.reset();
+ hmac_sha.update(seed, 0, seed.length);
+ sha_a = hmac_sha.digest();
+ hmac_sha.reset();
+ fillBuffer();
+ init = true;
+ }
+
+ public String name()
+ {
+ return "TLSRandom";
+ }
+
+ public byte nextByte()
+ {
+ if (!init)
+ throw new IllegalStateException();
+ if (idx >= buffer.length)
+ fillBuffer();
+ return buffer[idx++];
+ }
+
+ public void nextBytes(byte[] buf, int off, int len)
+ {
+ if (!init)
+ throw new IllegalStateException();
+ if (buf == null)
+ throw new NullPointerException();
+ if (off < 0 || off > buf.length || off + len > buf.length)
+ throw new ArrayIndexOutOfBoundsException();
+ int count = 0;
+ if (idx >= buffer.length)
+ fillBuffer();
+ while (count < len)
+ {
+ int l = Math.min(buffer.length-idx, len-count);
+ System.arraycopy(buffer, idx, buf, off+count, l);
+ idx += l;
+ count += l;
+ if (count < len && idx >= buffer.length)
+ fillBuffer();
+ }
+ }
+
+ // For future versions of GNU Crypto. No-ops.
+ public void addRandomByte (byte b)
+ {
+ }
+
+ public void addRandomBytes(byte[] buffer) {
+ addRandomBytes(buffer, 0, buffer.length);
+ }
+
+ public void addRandomBytes (byte[] b, int i, int j)
+ {
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ /*
+ * The PRF is defined as:
+ *
+ * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
+ * P_SHA-1(S2, label + seed);
+ *
+ * P_hash is defined as:
+ *
+ * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
+ * HMAC_hash(secret, A(2) + seed) +
+ * HMAC_hash(secret, A(3) + seed) + ...
+ *
+ * And A() is defined as:
+ *
+ * A(0) = seed
+ * A(i) = HMAC_hash(secret, A(i-1))
+ *
+ * For simplicity, we compute an 80-byte block on each call, which
+ * corresponds to five iterations of MD5, and four of SHA-1.
+ */
+ private synchronized void fillBuffer()
+ {
+ int len = hmac_md5.macSize();
+ for (int i = 0; i < buffer.length; i += len)
+ {
+ hmac_md5.update(md5_a, 0, md5_a.length);
+ hmac_md5.update(seed, 0, seed.length);
+ byte[] b = hmac_md5.digest();
+ hmac_md5.reset();
+ System.arraycopy(b, 0, buffer, i, len);
+ hmac_md5.update(md5_a, 0, md5_a.length);
+ md5_a = hmac_md5.digest();
+ hmac_md5.reset();
+ }
+ len = hmac_sha.macSize();
+ for (int i = 0; i < buffer.length; i += len)
+ {
+ hmac_sha.update(sha_a, 0, sha_a.length);
+ hmac_sha.update(seed, 0, seed.length);
+ byte[] b = hmac_sha.digest();
+ hmac_sha.reset();
+ for (int j = 0; j < len; j++)
+ {
+ buffer[j + i] ^= b[j];
+ }
+ hmac_sha.update(sha_a, 0, sha_a.length);
+ sha_a = hmac_sha.digest();
+ hmac_sha.reset();
+ }
+ idx = 0;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Util.java b/gnu/javax/net/ssl/provider/Util.java
new file mode 100644
index 000000000..15790dd26
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Util.java
@@ -0,0 +1,422 @@
+/* Util.java -- Miscellaneous utility methods.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+
+/**
+ * A collection of useful class methods.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+final class Util
+{
+
+ // Constants.
+ // -------------------------------------------------------------------------
+
+ static final String HEX = "0123456789abcdef";
+
+ // Static methods only.
+ private Util() { }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Convert a hexadecimal string into its byte representation.
+ *
+ * @param hex The hexadecimal string.
+ * @return The converted bytes.
+ */
+ static byte[] toByteArray(String hex)
+ {
+ hex = hex.toLowerCase();
+ byte[] buf = new byte[hex.length() / 2];
+ int j = 0;
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = (byte) ((Character.digit(hex.charAt(j++), 16) << 4) |
+ Character.digit(hex.charAt(j++), 16));
+ }
+ return buf;
+ }
+
+ /**
+ * Convert a byte array to a hexadecimal string, as though it were a
+ * big-endian arbitrarily-sized integer.
+ *
+ * @param buf The bytes to format.
+ * @param off The offset to start at.
+ * @param len The number of bytes to format.
+ * @return A hexadecimal representation of the specified bytes.
+ */
+ static String toHexString(byte[] buf, int off, int len)
+ {
+ StringBuffer str = new StringBuffer();
+ for (int i = 0; i < len; i++)
+ {
+ str.append(HEX.charAt(buf[i+off] >>> 4 & 0x0F));
+ str.append(HEX.charAt(buf[i+off] & 0x0F));
+ }
+ return str.toString();
+ }
+
+ /**
+ * See {@link #toHexString(byte[],int,int)}.
+ */
+ static String toHexString(byte[] buf)
+ {
+ return Util.toHexString(buf, 0, buf.length);
+ }
+
+ /**
+ * Convert a byte array to a hexadecimal string, separating octets
+ * with the given character.
+ *
+ * @param buf The bytes to format.
+ * @param off The offset to start at.
+ * @param len The number of bytes to format.
+ * @param sep The character to insert between octets.
+ * @return A hexadecimal representation of the specified bytes.
+ */
+ static String toHexString(byte[] buf, int off, int len, char sep)
+ {
+ StringBuffer str = new StringBuffer();
+ for (int i = 0; i < len; i++)
+ {
+ str.append(HEX.charAt(buf[i+off] >>> 4 & 0x0F));
+ str.append(HEX.charAt(buf[i+off] & 0x0F));
+ if (i < len - 1)
+ str.append(sep);
+ }
+ return str.toString();
+ }
+
+ /**
+ * See {@link #toHexString(byte[],int,int,char)}.
+ */
+ static String toHexString(byte[] buf, char sep)
+ {
+ return Util.toHexString(buf, 0, buf.length, sep);
+ }
+
+ /**
+ * Create a representation of the given byte array similar to the
+ * output of <code>`hexdump -C'</code>, which is
+ *
+ * <p><pre>OFFSET SIXTEEN-BYTES-IN-HEX PRINTABLE-BYTES</pre>
+ *
+ * <p>The printable bytes show up as-is if they are printable and
+ * not a newline character, otherwise showing as '.'.
+ *
+ * @param buf The bytes to format.
+ * @param off The offset to start at.
+ * @param len The number of bytes to encode.
+ * @param prefix A string to prepend to every line.
+ * @return The formatted string.
+ */
+ static String hexDump(byte[] buf, int off, int len, String prefix)
+ {
+ String nl = getProperty("line.separator");
+ StringBuffer str = new StringBuffer();
+ int i = 0;
+ while (i < len)
+ {
+ if (prefix != null)
+ str.append(prefix);
+ str.append(Util.formatInt(i+off, 16, 8));
+ str.append(" ");
+ String s = Util.toHexString(buf, i+off, Math.min(16, len-i), ' ');
+ str.append(s);
+ for (int j = 56 - (56 - s.length()); j < 56; j++)
+ str.append(" ");
+ for (int j = 0; j < Math.min(16, len - i); j++)
+ {
+ if ((buf[i+off+j] & 0xFF) < 0x20 || (buf[i+off+j] & 0xFF) > 0x7E)
+ str.append('.');
+ else
+ str.append((char) (buf[i+off+j] & 0xFF));
+ }
+ str.append(nl);
+ i += 16;
+ }
+ return str.toString();
+ }
+
+ /**
+ * See {@link #hexDump(byte[],int,int,String)}.
+ */
+ static String hexDump(byte[] buf, int off, int len)
+ {
+ return hexDump(buf, off, len, "");
+ }
+
+ /**
+ * See {@link #hexDump(byte[],int,int,String)}.
+ */
+ static String hexDump(byte[] buf, String prefix)
+ {
+ return hexDump(buf, 0, buf.length, prefix);
+ }
+
+ /**
+ * See {@link #hexDump(byte[],int,int,String)}.
+ */
+ static String hexDump(byte[] buf)
+ {
+ return hexDump(buf, 0, buf.length);
+ }
+
+ /**
+ * Format an integer into the specified radix, zero-filled.
+ *
+ * @param i The integer to format.
+ * @param radix The radix to encode to.
+ * @param len The target length of the string. The string is
+ * zero-padded to this length, but may be longer.
+ * @return The formatted integer.
+ */
+ static String formatInt(int i, int radix, int len)
+ {
+ String s = Integer.toString(i, radix);
+ StringBuffer buf = new StringBuffer();
+ for (int j = 0; j < len - s.length(); j++)
+ buf.append("0");
+ buf.append(s);
+ return buf.toString();
+ }
+
+ /**
+ * Concatenate two byte arrays into one.
+ *
+ * @param b1 The first byte array.
+ * @param b2 The second byte array.
+ * @return The concatenation of b1 and b2.
+ */
+ static byte[] concat(byte[] b1, byte[] b2)
+ {
+ byte[] b3 = new byte[b1.length+b2.length];
+ System.arraycopy(b1, 0, b3, 0, b1.length);
+ System.arraycopy(b2, 0, b3, b1.length, b2.length);
+ return b3;
+ }
+
+ /**
+ * See {@link #trim(byte[],int,int)}.
+ */
+ static byte[] trim(byte[] buffer, int len)
+ {
+ return trim(buffer, 0, len);
+ }
+
+ /**
+ * Returns a portion of a byte array, possibly zero-filled.
+ *
+ * @param buffer The byte array to trim.
+ * @param off The offset to begin reading at.
+ * @param len The number of bytes to return. This value can be larger
+ * than <i>buffer.length - off</i>, in which case the rest of the
+ * returned byte array will be filled with zeros.
+ * @throws IndexOutOfBoundsException If <i>off</i> or <i>len</i> is
+ * negative, or if <i>off</i> is larger than the byte array's
+ * length.
+ * @return The trimmed byte array.
+ */
+ static byte[] trim(byte[] buffer, int off, int len)
+ {
+ if (off < 0 || len < 0 || off > buffer.length)
+ throw new IndexOutOfBoundsException("max=" + buffer.length +
+ " off=" + off + " len=" + len);
+ if (off == 0 && len == buffer.length)
+ return buffer;
+ byte[] b = new byte[len];
+ System.arraycopy(buffer, off, b, 0, Math.min(len, buffer.length - off));
+ return b;
+ }
+
+ /**
+ * Returns the byte array representation of the given big integer with
+ * the leading zero byte (if any) trimmed off.
+ *
+ * @param bi The integer to trim.
+ * @return The byte representation of the big integer, with any leading
+ * zero removed.
+ */
+ static byte[] trim(BigInteger bi)
+ {
+ byte[] buf = bi.toByteArray();
+ if (buf[0] == 0x00 && !bi.equals(BigInteger.ZERO))
+ {
+ return trim(buf, 1, buf.length - 1);
+ }
+ else
+ {
+ return buf;
+ }
+ }
+
+ /**
+ * Returns the integer value of <code>{@link
+ * java.lang.System#currentTimeMillis()} / 1000</code>.
+ *
+ * @return The current time, in seconds.
+ */
+ static int unixTime()
+ {
+ return (int) (System.currentTimeMillis() / 1000L);
+ }
+
+ /**
+ * Transform an Object array into another by calling the given method
+ * on each object. The returned object array will have the runtime
+ * type of <i>returnType</i>. For example, the following will transform
+ * array of objects into their String representations, returning a String
+ * array. For example:
+ *
+ * <blockquote><p><code>
+ * String[] strings = (String[]) Util.transform(array, String.class,
+ * "toString", null);
+ * </code></p></blockquote>
+ *
+ * <p>If any element of the given array is <tt>null</tt>, then that
+ * entry in the returned array will also be <tt>null</tt>.
+ *
+ * @param array The array to transform. It does not need to be of
+ * uniform type.
+ * @param returnType The desired return type of the returned array.
+ * This must by the <i>component</i> type, not the array type.
+ * @param method The name of the method to invoke from each object.
+ * @param args The arguments to pass to the method, or <tt>null</tt>
+ * if the method takes no arguments.
+ * @throws InvocationTargetException If an exception occurs while
+ * calling <i>method</i> of any object.
+ * @throws NoSuchMethodException If <i>method</i> is not the name of
+ * a valid method of any component of the array.
+ * @throws ClassCastException If the returned object from the method
+ * is not assignable to the return type.
+ * @throws IllegalArgumentException If <i>args</i> is not appropriate
+ * for <i>method</i>
+ * @throws IllegalAccessException If <i>method</i> is not accessible.
+ * @throws SecurityException If <i>method</i> is not accessible.
+ * @return An array containing the output of <i>method</i> called on
+ * each element of <i>array</i> with <i>args</i>. The return type
+ * of the array will be an array of <i>returnType</i>.
+ */
+ static Object[] transform(Object[] array, Class returnType,
+ String method, Object[] args)
+ throws InvocationTargetException, NoSuchMethodException,
+ IllegalAccessException
+ {
+ if (args == null)
+ args = new Object[0];
+ Object[] result = (Object[]) Array.newInstance(returnType, array.length);
+ Class[] argsClasses = new Class[args.length];
+ for (int i = 0; i < args.length; i++)
+ {
+ argsClasses[i] = args[i].getClass();
+ }
+ for (int i = 0; i < array.length; i++)
+ {
+ if (array[i] == null)
+ {
+ result[i] = null;
+ continue;
+ }
+ Class objClass = array[i].getClass();
+ Method objMethod = objClass.getMethod(method, argsClasses);
+ Object o = objMethod.invoke(array[i], args);
+ if (!returnType.isAssignableFrom(o.getClass()))
+ throw new ClassCastException();
+ result[i] = o;
+ }
+ return result;
+ }
+
+ /**
+ * Get a system property as a privileged action.
+ *
+ * @param name The name of the property to get.
+ * @return The property named <i>name</i>, or null if the property is
+ * not set.
+ * @throws SecurityException If the Jessie code still does not have
+ * permission to read the property.
+ */
+ static String getProperty(final String name)
+ {
+ return (String) AccessController.doPrivileged(
+ new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return System.getProperty(name);
+ }
+ }
+ );
+ }
+
+ /**
+ * Get a security property as a privileged action.
+ *
+ * @param name The name of the property to get.
+ * @return The property named <i>name</i>, or null if the property is
+ * not set.
+ * @throws SecurityException If the Jessie code still does not have
+ * permission to read the property.
+ */
+ static String getSecurityProperty(final String name)
+ {
+ return (String) AccessController.doPrivileged(
+ new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return Security.getProperty(name);
+ }
+ }
+ );
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java b/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java
new file mode 100644
index 000000000..476655c45
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java
@@ -0,0 +1,359 @@
+/* X509KeyManagerFactory.java -- X.509 key manager factory.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.Socket;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Enumeration;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.List;
+
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactorySpi;
+import javax.net.ssl.ManagerFactoryParameters;
+import javax.net.ssl.X509KeyManager;
+
+import gnu.javax.net.ssl.NullManagerParameters;
+import gnu.javax.net.ssl.PrivateCredentials;
+
+/**
+ * This class implements a {@link javax.net.ssl.KeyManagerFactory} engine
+ * for the ``JessieX509'' algorithm.
+ */
+public class X509KeyManagerFactory extends KeyManagerFactorySpi
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private Manager current;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public X509KeyManagerFactory()
+ {
+ super();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ protected KeyManager[] engineGetKeyManagers()
+ {
+ if (current == null)
+ {
+ throw new IllegalStateException();
+ }
+ return new KeyManager[] { current };
+ }
+
+ protected void engineInit(ManagerFactoryParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ if (params instanceof NullManagerParameters)
+ {
+ current = new Manager(Collections.EMPTY_MAP, Collections.EMPTY_MAP);
+ }
+ else if (params instanceof PrivateCredentials)
+ {
+ List chains = ((PrivateCredentials) params).getCertChains();
+ List keys = ((PrivateCredentials) params).getPrivateKeys();
+ int i = 0;
+ HashMap certMap = new HashMap();
+ HashMap keyMap = new HashMap();
+ Iterator c = chains.iterator();
+ Iterator k = keys.iterator();
+ while (c.hasNext() && k.hasNext())
+ {
+ certMap.put(String.valueOf(i), c.next());
+ keyMap.put(String.valueOf(i), k.next());
+ i++;
+ }
+ current = new Manager(keyMap, certMap);
+ }
+ else
+ {
+ throw new InvalidAlgorithmParameterException();
+ }
+ }
+
+ protected void engineInit(KeyStore store, char[] passwd)
+ throws KeyStoreException, NoSuchAlgorithmException,
+ UnrecoverableKeyException
+ {
+ if (store == null)
+ {
+ String s = Util.getProperty("javax.net.ssl.keyStoreType");
+ if (s == null)
+ s = KeyStore.getDefaultType();
+ store = KeyStore.getInstance(s);
+ s = Util.getProperty("javax.net.ssl.keyStore");
+ if (s == null)
+ return;
+ String p = Util.getProperty("javax.net.ssl.keyStorePassword");
+ try
+ {
+ store.load(new FileInputStream(s), p != null ? p.toCharArray() : null);
+ }
+ catch (IOException ioe)
+ {
+ throw new KeyStoreException(ioe.toString());
+ }
+ catch (CertificateException ce)
+ {
+ throw new KeyStoreException(ce.toString());
+ }
+ }
+
+ HashMap p = new HashMap();
+ HashMap c = new HashMap();
+ Enumeration aliases = store.aliases();
+ UnrecoverableKeyException exception = null;
+ while (aliases.hasMoreElements())
+ {
+ String alias = (String) aliases.nextElement();
+ if (!store.isKeyEntry(alias))
+ {
+ continue;
+ }
+ X509Certificate[] chain = null;
+ Certificate[] chain2 = store.getCertificateChain (alias);
+ if (chain2 != null && chain2.length > 0 &&
+ (chain2[0] instanceof X509Certificate))
+ {
+ chain = toX509Chain(chain2);
+ }
+ else
+ {
+ continue;
+ }
+ PrivateKey key = null;
+ try
+ {
+ key = (PrivateKey) store.getKey(alias, passwd);
+ }
+ catch (UnrecoverableKeyException uke)
+ {
+ exception = uke;
+ continue;
+ }
+ if (key == null)
+ {
+ continue;
+ }
+ p.put(alias, key);
+ c.put(alias, chain);
+ }
+ if (p.isEmpty () && c.isEmpty ())
+ {
+ if (exception != null)
+ {
+ throw exception;
+ }
+ throw new KeyStoreException ("no private credentials found");
+ }
+ current = this.new Manager(p, c);
+ }
+
+ private static X509Certificate[] toX509Chain(Certificate[] chain)
+ {
+ if (chain instanceof X509Certificate[])
+ {
+ return (X509Certificate[]) chain;
+ }
+ X509Certificate[] _chain = new X509Certificate[chain.length];
+ for (int i = 0; i < chain.length; i++)
+ _chain[i] = (X509Certificate) chain[i];
+ return _chain;
+ }
+
+ // Inner class.
+ // -------------------------------------------------------------------------
+
+ private class Manager implements X509KeyManager
+ {
+ // Fields.
+ // -----------------------------------------------------------------------
+
+ private final Map privateKeys;
+ private final Map certChains;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ Manager(Map privateKeys, Map certChains)
+ {
+ this.privateKeys = privateKeys;
+ this.certChains = certChains;
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
+ Socket socket)
+ {
+ for (int i = 0; i < keyTypes.length; i++)
+ {
+ String[] s = getClientAliases(keyTypes[i], issuers);
+ if (s.length > 0)
+ return s[0];
+ }
+ return null;
+ }
+
+ public String[] getClientAliases(String keyType, Principal[] issuers)
+ {
+ return getAliases(keyType, issuers);
+ }
+
+ public String chooseServerAlias(String keyType, Principal[] issuers,
+ Socket socket)
+ {
+ String[] s = getServerAliases(keyType, issuers);
+ if (s.length > 0)
+ return s[0];
+ return null;
+ }
+
+ public String[] getServerAliases(String keyType, Principal[] issuers)
+ {
+ return getAliases(keyType, issuers);
+ }
+
+ private String[] getAliases(String keyType, Principal[] issuers)
+ {
+ LinkedList l = new LinkedList();
+ for (Iterator i = privateKeys.keySet().iterator(); i.hasNext(); )
+ {
+ String alias = (String) i.next();
+ X509Certificate[] chain = getCertificateChain(alias);
+ if (chain.length == 0)
+ continue;
+ PrivateKey privKey = getPrivateKey(alias);
+ if (privKey == null)
+ continue;
+ PublicKey pubKey = chain[0].getPublicKey();
+ if (keyType.equals("RSA") || keyType.equals("DHE_RSA") ||
+ keyType.equals("SRP_RSA") || keyType.equals("rsa_sign"))
+ {
+ if (!(privKey instanceof RSAPrivateKey) ||
+ !(pubKey instanceof RSAPublicKey))
+ continue;
+ }
+ if (keyType.equals("DHE_DSS") || keyType.equals("dss_sign") ||
+ keyType.equals("SRP_DSS"))
+ {
+ if (!(privKey instanceof DSAPrivateKey) ||
+ !(pubKey instanceof DSAPublicKey))
+ continue;
+ }
+ if (keyType.equals("DH_RSA") || keyType.equals("rsa_fixed_dh"))
+ {
+ if (!(privKey instanceof DHPrivateKey) ||
+ !(pubKey instanceof DHPublicKey))
+ continue;
+ if (!chain[0].getSigAlgName().equalsIgnoreCase("RSA"))
+ continue;
+ }
+ if (keyType.equals("DH_DSS") || keyType.equals("dss_fixed_dh"))
+ {
+ if (!(privKey instanceof DHPrivateKey) ||
+ !(pubKey instanceof DHPublicKey))
+ continue;
+ if (!chain[0].getSigAlgName().equalsIgnoreCase("DSA"))
+ continue;
+ }
+ if (issuers == null || issuers.length == 0)
+ {
+ l.add(alias);
+ continue;
+ }
+ for (int j = 0; j < issuers.length; j++)
+ if (chain[0].getIssuerDN().equals(issuers[j]))
+ {
+ l.add(alias);
+ break;
+ }
+ }
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+
+ public X509Certificate[] getCertificateChain(String alias)
+ {
+ X509Certificate[] c = (X509Certificate[]) certChains.get(alias);
+ return c != null ? (X509Certificate[]) c.clone() : null;
+ }
+
+ public PrivateKey getPrivateKey(String alias)
+ {
+ return (PrivateKey) privateKeys.get(alias);
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java b/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java
new file mode 100644
index 000000000..4f049e916
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java
@@ -0,0 +1,298 @@
+/* X509TrustManagerFactory.java -- X.509 trust manager factory.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.SignatureException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.ManagerFactoryParameters;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactorySpi;
+import javax.net.ssl.X509TrustManager;
+
+import gnu.javax.net.ssl.NullManagerParameters;
+import gnu.javax.net.ssl.StaticTrustAnchors;
+
+/**
+ * This class implements a {@link javax.net.ssl.TrustManagerFactory} engine
+ * for the ``JessieX509'' algorithm.
+ */
+public class X509TrustManagerFactory extends TrustManagerFactorySpi
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The location of the JSSE key store.
+ */
+ private static final String JSSE_CERTS = Util.getProperty("java.home")
+ + Util.getProperty("file.separator") + "lib"
+ + Util.getProperty("file.separator") + "security"
+ + Util.getProperty("file.separator") + "jssecerts";
+
+ /**
+ * The location of the system key store, containing the CA certs.
+ */
+ private static final String CA_CERTS = Util.getProperty("java.home")
+ + Util.getProperty("file.separator") + "lib"
+ + Util.getProperty("file.separator") + "security"
+ + Util.getProperty("file.separator") + "cacerts";
+
+ private Manager current;
+
+ // Construtors.
+ // -------------------------------------------------------------------------
+
+ public X509TrustManagerFactory()
+ {
+ super();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ protected TrustManager[] engineGetTrustManagers()
+ {
+ if (current == null)
+ {
+ throw new IllegalStateException("not initialized");
+ }
+ return new TrustManager[] { current };
+ }
+
+ protected void engineInit(ManagerFactoryParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ if (params instanceof StaticTrustAnchors)
+ {
+ current = new Manager(((StaticTrustAnchors) params).getCertificates());
+ }
+ else if (params instanceof NullManagerParameters)
+ {
+ current = new Manager(new X509Certificate[0]);
+ }
+ else
+ {
+ throw new InvalidAlgorithmParameterException();
+ }
+ }
+
+ protected void engineInit(KeyStore store) throws KeyStoreException
+ {
+ if (store == null)
+ {
+ String s = Util.getProperty("javax.net.ssl.trustStoreType");
+ if (s == null)
+ s = KeyStore.getDefaultType();
+ store = KeyStore.getInstance(s);
+ try
+ {
+ s = Util.getProperty("javax.net.ssl.trustStore");
+ FileInputStream in = null;
+ if (s == null)
+ {
+ try
+ {
+ in = new FileInputStream(JSSE_CERTS);
+ }
+ catch (IOException e)
+ {
+ in = new FileInputStream(CA_CERTS);
+ }
+ }
+ else
+ {
+ in = new FileInputStream(s);
+ }
+ String p = Util.getProperty("javax.net.ssl.trustStorePassword");
+ store.load(in, p != null ? p.toCharArray() : null);
+ }
+ catch (IOException ioe)
+ {
+ throw new KeyStoreException(ioe.toString());
+ }
+ catch (CertificateException ce)
+ {
+ throw new KeyStoreException(ce.toString());
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new KeyStoreException(nsae.toString());
+ }
+ }
+
+ LinkedList l = new LinkedList();
+ Enumeration aliases = store.aliases();
+ while (aliases.hasMoreElements())
+ {
+ String alias = (String) aliases.nextElement();
+ if (!store.isCertificateEntry(alias))
+ continue;
+ Certificate c = store.getCertificate(alias);
+ if (!(c instanceof X509Certificate))
+ continue;
+ l.add(c);
+ }
+ current = this.new Manager((X509Certificate[])
+ l.toArray(new X509Certificate[l.size()]));
+ }
+
+ // Inner class.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The actual manager implementation returned.
+ */
+ private class Manager implements X509TrustManager
+ {
+
+ // Fields.
+ // -----------------------------------------------------------------------
+
+ private final X509Certificate[] trusted;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ Manager(X509Certificate[] trusted)
+ {
+ this.trusted = trusted;
+ }
+
+ // Instance methodns.
+ // -----------------------------------------------------------------------
+
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException
+ {
+ checkTrusted(chain, authType);
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException
+ {
+ checkTrusted(chain, authType);
+ }
+
+ public X509Certificate[] getAcceptedIssuers()
+ {
+ if (trusted == null)
+ return new X509Certificate[0];
+ return (X509Certificate[]) trusted.clone();
+ }
+
+ // Own methods.
+ // -----------------------------------------------------------------------
+
+ private void checkTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException
+ {
+ // NOTE: this is not a full-featured path validation algorithm.
+ //
+ // Step 0: check if the target is valid now.
+ chain[0].checkValidity();
+
+ // Step 1: verify that the chain is complete and valid.
+ for (int i = 1; i < chain.length; i++)
+ {
+ chain[i].checkValidity();
+ try
+ {
+ chain[i-1].verify(chain[i].getPublicKey());
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new CertificateException(nsae.toString());
+ }
+ catch (NoSuchProviderException nspe)
+ {
+ throw new CertificateException(nspe.toString());
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new CertificateException(ike.toString());
+ }
+ catch (SignatureException se)
+ {
+ throw new CertificateException(se.toString());
+ }
+ }
+
+ // Step 2: verify that the root of the chain was issued by a trust anchor.
+ if (trusted == null || trusted.length == 0)
+ throw new CertificateException("no trust anchors");
+ for (int i = 0; i < trusted.length; i++)
+ {
+ try
+ {
+ trusted[i].checkValidity();
+ chain[chain.length-1].verify(trusted[i].getPublicKey());
+ return;
+ }
+ catch (Exception e)
+ {
+ }
+ //catch (CertificateException ce) { }
+ //catch (NoSuchAlgorithmException nsae) { }
+ //catch (NoSuchProviderException nspe) { }
+ //catch (InvalidKeyException ike) { }
+ //catch (SignatureException se) { }
+ }
+ throw new CertificateException();
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/XMLSessionContext.java b/gnu/javax/net/ssl/provider/XMLSessionContext.java
new file mode 100644
index 000000000..dcfa9d4ad
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/XMLSessionContext.java
@@ -0,0 +1,619 @@
+/* XMLSessionContext.java -- XML-encoded persistent SSL sessions.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeSet;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import gnu.javax.crypto.mac.IMac;
+import gnu.javax.crypto.mac.MacFactory;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+import gnu.javax.crypto.prng.IPBE;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.PRNGFactory;
+
+import gnu.javax.net.ssl.Base64;
+
+/**
+ * An implementation of session contexts that stores session data on the
+ * filesystem in a simple XML-encoded file.
+ */
+class XMLSessionContext extends SessionContext
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final File file;
+ private final IRandom pbekdf;
+ private final boolean compress;
+ private final SecureRandom random;
+ private boolean encoding;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ XMLSessionContext() throws IOException, SAXException
+ {
+ file = new File(Util.getSecurityProperty("jessie.SessionContext.xml.file"));
+ String password = Util.getSecurityProperty("jessie.SessionContext.xml.password");
+ compress = new Boolean(Util.getSecurityProperty("jessie.SessionContext.xml.compress")).booleanValue();
+ if (password == null)
+ {
+ password = "";
+ }
+ pbekdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA1");
+ HashMap kdfattr = new HashMap();
+ kdfattr.put(IPBE.PASSWORD, password.toCharArray());
+ // Dummy salt. This is replaced by a real salt when encoding.
+ kdfattr.put(IPBE.SALT, new byte[8]);
+ kdfattr.put(IPBE.ITERATION_COUNT, new Integer(1000));
+ pbekdf.init(kdfattr);
+ encoding = false;
+ if (file.exists())
+ {
+ decode();
+ }
+ encoding = true;
+ random = new SecureRandom ();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ synchronized boolean addSession(Session.ID sessionId, Session session)
+ {
+ boolean ret = super.addSession(sessionId, session);
+ if (ret && encoding)
+ {
+ try
+ {
+ encode();
+ }
+ catch (IOException ioe)
+ {
+ }
+ }
+ return ret;
+ }
+
+ synchronized void notifyAccess(Session session)
+ {
+ try
+ {
+ encode();
+ }
+ catch (IOException ioe)
+ {
+ }
+ }
+
+ synchronized boolean removeSession(Session.ID sessionId)
+ {
+ if (super.removeSession(sessionId))
+ {
+ try
+ {
+ encode();
+ }
+ catch (Exception x)
+ {
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void decode() throws IOException, SAXException
+ {
+ SAXParser parser = null;
+ try
+ {
+ parser = SAXParserFactory.newInstance().newSAXParser();
+ }
+ catch (Exception x)
+ {
+ throw new Error(x.toString());
+ }
+ SAXHandler handler = new SAXHandler(this, pbekdf);
+ InputStream in = null;
+ if (compress)
+ in = new GZIPInputStream(new FileInputStream(file));
+ else
+ in = new FileInputStream(file);
+ parser.parse(in, handler);
+ }
+
+ private void encode() throws IOException
+ {
+ IMode cipher = ModeFactory.getInstance("CBC", "AES", 16);
+ HashMap cipherAttr = new HashMap();
+ IMac mac = MacFactory.getInstance("HMAC-SHA1");
+ HashMap macAttr = new HashMap();
+ byte[] key = new byte[32];
+ byte[] iv = new byte[16];
+ byte[] mackey = new byte[20];
+ byte[] salt = new byte[8];
+ byte[] encryptedSecret = new byte[48];
+ cipherAttr.put(IMode.KEY_MATERIAL, key);
+ cipherAttr.put(IMode.IV, iv);
+ cipherAttr.put(IMode.STATE, new Integer(IMode.ENCRYPTION));
+ macAttr.put(IMac.MAC_KEY_MATERIAL, mackey);
+ PrintStream out = null;
+ if (compress)
+ {
+ out = new PrintStream(new GZIPOutputStream(new FileOutputStream(file)));
+ }
+ else
+ {
+ out = new PrintStream(new FileOutputStream(file));
+ }
+ out.println("<?xml version=\"1.0\"?>");
+ out.println("<!DOCTYPE sessions [");
+ out.println(" <!ELEMENT sessions (session*)>");
+ out.println(" <!ATTLIST sessions size CDATA \"0\">");
+ out.println(" <!ATTLIST sessions timeout CDATA \"86400\">");
+ out.println(" <!ELEMENT session (peer, certificates?, secret)>");
+ out.println(" <!ATTLIST session id CDATA #REQUIRED>");
+ out.println(" <!ATTLIST session protocol (SSLv3|TLSv1|TLSv1.1) #REQUIRED>");
+ out.println(" <!ATTLIST session suite CDATA #REQUIRED>");
+ out.println(" <!ATTLIST session created CDATA #REQUIRED>");
+ out.println(" <!ATTLIST session timestamp CDATA #REQUIRED>");
+ out.println(" <!ELEMENT peer (certificates?)>");
+ out.println(" <!ATTLIST peer host CDATA #REQUIRED>");
+ out.println(" <!ELEMENT certificates (#PCDATA)>");
+ out.println(" <!ATTLIST certificates type CDATA \"X.509\">");
+ out.println(" <!ELEMENT secret (#PCDATA)>");
+ out.println(" <!ATTLIST secret salt CDATA #REQUIRED>");
+ out.println("]>");
+ out.println();
+ out.print("<sessions size=\"");
+ out.print(cacheSize);
+ out.print("\" timeout=\"");
+ out.print(timeout);
+ out.println("\">");
+ for (Iterator it = sessions.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ Session.ID id = (Session.ID) entry.getKey();
+ Session session = (Session) entry.getValue();
+ if (!session.valid)
+ {
+ continue;
+ }
+ out.print("<session id=\"");
+ out.print(Base64.encode(id.getId(), 0));
+ out.print("\" suite=\"");
+ out.print(session.getCipherSuite());
+ out.print("\" protocol=\"");
+ out.print(session.getProtocol());
+ out.print("\" created=\"");
+ out.print(session.getCreationTime());
+ out.print("\" timestamp=\"");
+ out.print(session.getLastAccessedTime());
+ out.println("\">");
+ out.print("<peer host=\"");
+ out.print(session.getPeerHost());
+ out.println("\">");
+ Certificate[] certs = session.getPeerCertificates();
+ if (certs != null && certs.length > 0)
+ {
+ out.print("<certificates type=\"");
+ out.print(certs[0].getType());
+ out.println("\">");
+ for (int i = 0; i < certs.length; i++)
+ {
+ out.println("-----BEGIN CERTIFICATE-----");
+ try
+ {
+ out.print(Base64.encode(certs[i].getEncoded(), 70));
+ }
+ catch (CertificateEncodingException cee)
+ {
+ throw new IOException(cee.toString());
+ }
+ out.println("-----END CERTIFICATE-----");
+ }
+ out.println("</certificates>");
+ }
+ out.println("</peer>");
+ certs = session.getLocalCertificates();
+ if (certs != null && certs.length > 0)
+ {
+ out.print("<certificates type=\"");
+ out.print(certs[0].getType());
+ out.println("\">");
+ for (int i = 0; i < certs.length; i++)
+ {
+ out.println("-----BEGIN CERTIFICATE-----");
+ try
+ {
+ out.print(Base64.encode(certs[i].getEncoded(), 70));
+ }
+ catch (CertificateEncodingException cee)
+ {
+ throw new IOException(cee.toString());
+ }
+ out.println("-----END CERTIFICATE-----");
+ }
+ out.println("</certificates>");
+ }
+ random.nextBytes (salt);
+ pbekdf.init(Collections.singletonMap(IPBE.SALT, salt));
+ try
+ {
+ pbekdf.nextBytes(key, 0, key.length);
+ pbekdf.nextBytes(iv, 0, iv.length);
+ pbekdf.nextBytes(mackey, 0, mackey.length);
+ cipher.reset();
+ cipher.init(cipherAttr);
+ mac.init(macAttr);
+ }
+ catch (Exception ex)
+ {
+ throw new Error(ex.toString());
+ }
+ for (int i = 0; i < session.masterSecret.length; i += 16)
+ {
+ cipher.update(session.masterSecret, i, encryptedSecret, i);
+ }
+ mac.update(encryptedSecret, 0, encryptedSecret.length);
+ byte[] macValue = mac.digest();
+ out.print("<secret salt=\"");
+ out.print(Base64.encode(salt, 0));
+ out.println("\">");
+ out.print(Base64.encode(Util.concat(encryptedSecret, macValue), 70));
+ out.println("</secret>");
+ out.println("</session>");
+ }
+ out.println("</sessions>");
+ out.close();
+ }
+
+ // Inner class.
+ // -------------------------------------------------------------------------
+
+ private class SAXHandler extends DefaultHandler
+ {
+
+ // Field.
+ // -----------------------------------------------------------------------
+
+ private SessionContext context;
+ private Session current;
+ private IRandom pbekdf;
+ private StringBuffer buf;
+ private String certType;
+ private int state;
+ private IMode cipher;
+ private HashMap cipherAttr;
+ private IMac mac;
+ private HashMap macAttr;
+ private byte[] key;
+ private byte[] iv;
+ private byte[] mackey;
+
+ private static final int START = 0;
+ private static final int SESSIONS = 1;
+ private static final int SESSION = 2;
+ private static final int PEER = 3;
+ private static final int PEER_CERTS = 4;
+ private static final int CERTS = 5;
+ private static final int SECRET = 6;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ SAXHandler(SessionContext context, IRandom pbekdf)
+ {
+ this.context = context;
+ this.pbekdf = pbekdf;
+ buf = new StringBuffer();
+ state = START;
+ cipher = ModeFactory.getInstance("CBC", "AES", 16);
+ cipherAttr = new HashMap();
+ mac = MacFactory.getInstance("HMAC-SHA1");
+ macAttr = new HashMap();
+ key = new byte[32];
+ iv = new byte[16];
+ mackey = new byte[20];
+ cipherAttr.put(IMode.KEY_MATERIAL, key);
+ cipherAttr.put(IMode.IV, iv);
+ cipherAttr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
+ macAttr.put(IMac.MAC_KEY_MATERIAL, mackey);
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public void startElement(String u, String n, String qname, Attributes attr)
+ throws SAXException
+ {
+ qname = qname.toLowerCase();
+ switch (state)
+ {
+ case START:
+ if (qname.equals("sessions"))
+ {
+ try
+ {
+ timeout = Integer.parseInt(attr.getValue("timeout"));
+ cacheSize = Integer.parseInt(attr.getValue("size"));
+ if (timeout <= 0 || cacheSize < 0)
+ throw new SAXException("timeout or cache size out of range");
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new SAXException(nfe);
+ }
+ state = SESSIONS;
+ }
+ else
+ throw new SAXException("expecting sessions");
+ break;
+
+ case SESSIONS:
+ if (qname.equals("session"))
+ {
+ try
+ {
+ current = new Session(Long.parseLong(attr.getValue("created")));
+ current.enabledSuites = new ArrayList(SSLSocket.supportedSuites);
+ current.enabledProtocols = new TreeSet(SSLSocket.supportedProtocols);
+ current.context = context;
+ current.sessionId = new Session.ID(Base64.decode(attr.getValue("id")));
+ current.setLastAccessedTime(Long.parseLong(attr.getValue("timestamp")));
+ }
+ catch (Exception ex)
+ {
+ throw new SAXException(ex);
+ }
+ String prot = attr.getValue("protocol");
+ if (prot.equals("SSLv3"))
+ current.protocol = ProtocolVersion.SSL_3;
+ else if (prot.equals("TLSv1"))
+ current.protocol = ProtocolVersion.TLS_1;
+ else if (prot.equals("TLSv1.1"))
+ current.protocol = ProtocolVersion.TLS_1_1;
+ else
+ throw new SAXException("bad protocol: " + prot);
+ current.cipherSuite = CipherSuite.forName(attr.getValue("suite"));
+ state = SESSION;
+ }
+ else
+ throw new SAXException("expecting session");
+ break;
+
+ case SESSION:
+ if (qname.equals("peer"))
+ {
+ current.peerHost = attr.getValue("host");
+ state = PEER;
+ }
+ else if (qname.equals("certificates"))
+ {
+ certType = attr.getValue("type");
+ state = CERTS;
+ }
+ else if (qname.equals("secret"))
+ {
+ byte[] salt = null;
+ try
+ {
+ salt = Base64.decode(attr.getValue("salt"));
+ }
+ catch (IOException ioe)
+ {
+ throw new SAXException(ioe);
+ }
+ pbekdf.init(Collections.singletonMap(IPBE.SALT, salt));
+ state = SECRET;
+ }
+ else
+ throw new SAXException("bad element: " + qname);
+ break;
+
+ case PEER:
+ if (qname.equals("certificates"))
+ {
+ certType = attr.getValue("type");
+ state = PEER_CERTS;
+ }
+ else
+ throw new SAXException("bad element: " + qname);
+ break;
+
+ default:
+ throw new SAXException("bad element: " + qname);
+ }
+ }
+
+ public void endElement(String uri, String name, String qname)
+ throws SAXException
+ {
+ qname = qname.toLowerCase();
+ switch (state)
+ {
+ case SESSIONS:
+ if (qname.equals("sessions"))
+ state = START;
+ else
+ throw new SAXException("expecting sessions");
+ break;
+
+ case SESSION:
+ if (qname.equals("session"))
+ {
+ current.valid = true;
+ context.addSession(current.sessionId, current);
+ state = SESSIONS;
+ }
+ else
+ throw new SAXException("expecting session");
+ break;
+
+ case PEER:
+ if (qname.equals("peer"))
+ state = SESSION;
+ else
+ throw new SAXException("unexpected element: " + qname);
+ break;
+
+ case PEER_CERTS:
+ if (qname.equals("certificates"))
+ {
+ try
+ {
+ CertificateFactory fact = CertificateFactory.getInstance(certType);
+ current.peerCerts = (Certificate[])
+ fact.generateCertificates(new ByteArrayInputStream(
+ buf.toString().getBytes())).toArray(new Certificate[0]);
+ }
+ catch (Exception ex)
+ {
+ throw new SAXException(ex);
+ }
+ current.peerVerified = true;
+ state = PEER;
+ }
+ else
+ throw new SAXException("unexpected element: " + qname);
+ break;
+
+ case CERTS:
+ if (qname.equals("certificates"))
+ {
+ try
+ {
+ CertificateFactory fact = CertificateFactory.getInstance(certType);
+ current.localCerts = (Certificate[])
+ fact.generateCertificates(new ByteArrayInputStream(
+ buf.toString().getBytes())).toArray(new Certificate[0]);
+ }
+ catch (Exception ex)
+ {
+ throw new SAXException(ex);
+ }
+ state = SESSION;
+ }
+ else
+ throw new SAXException("unexpected element: " + qname);
+ break;
+
+ case SECRET:
+ if (qname.equals("secret"))
+ {
+ byte[] encrypted = null;
+ try
+ {
+ encrypted = Base64.decode(buf.toString());
+ if (encrypted.length != 68)
+ throw new IOException("encrypted secret not 68 bytes long");
+ pbekdf.nextBytes(key, 0, key.length);
+ pbekdf.nextBytes(iv, 0, iv.length);
+ pbekdf.nextBytes(mackey, 0, mackey.length);
+ cipher.reset();
+ cipher.init(cipherAttr);
+ mac.init(macAttr);
+ }
+ catch (Exception ex)
+ {
+ throw new SAXException(ex);
+ }
+ mac.update(encrypted, 0, 48);
+ byte[] macValue = mac.digest();
+ for (int i = 0; i < macValue.length; i++)
+ {
+ if (macValue[i] != encrypted[48+i])
+ throw new SAXException("MAC mismatch");
+ }
+ current.masterSecret = new byte[48];
+ for (int i = 0; i < current.masterSecret.length; i += 16)
+ {
+ cipher.update(encrypted, i, current.masterSecret, i);
+ }
+ state = SESSION;
+ }
+ else
+ throw new SAXException("unexpected element: " + qname);
+ break;
+
+ default:
+ throw new SAXException("unexpected element: " + qname);
+ }
+ buf.setLength(0);
+ }
+
+ public void characters(char[] ch, int off, int len) throws SAXException
+ {
+ if (state != CERTS && state != PEER_CERTS && state != SECRET)
+ {
+ throw new SAXException("illegal character data");
+ }
+ buf.append(ch, off, len);
+ }
+ }
+}
diff --git a/gnu/javax/security/auth/Password.java b/gnu/javax/security/auth/Password.java
new file mode 100644
index 000000000..7284b7d68
--- /dev/null
+++ b/gnu/javax/security/auth/Password.java
@@ -0,0 +1,285 @@
+/* Password.java -- opaque wrapper around a password.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.security.auth;
+
+import gnu.java.security.util.ExpirableObject;
+
+import javax.security.auth.DestroyFailedException;
+
+/**
+ * Immutible, though destroyable, password class.
+ *
+ * <p>Extends {@link ExpirableObject}, implementing {@link doDestroy()}
+ * in which encapsulated {@link char[]}, and {@link byte[]} password fields
+ * are cleared (elements set to zero) in order to thwart memory heap
+ * snooping.
+ */
+public final class Password extends ExpirableObject
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * Password stored in {@link char[]} format.
+ */
+ private final char[] password;
+
+ /**
+ * Password stored in {@link byte[]} format.
+ */
+ private final byte[] bPassword;
+
+ /**
+ * Indicates whether this Password object's {@link doDestroy()} method has
+ * been called. See also, {@link ExpirableObject#Destroy()}.
+ */
+ private boolean mIsDestroyed = false;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Create a new expirable Password object that will expire after the
+ * default timeout {@link ExpirableObject#DEFAULT_TIMEOUT}.
+ *
+ * @param password The character array password to associate with this
+ * Password object.
+ */
+ public Password (char[] password)
+ {
+ this (password, 0, password.length, DEFAULT_TIMEOUT);
+ }
+
+ /**
+ * Create a new expirable Password object that will expire after the
+ * timeout denoted by constructor parameter, <i>delay</i>.
+ *
+ * @param password The character array password to associate with this
+ * Password object.
+ * @param delay The number of miliseconds before this Password object
+ * will be automatically destroyed.
+ */
+ public Password (char[] password, long delay)
+ {
+ this (password, 0, password.length, delay);
+ }
+
+ /**
+ * Create a new expirable Password object that will expire after the
+ * default timeout {@link ExpirableObject#DEFAULT_TIMEOUT}.
+ *
+ * @param password The character array password to associate with this
+ * Password object.
+ * @param offset The <i>password</i> character array parameter element
+ * marking the beginning of the contained password string.
+ * @param length The number of characters, beginning at <i>offset</i>,
+ * to be copied into this object's {@link password} field.
+ */
+ public Password (char[] password, int offset, int length)
+ {
+ this (password, offset, length, DEFAULT_TIMEOUT);
+ }
+
+ /**
+ * Create a new expirable Password object that will expire after the
+ * timeout denoted by constructor parameter, <i>delay</i>.
+ *
+ * @param password The character array password to associate with this
+ * Password object.
+ * @param offset The <i>password</i> character array parameter element
+ * marking the beginning of the contained password string.
+ * @param length The number of characters, beginning at <i>offset</i>,
+ * to be copied into this object's {@link password} field.
+ * @param delay The number of miliseconds before this Password object
+ * will be automatically destroyed.
+ */
+ public Password (char[] password, int offset, int length, long delay)
+ {
+ super (delay);
+
+ if (offset < 0 || length < 0 || offset + length > password.length)
+ throw new ArrayIndexOutOfBoundsException ("off=" + offset + " length=" +
+ length + " array.length=" +
+ password.length);
+
+ int i, j;
+ this.password = new char[length];
+ bPassword = new byte[length];
+
+ for(i = 0, j = offset; i < length; i++, j++)
+ {
+ this.password[i] = (char) password[j];
+ // XXX this should use character encodings, other than ASCII.
+ bPassword[i] = (byte) (password[j] & 0x7F);
+ }
+ }
+
+ /**
+ * Create a new expirable Password object that will expire after the
+ * default timeout {@link ExpirableObject#DEFAULT_TIMEOUT}.
+ *
+ * @param password The byte array password to associate with this
+ * Password object.
+ */
+ public Password (byte[] password)
+ {
+ this (password, 0, password.length, DEFAULT_TIMEOUT);
+ }
+
+ /**
+ * Create a new expirable Password object that will expire after the
+ * timeout denoted by constructor parameter, <i>delay</i>.
+ *
+ * @param password The byte array password to associate with this
+ * Password object.
+ * @param delay The number of miliseconds before this Password object
+ * will be automatically destroyed.
+ */
+ public Password (byte[] password, long delay)
+ {
+ this (password, 0, password.length, delay);
+ }
+
+ /**
+ * Create a new expirable Password object that will expire after the
+ * default timeout {@link ExpirableObject#DEFAULT_TIMEOUT}.
+ *
+ * @param password The byte array password to associate with this
+ * Password object.
+ * @param offset The <i>password</i> byte array parameter element
+ * marking the beginning of the contained password string.
+ * @param length The number of bytes, beginning at <i>offset</i>,
+ * to be copied into this object's {@link password} field.
+ */
+ public Password (byte[] password, int offset, int length)
+ {
+ this (password, offset, length, DEFAULT_TIMEOUT);
+ }
+
+ /**
+ * Create a new expirable Password object that will expire after the
+ * timeout denoted by constructor parameter, <i>delay</i>.
+ *
+ * @param password The byte array password to associate with this
+ * Password object.
+ * @param offset The <i>password</i> byte array parameter element
+ * marking the beginning of the contained password string.
+ * @param length The number of bytes, beginning at <i>offset</i>,
+ * to be copied into this object's {@link bPassword} field.
+ * @param delay The number of miliseconds before this Password object
+ * will be automatically destroyed.
+ */
+ public Password (byte[] password, int offset, int length, long delay)
+ {
+ super (delay);
+
+ if (offset < 0 || length < 0 || offset + length > password.length)
+ throw new ArrayIndexOutOfBoundsException ("off=" + offset + " length=" +
+ length + " array.length=" +
+ password.length);
+
+ int i, j;
+ this.password = new char[length];
+ bPassword = new byte[length];
+
+ for (i = 0, j = offset; i < length; i++, j++)
+ {
+ this.password[i] = (char) password[j];
+ bPassword[i] = password[j];
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns a reference to the {@link char[]} password storage field,
+ * {@link password}.
+ */
+ public synchronized char[] getPassword()
+ {
+ if (mIsDestroyed)
+ throw new IllegalStateException ("Attempted destroyed password access.");
+
+ return password;
+ }
+
+ /**
+ * Returns a reference to the {@link byte[]} password storage field,
+ * {@link bPassword}.
+ */
+ public synchronized byte[] getBytes()
+ {
+ if (mIsDestroyed)
+ throw new IllegalStateException ("Attempted destroyed password access.");
+
+ return bPassword;
+ }
+
+ /**
+ * Sets password field char[], and byte[] array elements to zero.
+ * This method implements base class {@link ExpirableObject} abstract
+ * method, {@link ExpirableObject#doDestroy()}. See also,
+ * {@link ExpirableObject#destroy()}.
+ */
+ protected synchronized void doDestroy()
+ {
+ if (isDestroyed())
+ return;
+ else
+ {
+ for (int i = 0; i < password.length; i++)
+ password[i] = 0;
+ for (int i = 0; i < bPassword.length; i++)
+ bPassword[i] = 0;
+ mIsDestroyed = true;
+ }
+ }
+
+ /**
+ * Returns true, or false relative to whether, or not this object's
+ * {@link doDestroy()} method has been called. See also,
+ * {@ExpirableObject#destroy()}.
+ */
+ public synchronized boolean isDestroyed()
+ {
+ return (mIsDestroyed);
+ }
+}
diff --git a/gnu/javax/security/auth/callback/AWTCallbackHandler.java b/gnu/javax/security/auth/callback/AWTCallbackHandler.java
new file mode 100644
index 000000000..539c4a17e
--- /dev/null
+++ b/gnu/javax/security/auth/callback/AWTCallbackHandler.java
@@ -0,0 +1,452 @@
+/* AWTCallbackHandler.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.security.auth.callback;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Dialog;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.TextField;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+
+import java.util.Locale;
+
+import javax.security.auth.callback.ChoiceCallback;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.LanguageCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.TextOutputCallback;
+
+public class AWTCallbackHandler extends AbstractCallbackHandler
+ implements ActionListener, WindowListener
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ protected String actionCommand;
+
+ private static final String ACTION_CANCEL = "CANCEL";
+ private static final String ACTION_NO = "NO";
+ private static final String ACTION_NONE = "NONE";
+ private static final String ACTION_OK = "OK";
+ private static final String ACTION_YES = "YES";
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public AWTCallbackHandler()
+ {
+ super ("AWT");
+ actionCommand = ACTION_NONE;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ protected synchronized void handleChoice(ChoiceCallback c)
+ {
+ Frame ownerFrame = new Frame();
+ Dialog dialog = new Dialog(ownerFrame);
+ String[] choices = c.getChoices();
+ dialog.setTitle(c.getPrompt());
+ Label label = new Label(c.getPrompt());
+ List list = new List(Math.min(5, choices.length),
+ c.allowMultipleSelections());
+ Panel buttons = new Panel();
+ Button ok = new Button(messages.getString("callback.ok"));
+ ok.setActionCommand(ACTION_OK);
+ ok.addActionListener(this);
+ Button cancel = new Button(messages.getString("callback.cancel"));
+ cancel.setActionCommand(ACTION_CANCEL);
+ cancel.addActionListener(this);
+ for (int i = 0; i < choices.length; i++)
+ {
+ list.add(choices[i]);
+ }
+ if (c.getDefaultChoice() >= 0 && c.getDefaultChoice() < choices.length)
+ {
+ list.select(c.getDefaultChoice());
+ }
+ dialog.setLayout(new BorderLayout());
+ dialog.add(label, BorderLayout.NORTH);
+ dialog.add(list, BorderLayout.CENTER);
+ buttons.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ buttons.add(cancel);
+ buttons.add(ok);
+ dialog.add(buttons, BorderLayout.SOUTH);
+ dialog.pack();
+ dialog.show();
+ try { wait(); }
+ catch (InterruptedException ie) { }
+ if (actionCommand.equals(ACTION_OK))
+ {
+ if (c.allowMultipleSelections())
+ {
+ c.setSelectedIndexes(list.getSelectedIndexes());
+ }
+ else
+ {
+ c.setSelectedIndex(list.getSelectedIndex());
+ }
+ }
+ dialog.dispose();
+ ownerFrame.dispose();
+ }
+
+ protected synchronized void handleConfirmation(ConfirmationCallback c)
+ {
+ Frame ownerFrame = new Frame();
+ Dialog dialog = new Dialog(ownerFrame);
+ switch (c.getMessageType())
+ {
+ case ConfirmationCallback.ERROR:
+ dialog.setTitle(messages.getString("callback.error"));
+ break;
+ case ConfirmationCallback.INFORMATION:
+ dialog.setTitle(messages.getString("callback.information"));
+ break;
+ case ConfirmationCallback.WARNING:
+ dialog.setTitle(messages.getString("callback.warning"));
+ break;
+ default:
+ dialog.setTitle("");
+ }
+ dialog.setLayout(new GridLayout(2, 1));
+ dialog.add(new Label(c.getPrompt()));
+ Panel buttons = new Panel();
+ buttons.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ dialog.add(buttons);
+ String[] choices = null;
+ int[] values = null;
+ switch (c.getOptionType())
+ {
+ case ConfirmationCallback.OK_CANCEL_OPTION:
+ choices = new String[] {
+ messages.getString("callback.cancel"),
+ messages.getString("callback.ok")
+ };
+ values = new int[] {
+ ConfirmationCallback.CANCEL, ConfirmationCallback.OK
+ };
+ break;
+ case ConfirmationCallback.YES_NO_CANCEL_OPTION:
+ choices = new String[] {
+ messages.getString("callback.cancel"),
+ messages.getString("callback.no"),
+ messages.getString("callback.yes")
+ };
+ values = new int[] {
+ ConfirmationCallback.CANCEL, ConfirmationCallback.NO,
+ ConfirmationCallback.YES
+ };
+ break;
+ case ConfirmationCallback.YES_NO_OPTION:
+ choices = new String[] {
+ messages.getString("callback.no"),
+ messages.getString("callback.yes")
+ };
+ values = new int[] {
+ ConfirmationCallback.NO, ConfirmationCallback.YES
+ };
+ break;
+ case ConfirmationCallback.UNSPECIFIED_OPTION:
+ choices = c.getOptions();
+ values = new int[choices.length];
+ for (int i = 0; i < values.length; i++)
+ values[i] = i;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ for (int i = 0; i < choices.length; i++)
+ {
+ Button b = new Button(choices[i]);
+ b.setActionCommand(choices[i]);
+ b.addActionListener(this);
+ buttons.add(b);
+ }
+ dialog.pack();
+ dialog.show();
+ try { wait(); }
+ catch (InterruptedException ie) { }
+ for (int i = 0; i < choices.length; i++)
+ {
+ if (actionCommand.equals(choices[i]))
+ {
+ c.setSelectedIndex(values[i]);
+ break;
+ }
+ }
+ dialog.dispose();
+ ownerFrame.dispose();
+ }
+
+ protected synchronized void handleLanguage(LanguageCallback c)
+ {
+ Locale[] locales = Locale.getAvailableLocales();
+ String[] languages = new String[locales.length];
+ Locale def = Locale.getDefault();
+ int defind = 0;
+ for (int i = 0; i < locales.length; i++)
+ {
+ StringBuffer lang =
+ new StringBuffer(locales[i].getDisplayLanguage(locales[i]));
+ String country = locales[i].getDisplayCountry(locales[i]);
+ String variant = locales[i].getDisplayVariant(locales[i]);
+ if (country.length() > 0 && variant.length() > 0)
+ {
+ lang.append(" (");
+ lang.append(country);
+ lang.append(", ");
+ lang.append(variant);
+ lang.append(")");
+ }
+ else if (country.length() > 0)
+ {
+ lang.append(" (");
+ lang.append(country);
+ lang.append(")");
+ }
+ else if (variant.length() > 0)
+ {
+ lang.append(" (");
+ lang.append(variant);
+ lang.append(")");
+ }
+ languages[i] = lang.toString();
+ if (locales[i].equals(def))
+ defind = i;
+ }
+ ChoiceCallback c2 =
+ new ChoiceCallback(messages.getString("callback.language"), languages,
+ defind, false);
+ handleChoice(c2);
+ c.setLocale(def);
+ if (c2.getSelectedIndexes() != null && c2.getSelectedIndexes().length > 0)
+ {
+ int index = c2.getSelectedIndexes()[0];
+ if (index >= 0 && index < locales.length)
+ c.setLocale(locales[index]);
+ }
+ }
+
+ protected synchronized void handleName(NameCallback c)
+ {
+ Frame ownerFrame = new Frame();
+ Dialog dialog = new Dialog(ownerFrame);
+ dialog.setTitle(c.getPrompt());
+ dialog.setLayout(new GridLayout(3, 1));
+ Label label = new Label(c.getPrompt());
+ TextField input = new TextField();
+ if (c.getDefaultName() != null)
+ {
+ input.setText(c.getDefaultName());
+ }
+ Panel buttons = new Panel();
+ Button ok = new Button(messages.getString("callback.ok"));
+ ok.setActionCommand(ACTION_OK);
+ ok.addActionListener(this);
+ Button cancel = new Button(messages.getString("callback.cancel"));
+ cancel.setActionCommand(ACTION_CANCEL);
+ cancel.addActionListener(this);
+ dialog.add(label);
+ dialog.add(input);
+ buttons.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ buttons.add(ok);
+ buttons.add(cancel);
+ dialog.add(buttons);
+ dialog.pack();
+ dialog.show();
+ try { wait(); }
+ catch (InterruptedException ie) { }
+ if (actionCommand.equals(ACTION_OK))
+ {
+ c.setName(input.getText());
+ }
+ dialog.dispose();
+ ownerFrame.dispose();
+ }
+
+ protected synchronized void handlePassword(PasswordCallback c)
+ {
+ Frame ownerFrame = new Frame();
+ Dialog dialog = new Dialog(ownerFrame);
+ dialog.setTitle(c.getPrompt());
+ dialog.setLayout(new GridLayout(3, 1));
+ Label label = new Label(c.getPrompt());
+ TextField input = new TextField();
+ if (!c.isEchoOn())
+ {
+ input.setEchoChar('*');
+ }
+ Panel buttons = new Panel();
+ Button ok = new Button(messages.getString("callback.ok"));
+ ok.setActionCommand(ACTION_OK);
+ ok.addActionListener(this);
+ Button cancel = new Button(messages.getString("callback.cancel"));
+ cancel.setActionCommand(ACTION_CANCEL);
+ cancel.addActionListener(this);
+ dialog.add(label);
+ dialog.add(input);
+ buttons.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ buttons.add(ok);
+ buttons.add(cancel);
+ dialog.add(buttons);
+ dialog.pack();
+ dialog.show();
+ try { wait(); }
+ catch (InterruptedException ie) { }
+ if (actionCommand.equals(ACTION_OK))
+ {
+ c.setPassword(input.getText().toCharArray());
+ }
+ dialog.dispose();
+ ownerFrame.dispose();
+ }
+
+ protected synchronized void handleTextInput(TextInputCallback c)
+ {
+ Frame ownerFrame = new Frame();
+ Dialog dialog = new Dialog(ownerFrame);
+ dialog.setTitle(c.getPrompt());
+ dialog.setLayout(new BorderLayout());
+ Label label = new Label(c.getPrompt());
+ TextArea text = new TextArea(10, 40);
+ if (c.getDefaultText() != null)
+ {
+ text.setText(c.getDefaultText());
+ }
+ Panel buttons = new Panel();
+ Button ok = new Button(messages.getString("callback.ok"));
+ ok.setActionCommand(ACTION_OK);
+ ok.addActionListener(this);
+ Button cancel = new Button(messages.getString("callback.cancel"));
+ cancel.setActionCommand(ACTION_CANCEL);
+ cancel.addActionListener(this);
+ dialog.add(label, BorderLayout.NORTH);
+ dialog.add(text, BorderLayout.CENTER);
+ buttons.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ buttons.add(ok);
+ buttons.add(cancel);
+ dialog.add(buttons, BorderLayout.SOUTH);
+ dialog.pack();
+ dialog.show();
+ try { wait(); }
+ catch (InterruptedException ie) { }
+ if (actionCommand.equals(ACTION_OK))
+ {
+ c.setText(text.getText());
+ }
+ dialog.dispose();
+ ownerFrame.dispose();
+ }
+
+ protected synchronized void handleTextOutput(TextOutputCallback c)
+ {
+ Frame ownerFrame = new Frame();
+ Dialog dialog = new Dialog(ownerFrame);
+ dialog.setLayout(new GridLayout(2, 1));
+ switch (c.getMessageType() /*c.getStyle()*/)
+ {
+ case ConfirmationCallback.ERROR:
+ dialog.setTitle(messages.getString("callback.error"));
+ break;
+ case ConfirmationCallback.INFORMATION:
+ dialog.setTitle(messages.getString("callback.information"));
+ break;
+ case ConfirmationCallback.WARNING:
+ dialog.setTitle(messages.getString("callback.warning"));
+ break;
+ default:
+ dialog.setTitle("");
+ }
+ Label label = new Label(c.getMessage());
+ Panel buttons = new Panel();
+ Button ok = new Button(messages.getString("callback.ok"));
+ buttons.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ buttons.add(ok);
+ ok.addActionListener(this);
+ dialog.add(label);
+ dialog.add(buttons);
+ dialog.pack();
+ dialog.show();
+ try { wait(); }
+ catch (InterruptedException ie) { }
+ dialog.dispose();
+ ownerFrame.dispose();
+ }
+
+ // ActionListener interface implementation.
+ // -------------------------------------------------------------------------
+
+ public synchronized void actionPerformed(ActionEvent ae)
+ {
+ actionCommand = ae.getActionCommand();
+ notifyAll();
+ }
+
+ // WindowListener interface implementation.
+ // -------------------------------------------------------------------------
+
+ public synchronized void windowClosing(WindowEvent we)
+ {
+ actionCommand = ACTION_NONE;
+ notifyAll();
+ }
+
+ public void windowOpened(WindowEvent we) { }
+ public void windowClosed(WindowEvent we) { }
+ public void windowIconified(WindowEvent we) { }
+ public void windowDeiconified(WindowEvent we) { }
+ public void windowActivated(WindowEvent we) { }
+ public void windowDeactivated(WindowEvent we) { }
+}
diff --git a/gnu/javax/security/auth/callback/AbstractCallbackHandler.java b/gnu/javax/security/auth/callback/AbstractCallbackHandler.java
new file mode 100644
index 000000000..eeedf2605
--- /dev/null
+++ b/gnu/javax/security/auth/callback/AbstractCallbackHandler.java
@@ -0,0 +1,258 @@
+/* AbstractCallbackHandler.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.security.auth.callback;
+
+import gnu.java.security.Engine;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.ChoiceCallback;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.LanguageCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+public abstract class AbstractCallbackHandler implements CallbackHandler
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private static final String SERVICE = "CallbackHandler";
+
+ protected final ResourceBundle messages;
+
+ private final String name;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ protected AbstractCallbackHandler (final String name)
+ {
+ super();
+ messages = PropertyResourceBundle.getBundle("gnu/javax/security/auth/callback/MessagesBundle");
+ this.name = name;
+ }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ public static CallbackHandler getInstance(String type)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] p = Security.getProviders();
+ for (int i = 0; i < p.length; i++)
+ {
+ try
+ {
+ return getInstance(type, p[i]);
+ }
+ catch (NoSuchAlgorithmException ignored)
+ {
+ }
+ }
+ throw new NoSuchAlgorithmException(type);
+ }
+
+ public static CallbackHandler getInstance(String type, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ Provider p = Security.getProvider(provider);
+ if (p == null)
+ {
+ throw new NoSuchProviderException(provider);
+ }
+ return getInstance(type, p);
+ }
+
+ public static CallbackHandler getInstance(String type, Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ return (CallbackHandler) Engine.getInstance(SERVICE, type, provider);
+ }
+ catch (InvocationTargetException ite)
+ {
+ Throwable cause = ite.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ NoSuchAlgorithmException nsae = new NoSuchAlgorithmException(type);
+ if (cause != null)
+ nsae.initCause (cause);
+ throw nsae;
+ }
+ catch (ClassCastException cce)
+ {
+ NoSuchAlgorithmException nsae = new NoSuchAlgorithmException(type);
+ nsae.initCause (cce);
+ throw nsae;
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException
+ {
+ if (callbacks == null)
+ throw new NullPointerException();
+ for (int i = 0; i < callbacks.length; i++)
+ {
+ if (callbacks[i] == null)
+ continue;
+ if (callbacks[i] instanceof ChoiceCallback)
+ handleChoice((ChoiceCallback) callbacks[i]);
+ else if (callbacks[i] instanceof ConfirmationCallback)
+ handleConfirmation((ConfirmationCallback) callbacks[i]);
+ else if (callbacks[i] instanceof LanguageCallback)
+ handleLanguage((LanguageCallback) callbacks[i]);
+ else if (callbacks[i] instanceof NameCallback)
+ handleName((NameCallback) callbacks[i]);
+ else if (callbacks[i] instanceof PasswordCallback)
+ handlePassword((PasswordCallback) callbacks[i]);
+ else if (callbacks[i] instanceof TextInputCallback)
+ handleTextInput((TextInputCallback) callbacks[i]);
+ else if (callbacks[i] instanceof TextOutputCallback)
+ handleTextOutput((TextOutputCallback) callbacks[i]);
+ else
+ handleOther(callbacks[i]);
+ }
+ }
+
+ public final String getName ()
+ {
+ return name;
+ }
+
+ // Abstract methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Handles a {@link ChoiceCallback}.
+ *
+ * @param callback The choice callback.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected abstract void handleChoice(ChoiceCallback callback)
+ throws IOException;
+
+ /**
+ * Handles a {@link ConfirmationCallback}.
+ *
+ * @param callback The confirmation callback.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected abstract void handleConfirmation(ConfirmationCallback callback)
+ throws IOException;
+
+ /**
+ * Handles a {@link LanguageCallback}.
+ *
+ * @param callback The language callback.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected abstract void handleLanguage(LanguageCallback callback)
+ throws IOException;
+
+ /**
+ * Handles a {@link NameCallback}.
+ *
+ * @param callback The name callback.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected abstract void handleName(NameCallback callback)
+ throws IOException;
+
+ /**
+ * Handles a {@link PasswordCallback}.
+ *
+ * @param callback The password callback.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected abstract void handlePassword(PasswordCallback callback)
+ throws IOException;
+
+ /**
+ * Handles a {@link TextInputCallback}.
+ *
+ * @param callback The text input callback.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected abstract void handleTextInput(TextInputCallback callback)
+ throws IOException;
+
+ /**
+ * Handles a {@link TextOutputCallback}.
+ *
+ * @param callback The text output callback.
+ * @throws IOException If an I/O error occurs.
+ */
+ protected abstract void handleTextOutput(TextOutputCallback callback)
+ throws IOException;
+
+ /**
+ * Handles an unknown callback. The default implementation simply throws
+ * an {@link UnsupportedCallbackException}.
+ *
+ * @param callback The callback to handle.
+ * @throws IOException If an I/O error occurs.
+ * @throws UnsupportedCallbackException If the specified callback is not
+ * supported.
+ */
+ protected void handleOther(Callback callback)
+ throws IOException, UnsupportedCallbackException
+ {
+ throw new UnsupportedCallbackException(callback);
+ }
+}
diff --git a/gnu/javax/security/auth/callback/ConsoleCallbackHandler.java b/gnu/javax/security/auth/callback/ConsoleCallbackHandler.java
new file mode 100644
index 000000000..4ce22cb30
--- /dev/null
+++ b/gnu/javax/security/auth/callback/ConsoleCallbackHandler.java
@@ -0,0 +1,289 @@
+/* ConsoleCallbackHandler.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.security.auth.callback;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+
+import javax.security.auth.callback.ChoiceCallback;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.LanguageCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.TextOutputCallback;
+
+/**
+ * An implementation of {@link CallbackHandler} that reads and writes
+ * information to and from <code>System.in</code> and <code>System.out</code>.
+ */
+public class ConsoleCallbackHandler extends AbstractCallbackHandler
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final PrintStream out;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public ConsoleCallbackHandler()
+ {
+ this (System.out);
+ }
+
+ public ConsoleCallbackHandler (final PrintStream out)
+ {
+ super ("CONSOLE");
+ this.out = out;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ protected void handleChoice(ChoiceCallback c) throws IOException
+ {
+ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ out.println(c.getPrompt());
+ out.print('(');
+ String[] choices = c.getChoices();
+ for (int i = 0; i < choices.length; i++)
+ {
+ out.print(choices[i]);
+ if (i != choices.length - 1)
+ out.print(", ");
+ }
+ out.print(") ");
+ if (c.getDefaultChoice() >= 0 && c.getDefaultChoice() < choices.length)
+ {
+ out.print('[');
+ out.print(choices[c.getDefaultChoice()]);
+ out.print("] ");
+ }
+ String reply = in.readLine();
+ if (reply == null || reply.length() == 0)
+ {
+ c.setSelectedIndex(c.getDefaultChoice());
+ return;
+ }
+ if (!c.allowMultipleSelections())
+ {
+ for (int i = 0; i < choices.length; i++)
+ {
+ if (reply.trim().equals(choices[i]))
+ {
+ c.setSelectedIndex(i);
+ return;
+ }
+ }
+ c.setSelectedIndex(c.getDefaultChoice());
+ }
+ else
+ {
+ TreeSet indices = new TreeSet();
+ StringTokenizer tok = new StringTokenizer(reply, ",");
+ String[] replies = new String[tok.countTokens()];
+ int idx = 0;
+ while (tok.hasMoreTokens())
+ {
+ replies[idx++] = tok.nextToken().trim();
+ }
+ for (int i = 0; i < choices.length; i++)
+ for (int j = 0; j < replies.length; i++)
+ {
+ if (choices[i].equals(replies[j]))
+ {
+ indices.add(new Integer(i));
+ }
+ }
+ if (indices.size() == 0)
+ c.setSelectedIndex(c.getDefaultChoice());
+ else
+ {
+ int[] ii = new int[indices.size()];
+ int i = 0;
+ for (Iterator it = indices.iterator(); it.hasNext(); )
+ ii[i++] = ((Integer) it.next()).intValue();
+ c.setSelectedIndexes(ii);
+ }
+ }
+ }
+
+ protected void handleConfirmation(ConfirmationCallback c) throws IOException
+ {
+ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ if (c.getPrompt() != null)
+ out.println(c.getPrompt());
+ String[] choices = null;
+ int[] values = null;
+ switch (c.getOptionType())
+ {
+ case ConfirmationCallback.OK_CANCEL_OPTION:
+ out.print(messages.getString("callback.okCancel"));
+ choices = new String[] {
+ messages.getString("callback.ok"),
+ messages.getString("callback.cancel"),
+ messages.getString("callback.shortOk"),
+ messages.getString("callback.shortCancel")
+ };
+ values = new int[] {
+ ConfirmationCallback.OK, ConfirmationCallback.CANCEL,
+ ConfirmationCallback.OK, ConfirmationCallback.CANCEL
+ };
+ break;
+ case ConfirmationCallback.YES_NO_CANCEL_OPTION:
+ out.print(messages.getString("callback.yesNoCancel"));
+ choices = new String[] {
+ messages.getString("callback.yes"),
+ messages.getString("callback.no"),
+ messages.getString("callback.cancel"),
+ messages.getString("callback.shortYes"),
+ messages.getString("callback.shortNo"),
+ messages.getString("callback.shortCancel")
+ };
+ values = new int[] {
+ ConfirmationCallback.YES, ConfirmationCallback.NO,
+ ConfirmationCallback.CANCEL, ConfirmationCallback.YES,
+ ConfirmationCallback.NO, ConfirmationCallback.CANCEL
+ };
+ break;
+ case ConfirmationCallback.YES_NO_OPTION:
+ out.print(messages.getString("callback.yesNo"));
+ choices = new String[] {
+ messages.getString("callback.yes"),
+ messages.getString("callback.no"),
+ messages.getString("callback.shortYes"),
+ messages.getString("callback.shortNo")
+ };
+ values = new int[] {
+ ConfirmationCallback.YES, ConfirmationCallback.NO,
+ ConfirmationCallback.YES, ConfirmationCallback.NO
+ };
+ break;
+ case ConfirmationCallback.UNSPECIFIED_OPTION:
+ choices = c.getOptions();
+ values = new int[choices.length];
+ for (int i = 0; i < values.length; i++)
+ values[i] = i;
+ out.print('(');
+ for (int i = 0; i < choices.length; i++)
+ {
+ out.print(choices[i]);
+ if (i != choices.length - 1)
+ out.print(", ");
+ }
+ out.print(") [");
+ out.print(choices[c.getDefaultOption()]);
+ out.print("] ");
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ String reply = in.readLine();
+ if (reply == null)
+ {
+ c.setSelectedIndex(c.getDefaultOption());
+ return;
+ }
+ reply = reply.trim();
+ for (int i = 0; i < choices.length; i++)
+ if (reply.equalsIgnoreCase(choices[i]))
+ {
+ c.setSelectedIndex(values[i]);
+ return;
+ }
+ c.setSelectedIndex(c.getDefaultOption());
+ }
+
+ protected void handleLanguage(LanguageCallback c) throws IOException
+ {
+ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ out.println(messages.getString("callback.language"));
+ String reply = null;
+ reply = in.readLine();
+ if (reply == null)
+ {
+ c.setLocale(Locale.getDefault());
+ }
+ else
+ {
+ c.setLocale(new Locale(reply.trim()));
+ }
+ }
+
+ protected void handleName(NameCallback c) throws IOException
+ {
+ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ out.print(c.getPrompt());
+ String name = in.readLine();
+ if (name != null)
+ c.setName(name.trim());
+ }
+
+ protected void handlePassword(PasswordCallback c) throws IOException
+ {
+ out.print(c.getPrompt());
+ BufferedReader in =
+ new BufferedReader(new InputStreamReader(System.in));
+ String pass = in.readLine();
+ c.setPassword(pass.toCharArray());
+ }
+
+ protected void handleTextInput(TextInputCallback c) throws IOException
+ {
+ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ out.print(c.getPrompt());
+ String text = in.readLine();
+ if (text != null)
+ c.setText(text);
+ }
+
+ protected void handleTextOutput(TextOutputCallback c)
+ {
+ out.print(c.getMessage());
+ }
+}
diff --git a/gnu/javax/security/auth/callback/DefaultCallbackHandler.java b/gnu/javax/security/auth/callback/DefaultCallbackHandler.java
new file mode 100644
index 000000000..fc48782fe
--- /dev/null
+++ b/gnu/javax/security/auth/callback/DefaultCallbackHandler.java
@@ -0,0 +1,109 @@
+/* DefaultCallbackHandler.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.security.auth.callback;
+
+import java.util.Locale;
+
+import javax.security.auth.callback.ChoiceCallback;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.LanguageCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.TextOutputCallback;
+
+/**
+ * This trivial implementation of {@link CallbackHandler} sets its
+ * {@link Callback} arguments to default values, with no user interaction.
+ */
+public class DefaultCallbackHandler extends AbstractCallbackHandler
+{
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public DefaultCallbackHandler()
+ {
+ super("DEFAULT");
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ protected void handleChoice(ChoiceCallback c)
+ {
+ c.setSelectedIndex(c.getDefaultChoice());
+ }
+
+ protected void handleConfirmation(ConfirmationCallback c)
+ {
+ if (c.getOptionType() == ConfirmationCallback.YES_NO_OPTION)
+ c.setSelectedIndex(ConfirmationCallback.NO);
+ else if (c.getOptionType() == ConfirmationCallback.YES_NO_CANCEL_OPTION)
+ c.setSelectedIndex(ConfirmationCallback.NO);
+ else if (c.getOptionType() == ConfirmationCallback.OK_CANCEL_OPTION)
+ c.setSelectedIndex(ConfirmationCallback.OK);
+ else
+ c.setSelectedIndex(c.getDefaultOption());
+ }
+
+ protected void handleLanguage(LanguageCallback c)
+ {
+ c.setLocale(Locale.getDefault());
+ }
+
+ protected void handleName(NameCallback c)
+ {
+ c.setName(System.getProperty("user.name"));
+ }
+
+ protected void handlePassword(PasswordCallback c)
+ {
+ c.setPassword(new char[0]);
+ }
+
+ protected void handleTextInput(TextInputCallback c)
+ {
+ c.setText("");
+ }
+
+ protected void handleTextOutput(TextOutputCallback c)
+ {
+ }
+}
diff --git a/gnu/javax/security/auth/callback/GnuCallbacks.java b/gnu/javax/security/auth/callback/GnuCallbacks.java
new file mode 100644
index 000000000..9fd72f926
--- /dev/null
+++ b/gnu/javax/security/auth/callback/GnuCallbacks.java
@@ -0,0 +1,64 @@
+/* GnuCallbacks.java -- Provider for callback implementations.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.security.auth.callback;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+
+public final class GnuCallbacks extends Provider
+{
+ public GnuCallbacks()
+ {
+ super("GNU-CALLBACKS", 2.1, "Implementations of various callback handlers.");
+
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ put("CallbackHandler.Default", DefaultCallbackHandler.class.getName());
+ put("CallbackHandler.Console", ConsoleCallbackHandler.class.getName());
+ put("CallbackHandler.AWT", AWTCallbackHandler.class.getName());
+ put("CallbackHandler.Swing", SwingCallbackHandler.class.getName());
+
+ return null;
+ }
+ });
+ }
+}
diff --git a/gnu/javax/security/auth/callback/SwingCallbackHandler.java b/gnu/javax/security/auth/callback/SwingCallbackHandler.java
new file mode 100644
index 000000000..8e3e46eff
--- /dev/null
+++ b/gnu/javax/security/auth/callback/SwingCallbackHandler.java
@@ -0,0 +1,587 @@
+ /* SwingCallbackHandler.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.security.auth.callback;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import java.io.IOException;
+
+import java.util.Locale;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.ChoiceCallback;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.LanguageCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.TextOutputCallback;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+
+public class SwingCallbackHandler extends AbstractCallbackHandler
+{
+ public SwingCallbackHandler ()
+ {
+ super ("SWING");
+ }
+
+ protected void handleChoice (final ChoiceCallback callback)
+ throws IOException
+ {
+ final JDialog dialog = new JDialog ();
+ dialog.setResizable (false);
+ Container content = dialog.getContentPane ();
+ GridBagLayout layout = new GridBagLayout ();
+ content.setLayout (layout);
+ JLabel prompt = new JLabel (callback.getPrompt (), JLabel.LEFT);
+ content.add (prompt, new GridBagConstraints (0, 0, 1, 1, 0, 0,
+ GridBagConstraints.WEST,
+ GridBagConstraints.NONE,
+ new Insets (5, 5, 5, 5), 5, 5));
+
+ String[] choices = callback.getChoices ();
+ final JList choicesList = new JList (choices);
+ JScrollPane choicesPane = new JScrollPane (choicesList,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ final int defaultChoice = callback.getDefaultChoice ();
+ choicesList.setSelectedIndex (defaultChoice);
+ choicesList.setSelectionMode (callback.allowMultipleSelections ()
+ ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
+ : ListSelectionModel.SINGLE_SELECTION);
+ content.add (choicesPane, new GridBagConstraints (0, 1, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER,
+ GridBagConstraints.BOTH,
+ new Insets (0, 10, 0, 10), 5, 5));
+
+ JPanel confirmButtons = new JPanel ();
+ confirmButtons.setLayout (new FlowLayout (FlowLayout.RIGHT));
+ JButton cancel = new JButton (messages.getString ("callback.cancel"));
+ JButton ok = new JButton (messages.getString ("callback.ok"));
+ confirmButtons.add (cancel);
+ confirmButtons.add (ok);
+ content.add (confirmButtons, new GridBagConstraints (0, 2, 1, 1, 0, 0,
+ GridBagConstraints.EAST,
+ GridBagConstraints.NONE,
+ new Insets (5, 5, 5, 5),
+ 0, 0));
+ dialog.getRootPane ().setDefaultButton (ok);
+
+ cancel.addActionListener (new ActionListener ()
+ {
+ public void actionPerformed (final ActionEvent ae)
+ {
+ callback.setSelectedIndex (defaultChoice);
+ dialog.setVisible (false);
+ synchronized (callback)
+ {
+ callback.notify ();
+ }
+ }
+ });
+ ok.addActionListener (new ActionListener ()
+ {
+ public void actionPerformed (final ActionEvent ae)
+ {
+ if (callback.allowMultipleSelections ())
+ {
+ int[] indices = choicesList.getSelectedIndices ();
+ if (indices != null && indices.length > 0)
+ callback.setSelectedIndexes (indices);
+ else
+ callback.setSelectedIndex (defaultChoice);
+ }
+ else
+ {
+ int selected = choicesList.getSelectedIndex ();
+ if (selected != -1)
+ callback.setSelectedIndex (selected);
+ else
+ callback.setSelectedIndex (defaultChoice);
+ }
+ dialog.setVisible (false);
+ synchronized (callback)
+ {
+ callback.notify ();
+ }
+ }
+ });
+
+ dialog.pack ();
+ dialog.setSize (new Dimension (400, 400));
+ dialog.setVisible (true);
+ waitForInput (dialog, callback);
+ }
+
+ protected void handleConfirmation (final ConfirmationCallback callback)
+ throws IOException
+ {
+ final JDialog dialog = new JDialog ();
+ switch (callback.getMessageType ())
+ {
+ case ConfirmationCallback.ERROR:
+ dialog.setTitle (messages.getString ("callback.error"));
+ break;
+ case ConfirmationCallback.WARNING:
+ dialog.setTitle (messages.getString ("callback.warning"));
+ break;
+ case ConfirmationCallback.INFORMATION:
+ dialog.setTitle (messages.getString ("callback.information"));
+ break;
+ }
+ Container content = dialog.getContentPane ();
+ content.setLayout (new GridBagLayout ());
+
+ String prompt = callback.getPrompt ();
+ if (prompt != null)
+ {
+ content.add (new JLabel (prompt),
+ new GridBagConstraints (0, 0, 1, 1, 0, 0,
+ GridBagConstraints.WEST,
+ GridBagConstraints.NONE,
+ new Insets (5, 5, 5, 25), 0, 0));
+ }
+
+ final String[] options = callback.getOptions ();
+ ActionListener listener = new ActionListener ()
+ {
+ public void actionPerformed (ActionEvent ae)
+ {
+ String cmd = ae.getActionCommand ();
+ if (options != null)
+ {
+ for (int i = 0; i < options.length; i++)
+ {
+ if (cmd.equals (options[i]))
+ {
+ callback.setSelectedIndex (i);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (cmd.equals ("cancel"))
+ callback.setSelectedIndex (ConfirmationCallback.CANCEL);
+ else if (cmd.equals ("okay"))
+ callback.setSelectedIndex (ConfirmationCallback.OK);
+ else if (cmd.equals ("yes"))
+ callback.setSelectedIndex (ConfirmationCallback.YES);
+ else if (cmd.equals ("no"))
+ callback.setSelectedIndex (ConfirmationCallback.NO);
+ }
+ dialog.setVisible (false);
+ synchronized (callback)
+ {
+ callback.notify ();
+ }
+ }
+ };
+
+ JPanel buttons = new JPanel ();
+ buttons.setLayout (new FlowLayout (FlowLayout.RIGHT));
+ switch (callback.getOptionType ())
+ {
+ case ConfirmationCallback.YES_NO_CANCEL_OPTION:
+ {
+ JButton cancel = new JButton (messages.getString ("callback.cancel"));
+ buttons.add (cancel);
+ cancel.setActionCommand ("cancel");
+ cancel.addActionListener (listener);
+ }
+ /* Fall-through. */
+ case ConfirmationCallback.YES_NO_OPTION:
+ {
+ JButton yes = new JButton (messages.getString ("callback.yes"));
+ JButton no = new JButton (messages.getString ("callback.no"));
+ buttons.add (no);
+ buttons.add (yes);
+ yes.setActionCommand ("yes");
+ yes.addActionListener (listener);
+ no.setActionCommand ("no");
+ no.addActionListener (listener);
+ dialog.getRootPane ().setDefaultButton (yes);
+ }
+ break;
+ case ConfirmationCallback.OK_CANCEL_OPTION:
+ {
+ JButton okay = new JButton (messages.getString ("callback.ok"));
+ JButton cancel = new JButton (messages.getString ("callback.cancel"));
+ buttons.add (cancel);
+ buttons.add (okay);
+ okay.setActionCommand ("okay");
+ okay.addActionListener (listener);
+ cancel.setActionCommand ("cancel");
+ cancel.addActionListener (listener);
+ dialog.getRootPane ().setDefaultButton (okay);
+ }
+ break;
+ case ConfirmationCallback.UNSPECIFIED_OPTION:
+ for (int i = 0; i < options.length; i++)
+ {
+ JButton button = new JButton (options[i]);
+ buttons.add (button);
+ button.setActionCommand (options[i]);
+ button.addActionListener (listener);
+ if (i == options.length - 1)
+ dialog.getRootPane ().setDefaultButton (button);
+ }
+ }
+ content.add (buttons,
+ new GridBagConstraints (0, GridBagConstraints.RELATIVE,
+ 1, 1, 1, 1,
+ GridBagConstraints.SOUTHEAST,
+ GridBagConstraints.BOTH,
+ new Insets (5, 5, 5, 5), 0, 0));
+ dialog.setResizable (false);
+ dialog.pack ();
+ dialog.setVisible (true);
+ waitForInput (dialog, callback);
+ }
+
+ protected void handleLanguage (final LanguageCallback callback)
+ throws IOException
+ {
+ Locale locale = Locale.getDefault ();
+ Locale[] locales = Locale.getAvailableLocales ();
+ String[] localeNames = new String[locales.length+1];
+ int defaultIndex = 0;
+ for (int i = 0; i < locales.length; i++)
+ {
+ localeNames[i+1] = locales[i].getDisplayLanguage (locales[i]);
+ String country = locales[i].getDisplayCountry (locales[i]);
+ if (country.length () > 0)
+ localeNames[i+1] += " (" + country + ")";
+ if (locales[i].equals (locale))
+ defaultIndex = i;
+ }
+ locales[0] = locale;
+ localeNames[0] = locale.getDisplayLanguage (locale);
+ String country = locale.getDisplayCountry (locale);
+ if (country.length () > 0)
+ localeNames[0] += " (" + country + ")";
+ ChoiceCallback cb = new ChoiceCallback (messages.getString ("callback.language"),
+ localeNames, 0,
+ false);
+ handleChoice (cb);
+ int selected = cb.getSelectedIndexes ()[0];
+ if (selected > 0)
+ callback.setLocale (locales[selected - 1]);
+ else
+ callback.setLocale (locale);
+ }
+
+ protected void handleName (final NameCallback callback)
+ throws IOException
+ {
+ final JDialog dialog = new JDialog ();
+ Container content = dialog.getContentPane ();
+ content.setLayout (new GridBagLayout ());
+
+ content.add (new JLabel (callback.getPrompt ()),
+ new GridBagConstraints (0, 0, 1, 1, 0, 0,
+ GridBagConstraints.NORTHEAST,
+ GridBagConstraints.VERTICAL,
+ new Insets (10, 10, 15, 5), 0, 0));
+
+ final JTextField name = new JTextField ();
+ name.setColumns (20);
+ String _name;
+ if ((_name = callback.getDefaultName ()) != null)
+ name.setText (_name);
+ content.add (name, new GridBagConstraints (1, 0, 1, 1, 1, 1,
+ GridBagConstraints.NORTHWEST,
+ GridBagConstraints.BOTH,
+ new Insets (10, 5, 15, 10), 0, 0));
+
+ ActionListener listener = new ActionListener ()
+ {
+ public void actionPerformed (ActionEvent ae)
+ {
+ String cmd = ae.getActionCommand ();
+ if (cmd.equals ("okay"))
+ callback.setName (name.getText ());
+ dialog.setVisible (false);
+ synchronized (callback)
+ {
+ callback.notify ();
+ }
+ }
+ };
+
+ JPanel buttons = new JPanel ();
+ buttons.setLayout (new FlowLayout (FlowLayout.RIGHT));
+ JButton cancel = new JButton (messages.getString ("callback.cancel"));
+ JButton okay = new JButton (messages.getString ("callback.ok"));
+ cancel.setActionCommand ("cancel");
+ cancel.addActionListener (listener);
+ buttons.add (cancel);
+ okay.setActionCommand ("okay");
+ okay.addActionListener (listener);
+ buttons.add (okay);
+ content.add (buttons, new GridBagConstraints (0, 1, 2, 1, 0, 0,
+ GridBagConstraints.SOUTHEAST,
+ GridBagConstraints.NONE,
+ new Insets (0, 10, 10, 10), 0, 0));
+
+ dialog.setResizable (false);
+ dialog.pack ();
+ dialog.setVisible (true);
+ dialog.getRootPane ().setDefaultButton (okay);
+ waitForInput (dialog, callback);
+ }
+
+ protected void handlePassword (final PasswordCallback callback)
+ throws IOException
+ {
+ final JDialog dialog = new JDialog ();
+ Container content = dialog.getContentPane ();
+ content.setLayout (new GridBagLayout ());
+
+ content.add (new JLabel (callback.getPrompt ()),
+ new GridBagConstraints (0, 0, 1, 1, 0, 0,
+ GridBagConstraints.NORTHEAST,
+ GridBagConstraints.VERTICAL,
+ new Insets (10, 10, 15, 5), 0, 0));
+
+ final JPasswordField password = new JPasswordField ();
+ password.setColumns (20);
+ password.setEchoChar (callback.isEchoOn () ? '\u0000' : '\u2022');
+ content.add (password, new GridBagConstraints (1, 0, 1, 1, 1, 1,
+ GridBagConstraints.NORTHWEST,
+ GridBagConstraints.BOTH,
+ new Insets (10, 5, 15, 10), 0, 0));
+
+ ActionListener listener = new ActionListener ()
+ {
+ public void actionPerformed (ActionEvent ae)
+ {
+ String cmd = ae.getActionCommand ();
+ if (cmd.equals ("okay"))
+ callback.setPassword (password.getPassword ());
+ dialog.setVisible (false);
+ synchronized (callback)
+ {
+ callback.notify ();
+ }
+ }
+ };
+
+ JPanel buttons = new JPanel ();
+ buttons.setLayout (new FlowLayout (FlowLayout.RIGHT));
+ JButton cancel = new JButton (messages.getString ("callback.cancel"));
+ JButton okay = new JButton (messages.getString ("callback.ok"));
+ cancel.setActionCommand ("cancel");
+ cancel.addActionListener (listener);
+ buttons.add (cancel);
+ okay.setActionCommand ("okay");
+ okay.addActionListener (listener);
+ buttons.add (okay);
+ content.add (buttons, new GridBagConstraints (0, 1, 2, 1, 0, 0,
+ GridBagConstraints.SOUTHEAST,
+ GridBagConstraints.NONE,
+ new Insets (0, 10, 10, 10), 0, 0));
+
+ dialog.setResizable (false);
+ dialog.pack ();
+ dialog.setVisible (true);
+ dialog.getRootPane ().setDefaultButton (okay);
+ waitForInput (dialog, callback);
+ }
+
+ protected void handleTextInput (final TextInputCallback callback)
+ throws IOException
+ {
+ final JDialog dialog = new JDialog ();
+ Container content = dialog.getContentPane ();
+ content.setLayout (new GridBagLayout ());
+
+ content.add (new JLabel (callback.getPrompt ()),
+ new GridBagConstraints (0, 0, 1, 1, 0, 0,
+ GridBagConstraints.NORTHWEST,
+ GridBagConstraints.NONE,
+ new Insets (10, 10, 15, 5), 0, 0));
+
+ final JTextArea text = new JTextArea (24, 80);
+ text.setEditable (true);
+ String _text;
+ if ((_text = callback.getDefaultText ()) != null)
+ text.setText (_text);
+ text.setFont (new Font ("Monospaced", Font.PLAIN, 12));
+ JScrollPane textPane = new JScrollPane (text,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ content.add (textPane,
+ new GridBagConstraints (0, 1, 1, 1, 1, 1,
+ GridBagConstraints.CENTER,
+ GridBagConstraints.BOTH,
+ new Insets (5, 10, 5, 10), 0, 0));
+
+ ActionListener listener = new ActionListener ()
+ {
+ public void actionPerformed (ActionEvent ae)
+ {
+ String cmd = ae.getActionCommand ();
+ if (cmd.equals ("okay"))
+ callback.setText (text.getText ());
+ dialog.setVisible (false);
+ synchronized (callback)
+ {
+ callback.notify ();
+ }
+ }
+ };
+
+ JPanel buttons = new JPanel ();
+ buttons.setLayout (new FlowLayout (FlowLayout.RIGHT));
+ JButton cancel = new JButton (messages.getString ("callback.cancel"));
+ JButton okay = new JButton (messages.getString ("callback.ok"));
+ cancel.setActionCommand ("cancel");
+ cancel.addActionListener (listener);
+ buttons.add (cancel);
+ okay.setActionCommand ("okay");
+ okay.addActionListener (listener);
+ buttons.add (okay);
+ content.add (buttons, new GridBagConstraints (0, 2, 1, 1, 0, 0,
+ GridBagConstraints.SOUTHEAST,
+ GridBagConstraints.NONE,
+ new Insets (0, 10, 10, 10), 0, 0));
+
+ dialog.setResizable (true);
+ dialog.pack ();
+ dialog.setVisible (true);
+ dialog.getRootPane ().setDefaultButton (okay);
+ waitForInput (dialog, callback);
+ }
+
+ protected void handleTextOutput (final TextOutputCallback callback)
+ throws IOException
+ {
+ final JDialog dialog = new JDialog ();
+ switch (callback.getMessageType ())
+ {
+ case TextOutputCallback.ERROR:
+ dialog.setTitle (messages.getString ("callback.error"));
+ break;
+ case TextOutputCallback.WARNING:
+ dialog.setTitle (messages.getString ("callback.warning"));
+ break;
+ case TextOutputCallback.INFORMATION:
+ dialog.setTitle (messages.getString ("callback.information"));
+ break;
+ }
+ Container content = dialog.getContentPane ();
+ content.setLayout (new GridBagLayout ());
+
+ final JTextArea text = new JTextArea (24, 80);
+ text.setEditable (false);
+ text.setText (callback.getMessage ());
+ text.setFont (new Font ("Monospaced", Font.PLAIN, 12));
+ JScrollPane textPane = new JScrollPane (text,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ content.add (textPane,
+ new GridBagConstraints (0, 0, 1, 1, 1, 1,
+ GridBagConstraints.CENTER,
+ GridBagConstraints.BOTH,
+ new Insets (10, 10, 5, 10), 0, 0));
+
+ ActionListener listener = new ActionListener ()
+ {
+ public void actionPerformed (ActionEvent ae)
+ {
+ dialog.setVisible (false);
+ synchronized (callback)
+ {
+ callback.notify ();
+ }
+ }
+ };
+
+ JButton okay = new JButton (messages.getString ("callback.ok"));
+ okay.setActionCommand ("okay");
+ okay.addActionListener (listener);
+ content.add (okay, new GridBagConstraints (0, 1, 1, 1, 0, 0,
+ GridBagConstraints.SOUTHEAST,
+ GridBagConstraints.NONE,
+ new Insets (0, 10, 10, 10), 0, 0));
+
+ dialog.setResizable (true);
+ dialog.pack ();
+ dialog.setVisible (true);
+ dialog.getRootPane ().setDefaultButton (okay);
+ waitForInput (dialog, callback);
+ }
+
+ private void waitForInput (JDialog dialog, Callback callback)
+ {
+ synchronized (callback)
+ {
+ while (dialog.isVisible ())
+ {
+ try
+ {
+ callback.wait (1000);
+ }
+ catch (InterruptedException ignored)
+ {
+ }
+ }
+ }
+ dialog.dispose ();
+ }
+} \ No newline at end of file
diff --git a/resource/gnu/javax/security/auth/callback/MessagesBundle.properties b/resource/gnu/javax/security/auth/callback/MessagesBundle.properties
new file mode 100644
index 000000000..95ad337f5
--- /dev/null
+++ b/resource/gnu/javax/security/auth/callback/MessagesBundle.properties
@@ -0,0 +1,52 @@
+# MessagesBundle.properties -- Default messages bundle.
+# Copyright (C) 2005 Free Software Foundation, Inc.
+#
+# This file is a part of GNU Classpath.
+#
+# GNU Classpath is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# GNU Classpath is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Classpath; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+#
+# Linking this library statically or dynamically with other modules is
+# making a combined work based on this library. Thus, the terms and
+# conditions of the GNU General Public License cover the whole
+# combination.
+#
+# As a special exception, the copyright holders of this library give
+# you permission to link this library with independent modules to
+# produce an executable, regardless of the license terms of these
+# independent modules, and to copy and distribute the resulting
+# executable under terms of your choice, provided that you also meet,
+# for each linked independent module, the terms and conditions of the
+# license of that module. An independent module is a module which is
+# not derived from or based on this library. If you modify this
+# library, you may extend this exception to your version of the
+# library, but you are not obligated to do so. If you do not wish to
+# do so, delete this exception statement from your version.
+
+callback.yesNo=(yes or no)\
+callback.yesNoCancel=(yes, no, cancel)\
+callback.okCancel=(ok or cancel)\
+callback.language=Choose your language:\
+
+callback.yes=Yes
+callback.shortYes=y
+callback.no=No
+callback.shortNo=n
+callback.cancel=Cancel
+callback.ok=Okay
+
+callback.error=Error
+callback.information=Information
+callback.warning=Warning
diff --git a/resource/java/security/classpath.security b/resource/java/security/classpath.security
index c8e9dac94..cc7d49378 100644
--- a/resource/java/security/classpath.security
+++ b/resource/java/security/classpath.security
@@ -37,3 +37,6 @@
security.provider.1=gnu.java.security.provider.Gnu
+security.provider.2=gnu.javax.crypto.jce.GnuCrypto
+security.provider.3=gnu.javax.crypto.jce.GnuSasl
+security.provider.4=gnu.javax.net.ssl.provider.Jessie