summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/gnu/javax
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/javax')
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Assembly.java298
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Cascade.java405
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/CascadeStage.java109
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/CascadeTransformer.java139
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/DeflateTransformer.java233
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Direction.java92
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/LoopbackTransformer.java116
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/ModeStage.java129
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Operation.java89
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/PaddingTransformer.java178
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Stage.java218
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/Transformer.java460
-rw-r--r--libjava/classpath/gnu/javax/crypto/assembly/TransformerException.java158
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/Anubis.java583
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/BaseCipher.java304
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/Blowfish.java749
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/Cast5.java1391
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/CipherFactory.java169
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/DES.java894
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/IBlockCipher.java205
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/IBlockCipherSpi.java128
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/Khazad.java521
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/NullCipher.java129
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/Rijndael.java859
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/Serpent.java1830
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/Square.java520
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java196
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/Twofish.java909
-rw-r--r--libjava/classpath/gnu/javax/crypto/cipher/WeakKeyException.java71
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/DiffieHellmanImpl.java (renamed from libjava/classpath/gnu/javax/crypto/DiffieHellmanImpl.java)98
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/GnuCrypto.java620
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/GnuSasl.java114
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java229
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/AESSpi.java104
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/ARCFourSpi.java208
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/AnubisSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/BlowfishSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/Cast5Spi.java68
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java507
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/DESSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/KhazadSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/NullCipherSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/PBES2.java1352
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/RijndaelSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/SerpentSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/SquareSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/TripleDESSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/cipher/TwofishSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java73
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java80
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java80
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java87
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java120
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java52
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/keyring/GnuKeyring.java413
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacHavalSpi.java67
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD2Spi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD4Spi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD5Spi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA160Spi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA256Spi.java67
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA384Spi.java67
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA512Spi.java67
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacTigerSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/MacAdapter.java156
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacAnubisImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacCast5Impl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacDESImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacImpl.java137
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacKhazadImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacSerpentImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacSquareImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/OMacTwofishImpl.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/TMMH16Spi.java91
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/UHash32Spi.java59
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/mac/UMac32Spi.java91
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/params/BlockCipherParameters.java209
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/params/DEREncodingException.java53
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/params/DERReader.java160
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/params/DERWriter.java154
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java120
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/prng/CSPRNGSpi.java114
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/prng/FortunaImpl.java85
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/prng/ICMRandomSpi.java260
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/prng/UMacRandomSpi.java207
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyFactory.java232
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyPairGeneratorSpi.java91
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/sig/DHParameters.java220
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/sig/DHParametersGenerator.java152
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java139
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/spec/TMMHParameterSpec.java129
-rw-r--r--libjava/classpath/gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java82
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/BaseKeyAgreementParty.java208
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/GnuSecretKey.java149
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/IKeyAgreementParty.java105
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/IncomingMessage.java356
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/KeyAgreementException.java187
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/KeyAgreementFactory.java181
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/OutgoingMessage.java255
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairPKCS8Codec.java229
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java370
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairX509Codec.java244
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java134
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java147
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanSender.java156
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java130
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/ElGamalReceiver.java121
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/ElGamalSender.java134
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/GnuDHKey.java184
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java290
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java196
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/GnuDHPublicKey.java194
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/dh/RFC2631.java255
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRP6Host.java213
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java172
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslClient.java101
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslServer.java101
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSClient.java191
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSServer.java220
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRP6User.java203
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRPAlgorithm.java175
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRPKey.java170
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java351
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java380
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRPPrivateKey.java250
-rw-r--r--libjava/classpath/gnu/javax/crypto/key/srp6/SRPPublicKey.java194
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/AuthenticatedEntry.java222
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/BaseKeyring.java198
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/BinaryDataEntry.java128
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/CertPathEntry.java133
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/CertificateEntry.java150
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/CompressedEntry.java113
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/EncryptedEntry.java235
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/Entry.java178
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/EnvelopeEntry.java398
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/GnuPrivateKeyring.java328
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/GnuPublicKeyring.java146
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/IKeyring.java164
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/IPrivateKeyring.java142
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/IPublicKeyring.java81
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/MalformedKeyringException.java58
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java148
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/MeteredInputStream.java137
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java285
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java301
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PasswordProtectedEntry.java66
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PrimitiveEntry.java129
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PrivateKeyEntry.java221
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/Properties.java227
-rw-r--r--libjava/classpath/gnu/javax/crypto/keyring/PublicKeyEntry.java192
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/BaseMac.java148
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/HMac.java328
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/HMacFactory.java128
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/IMac.java197
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/MacFactory.java164
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/MacInputStream.java138
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/MacOutputStream.java140
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/OMAC.java402
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/TMMH16.java402
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/UHash32.java957
-rw-r--r--libjava/classpath/gnu/javax/crypto/mac/UMac32.java491
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/BaseMode.java352
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/CBC.java143
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/CFB.java175
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/CTR.java221
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/EAX.java352
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/ECB.java137
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/IAuthenticatedMode.java60
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/ICM.java228
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/IMode.java145
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/ModeFactory.java192
-rw-r--r--libjava/classpath/gnu/javax/crypto/mode/OFB.java194
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/BasePad.java153
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/IPad.java110
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/PKCS1_V1_5.java184
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/PKCS7.java149
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/PadFactory.java136
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/SSL3.java98
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/TBC.java156
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/TLS1.java105
-rw-r--r--libjava/classpath/gnu/javax/crypto/pad/WrongPaddingException.java63
-rw-r--r--libjava/classpath/gnu/javax/crypto/prng/ARCFour.java161
-rw-r--r--libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java1268
-rw-r--r--libjava/classpath/gnu/javax/crypto/prng/Fortuna.java366
-rw-r--r--libjava/classpath/gnu/javax/crypto/prng/ICMGenerator.java379
-rw-r--r--libjava/classpath/gnu/javax/crypto/prng/IPBE.java69
-rw-r--r--libjava/classpath/gnu/javax/crypto/prng/PBKDF2.java216
-rw-r--r--libjava/classpath/gnu/javax/crypto/prng/PRNGFactory.java143
-rw-r--r--libjava/classpath/gnu/javax/crypto/prng/UMacGenerator.java228
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/AuthInfo.java143
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/AuthInfoProviderFactory.java89
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/ClientFactory.java210
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/ClientMechanism.java365
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/ConfidentialityException.java84
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/IAuthInfoProvider.java117
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java62
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/IllegalMechanismStateException.java86
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/InputBuffer.java339
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/IntegrityException.java83
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/NoSuchMechanismException.java62
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/NoSuchUserException.java67
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/OutputBuffer.java225
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/SaslEncodingException.java66
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/SaslInputStream.java459
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/SaslOutputStream.java218
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/SaslUtil.java89
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/ServerFactory.java194
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/ServerMechanism.java371
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/UserAlreadyExistsException.java70
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousClient.java120
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousServer.java107
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java109
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java200
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Client.java201
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java66
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Server.java185
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Util.java137
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/crammd5/PasswordFile.java301
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/plain/PasswordFile.java309
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java206
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/plain/PlainClient.java193
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/plain/PlainRegistry.java67
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/plain/PlainServer.java196
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/CALG.java292
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/ClientStore.java173
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/IALG.java159
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/KDF.java169
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/PasswordFile.java699
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/SRP.java285
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java218
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/SRPClient.java1211
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/SRPRegistry.java219
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/SRPServer.java1156
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/SecurityContext.java164
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/ServerStore.java196
-rw-r--r--libjava/classpath/gnu/javax/crypto/sasl/srp/StoreEntry.java89
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/Base64.java311
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/EntropySource.java62
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/NullManagerParameters.java56
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/PrivateCredentials.java360
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/SRPManagerParameters.java81
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/SRPTrustManager.java99
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/StaticTrustAnchors.java1942
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Alert.java474
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/AlertException.java76
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Certificate.java194
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/CertificateRequest.java285
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/CertificateType.java104
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/CertificateVerify.java95
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/CipherSuite.java754
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/ClientHello.java253
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/ClientKeyExchange.java181
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/CompressionMethod.java104
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Constructed.java57
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/ContentType.java135
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Context.java334
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/DiffieHellman.java285
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/DigestInputStream.java103
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/DigestOutputStream.java107
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Enumerated.java79
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Extension.java214
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Extensions.java159
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Finished.java143
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/GNUSecurityParameters.java490
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Handshake.java440
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JCESecurityParameters.java307
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JDBCSessionContext.java356
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Jessie.java91
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java (renamed from libjava/classpath/gnu/javax/crypto/GnuDHPrivateKey.java)69
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPublicKey.java99
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java98
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java98
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/KeyPool.java119
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/MacException.java53
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/OverflowException.java57
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/ProtocolVersion.java180
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Random.java124
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/RecordInput.java232
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/RecordInputStream.java106
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/RecordOutputStream.java189
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/RecordingInputStream.java131
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java225
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLHMac.java158
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLRSASignature.java235
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLRandom.java165
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLServerSocket.java283
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java136
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLSocket.java3530
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketFactory.java133
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketInputStream.java181
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java115
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SecurityParameters.java178
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/ServerHello.java216
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/ServerKeyExchange.java286
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Session.java381
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SessionContext.java250
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Signature.java158
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/SynchronizedRandom.java104
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/TLSHMac.java138
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/TLSRandom.java252
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/Util.java422
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java359
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java298
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/XMLSessionContext.java619
-rw-r--r--libjava/classpath/gnu/javax/security/auth/Password.java285
-rw-r--r--libjava/classpath/gnu/javax/security/auth/callback/AWTCallbackHandler.java452
-rw-r--r--libjava/classpath/gnu/javax/security/auth/callback/AbstractCallbackHandler.java258
-rw-r--r--libjava/classpath/gnu/javax/security/auth/callback/ConsoleCallbackHandler.java289
-rw-r--r--libjava/classpath/gnu/javax/security/auth/callback/DefaultCallbackHandler.java109
-rw-r--r--libjava/classpath/gnu/javax/security/auth/callback/GnuCallbacks.java64
-rw-r--r--libjava/classpath/gnu/javax/security/auth/callback/SwingCallbackHandler.java587
-rw-r--r--libjava/classpath/gnu/javax/security/auth/login/ConfigFileParser.java338
-rw-r--r--libjava/classpath/gnu/javax/security/auth/login/ConfigFileTokenizer.java243
-rw-r--r--libjava/classpath/gnu/javax/security/auth/login/GnuConfiguration.java450
336 files changed, 75858 insertions, 81 deletions
diff --git a/libjava/classpath/gnu/javax/crypto/assembly/Assembly.java b/libjava/classpath/gnu/javax/crypto/assembly/Assembly.java
new file mode 100644
index 00000000000..1d70eff87f4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/Cascade.java b/libjava/classpath/gnu/javax/crypto/assembly/Cascade.java
new file mode 100644
index 00000000000..20cd3de9d88
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/CascadeStage.java b/libjava/classpath/gnu/javax/crypto/assembly/CascadeStage.java
new file mode 100644
index 00000000000..71a8b178ff1
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/CascadeTransformer.java b/libjava/classpath/gnu/javax/crypto/assembly/CascadeTransformer.java
new file mode 100644
index 00000000000..325571dcddc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/DeflateTransformer.java b/libjava/classpath/gnu/javax/crypto/assembly/DeflateTransformer.java
new file mode 100644
index 00000000000..35328a6c1dc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/Direction.java b/libjava/classpath/gnu/javax/crypto/assembly/Direction.java
new file mode 100644
index 00000000000..2e8ef1145a4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/LoopbackTransformer.java b/libjava/classpath/gnu/javax/crypto/assembly/LoopbackTransformer.java
new file mode 100644
index 00000000000..62791264f96
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/ModeStage.java b/libjava/classpath/gnu/javax/crypto/assembly/ModeStage.java
new file mode 100644
index 00000000000..1cd8fd9154e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/Operation.java b/libjava/classpath/gnu/javax/crypto/assembly/Operation.java
new file mode 100644
index 00000000000..2646e1f3301
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/PaddingTransformer.java b/libjava/classpath/gnu/javax/crypto/assembly/PaddingTransformer.java
new file mode 100644
index 00000000000..8af46a72a95
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/Stage.java b/libjava/classpath/gnu/javax/crypto/assembly/Stage.java
new file mode 100644
index 00000000000..e44985534b7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/Transformer.java b/libjava/classpath/gnu/javax/crypto/assembly/Transformer.java
new file mode 100644
index 00000000000..c62c4677ffb
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/assembly/TransformerException.java b/libjava/classpath/gnu/javax/crypto/assembly/TransformerException.java
new file mode 100644
index 00000000000..412f0f0f183
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/Anubis.java b/libjava/classpath/gnu/javax/crypto/cipher/Anubis.java
new file mode 100644
index 00000000000..63b97ce4e08
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/BaseCipher.java b/libjava/classpath/gnu/javax/crypto/cipher/BaseCipher.java
new file mode 100644
index 00000000000..9d62311ed58
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/Blowfish.java b/libjava/classpath/gnu/javax/crypto/cipher/Blowfish.java
new file mode 100644
index 00000000000..5cb958ee47b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/Cast5.java b/libjava/classpath/gnu/javax/crypto/cipher/Cast5.java
new file mode 100644
index 00000000000..cbdfe61f5b1
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/CipherFactory.java b/libjava/classpath/gnu/javax/crypto/cipher/CipherFactory.java
new file mode 100644
index 00000000000..082bfb8fa2d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/DES.java b/libjava/classpath/gnu/javax/crypto/cipher/DES.java
new file mode 100644
index 00000000000..8b7627ceaf8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/IBlockCipher.java b/libjava/classpath/gnu/javax/crypto/cipher/IBlockCipher.java
new file mode 100644
index 00000000000..238ee280f83
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/IBlockCipherSpi.java b/libjava/classpath/gnu/javax/crypto/cipher/IBlockCipherSpi.java
new file mode 100644
index 00000000000..6fe07ca7f50
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/Khazad.java b/libjava/classpath/gnu/javax/crypto/cipher/Khazad.java
new file mode 100644
index 00000000000..b6c27833eb8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/NullCipher.java b/libjava/classpath/gnu/javax/crypto/cipher/NullCipher.java
new file mode 100644
index 00000000000..09252db9063
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/Rijndael.java b/libjava/classpath/gnu/javax/crypto/cipher/Rijndael.java
new file mode 100644
index 00000000000..058c8b3466d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/Serpent.java b/libjava/classpath/gnu/javax/crypto/cipher/Serpent.java
new file mode 100644
index 00000000000..b323b5017b9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/Square.java b/libjava/classpath/gnu/javax/crypto/cipher/Square.java
new file mode 100644
index 00000000000..15cb8b53602
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java b/libjava/classpath/gnu/javax/crypto/cipher/TripleDES.java
new file mode 100644
index 00000000000..9b44c9ca7fb
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/Twofish.java b/libjava/classpath/gnu/javax/crypto/cipher/Twofish.java
new file mode 100644
index 00000000000..bea7f5d2cf2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/cipher/WeakKeyException.java b/libjava/classpath/gnu/javax/crypto/cipher/WeakKeyException.java
new file mode 100644
index 00000000000..4454e0e4502
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/DiffieHellmanImpl.java b/libjava/classpath/gnu/javax/crypto/jce/DiffieHellmanImpl.java
index 4797af7cf79..02761477a69 100644
--- a/libjava/classpath/gnu/javax/crypto/DiffieHellmanImpl.java
+++ b/libjava/classpath/gnu/javax/crypto/jce/DiffieHellmanImpl.java
@@ -1,5 +1,5 @@
/* DiffieHellmanImpl.java -- implementation of the Diffie-Hellman key agreement.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -36,16 +36,11 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.javax.crypto;
-
-import gnu.java.security.provider.GnuDHPublicKey;
+package gnu.javax.crypto.jce;
import java.math.BigInteger;
-
-import java.security.Key;
import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
+import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
@@ -57,13 +52,13 @@ import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
- * The Diffie-Hellman key agreement.
- *
+ * The JCE implementation of a 2-party Diffie-Hellman key agreement.
+ *
* @author Casey Marshall (csm@gnu.org)
*/
-public final class DiffieHellmanImpl extends KeyAgreementSpi
+public final class DiffieHellmanImpl
+ extends KeyAgreementSpi
{
-
/** The private key being used for this agreement. */
private DHPrivateKey key;
@@ -74,86 +69,87 @@ public final class DiffieHellmanImpl extends KeyAgreementSpi
private boolean last_phase_done;
/** Trivial default constructor. */
- public DiffieHellmanImpl ()
+ public DiffieHellmanImpl()
{
+ super();
+
key = null;
result = null;
last_phase_done = false;
}
- // KeyAgreementSpi methods.
-
- protected Key engineDoPhase (final Key incoming, final boolean lastPhase)
- throws InvalidKeyException
+ protected Key engineDoPhase(Key incoming, boolean lastPhase)
+ throws InvalidKeyException
{
if (key == null)
- throw new IllegalStateException ("not initialized");
+ throw new IllegalStateException("Not initialized");
+
if (last_phase_done)
- throw new IllegalStateException ("last phase already done");
+ throw new IllegalStateException("Last phase already done");
+
+ if (! (incoming instanceof DHPublicKey))
+ throw new InvalidKeyException("Key MUST be a DHPublicKey");
- if (!(incoming instanceof DHPublicKey))
- throw new InvalidKeyException ("expecting javax.crypto.interfaces.DHPublicKey");
DHPublicKey pub = (DHPublicKey) incoming;
DHParameterSpec s1 = key.getParams();
DHParameterSpec s2 = pub.getParams();
- if (!s1.getG().equals (s2.getG())
- || !s1.getP().equals (s2.getP())
+ if (! s1.getG().equals(s2.getG()) || ! s1.getP().equals(s2.getP())
|| s1.getL() != s2.getL())
- throw new InvalidKeyException ("supplied key is not compatible");
+ throw new InvalidKeyException("Incompatible key");
- result = pub.getY().modPow (key.getX(), s1.getP());
- if (lastPhase)
- {
- last_phase_done = true;
- return null;
- }
+ result = pub.getY().modPow(key.getX(), s1.getP());
+ if (! lastPhase)
+ throw new IllegalArgumentException("This key-agreement MUST be concluded in one step only");
- throw new IllegalArgumentException ("only supports two-party Diffie Hellman");
+ last_phase_done = true;
+ return null;
}
- protected byte[] engineGenerateSecret ()
+ protected byte[] engineGenerateSecret()
{
- if (result == null || !last_phase_done)
- throw new IllegalStateException ("not finished");
+ if (result == null || ! last_phase_done)
+ throw new IllegalStateException("Not finished");
- byte[] buf = result.toByteArray ();
+ byte[] buf = result.toByteArray();
if (buf[0] == 0x00)
{
- byte[] buf2 = new byte[buf.length - 1];
- System.arraycopy (buf, 1, buf2, 0, buf2.length);
- buf = buf2;
+ byte[] buf2 = new byte[buf.length - 1];
+ System.arraycopy(buf, 1, buf2, 0, buf2.length);
+ buf = buf2;
}
+
return buf;
}
- protected int engineGenerateSecret (final byte[] secret, final int offset)
+ protected int engineGenerateSecret(byte[] secret, int offset)
{
byte[] s = engineGenerateSecret();
- System.arraycopy (s, 0, secret, offset, s.length);
+ System.arraycopy(s, 0, secret, offset, s.length);
return s.length;
}
- protected SecretKey engineGenerateSecret (final String algorithm)
- throws InvalidKeyException
+ protected SecretKey engineGenerateSecret(String algorithm)
+ throws InvalidKeyException
{
byte[] s = engineGenerateSecret();
- return new SecretKeySpec (s, algorithm);
+ return new SecretKeySpec(s, algorithm);
}
- protected void engineInit (final Key key, final SecureRandom random)
- throws InvalidKeyException
+ protected void engineInit(Key key, SecureRandom random)
+ throws InvalidKeyException
{
- if (!(key instanceof DHPrivateKey))
- throw new InvalidKeyException ("not a javax.crypto.interfaces.DHPrivateKey");
+ if (! (key instanceof DHPrivateKey))
+ throw new InvalidKeyException("Key MUST be a DHPrivateKey");
+
this.key = (DHPrivateKey) key;
result = null;
last_phase_done = false;
}
- protected void engineInit (final Key key, final AlgorithmParameterSpec params,
- final SecureRandom random)
- throws InvalidKeyException
+ protected void engineInit(Key key, AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException
{
- engineInit (key, random);
+ engineInit(key, random);
}
}
diff --git a/libjava/classpath/gnu/javax/crypto/jce/GnuCrypto.java b/libjava/classpath/gnu/javax/crypto/jce/GnuCrypto.java
new file mode 100644
index 00000000000..b0e73b13256
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/jce/GnuCrypto.java
@@ -0,0 +1,620 @@
+/* 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());
+
+
+ // KeyGenerator Adapter implementations
+ put("KeyGenerator.Anubis",
+ gnu.javax.crypto.jce.key.AnubisKeyGeneratorImpl.class.getName());
+ put("KeyGenerator.Blowfish",
+ gnu.javax.crypto.jce.key.BlowfishKeyGeneratorImpl.class.getName());
+ put("KeyGenerator.Cast5",
+ gnu.javax.crypto.jce.key.Cast5KeyGeneratorImpl.class.getName());
+ put("KeyGenerator.DES",
+ gnu.javax.crypto.jce.key.DESKeyGeneratorImpl.class.getName());
+ put("KeyGenerator.Khazad",
+ gnu.javax.crypto.jce.key.KhazadKeyGeneratorImpl.class.getName());
+ put("KeyGenerator.Rijndael",
+ gnu.javax.crypto.jce.key.RijndaelKeyGeneratorImpl.class.getName());
+ put("KeyGenerator.Serpent",
+ gnu.javax.crypto.jce.key.SerpentKeyGeneratorImpl.class.getName());
+ put("KeyGenerator.Square",
+ gnu.javax.crypto.jce.key.SquareKeyGeneratorImpl.class.getName());
+ put("KeyGenerator.TripleDES",
+ gnu.javax.crypto.jce.key.TripleDESKeyGeneratorImpl.class.getName());
+ put("Alg.Alias.KeyGenerator.AES", "Rijndael");
+ put("Alg.Alias.KeyGenerator.DESede", "TripleDES");
+ put("Alg.Alias.KeyGenerator.3-DES", "TripleDES");
+ put("Alg.Alias.KeyGenerator.3DES", "TripleDES");
+
+ // 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.DH",
+ gnu.javax.crypto.jce.DiffieHellmanImpl.class.getName());
+ put("Alg.Alias.KeyAgreement.DiffieHellman", "DH");
+
+ // 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");
+
+ // KeyPairGenerator ---------------------------------------------------
+ put("KeyPairGenerator.DH",
+ gnu.javax.crypto.jce.sig.DHKeyPairGeneratorSpi.class.getName());
+ put("KeyPairGenerator.DH KeySize", "512");
+ put("KeyPairGenerator.DH ImplementedIn", "Software");
+
+ put("Alg.Alias.KeyPairGenerator.DiffieHellman", "DH");
+
+ // KeyFactory ---------------------------------------------------------
+ put("KeyFactory.DH",
+ gnu.javax.crypto.jce.sig.DHKeyFactory.class.getName());
+
+ put("Alg.Alias,KeyFactory.DiffieHellman", "DH");
+
+ // Algorithm Parameters -----------------------------------------------
+ put("AlgorithmParameters.DH",
+ gnu.javax.crypto.jce.sig.DHParameters.class.getName());
+
+ put("Alg.Alias.AlgorithmParameters.DiffieHellman", "DH");
+
+ // Algorithm Parameters Generator -------------------------------------
+ put("AlgorithmParameterGenerator.DH",
+ gnu.javax.crypto.jce.sig.DHParametersGenerator.class.getName());
+
+ put("Alg.Alias.AlgorithmParameterGenerator.DiffieHellman", "DH");
+
+ 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/libjava/classpath/gnu/javax/crypto/jce/GnuSasl.java b/libjava/classpath/gnu/javax/crypto/jce/GnuSasl.java
new file mode 100644
index 00000000000..6ee86ae19d5
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java b/libjava/classpath/gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java
new file mode 100644
index 00000000000..59231c6c71d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/AESSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/AESSpi.java
new file mode 100644
index 00000000000..ba7466fc39c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/ARCFourSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/ARCFourSpi.java
new file mode 100644
index 00000000000..8fc1fe4cbbf
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/AnubisSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/AnubisSpi.java
new file mode 100644
index 00000000000..ac2f596c863
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/BlowfishSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/BlowfishSpi.java
new file mode 100644
index 00000000000..d1a28616d0d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/Cast5Spi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/Cast5Spi.java
new file mode 100644
index 00000000000..b1d4cf70374
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java
new file mode 100644
index 00000000000..9667a67fff8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/DESSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/DESSpi.java
new file mode 100644
index 00000000000..f3ec8220a7f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/KhazadSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/KhazadSpi.java
new file mode 100644
index 00000000000..7f43dd010fa
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/NullCipherSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/NullCipherSpi.java
new file mode 100644
index 00000000000..0876c9585a3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/PBES2.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/PBES2.java
new file mode 100644
index 00000000000..28b327d8365
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/RijndaelSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/RijndaelSpi.java
new file mode 100644
index 00000000000..1a67f934b9e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/SerpentSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/SerpentSpi.java
new file mode 100644
index 00000000000..394a0ce0a66
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/SquareSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/SquareSpi.java
new file mode 100644
index 00000000000..bb59cd224ce
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/TripleDESSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/TripleDESSpi.java
new file mode 100644
index 00000000000..cec30f6537d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/cipher/TwofishSpi.java b/libjava/classpath/gnu/javax/crypto/jce/cipher/TwofishSpi.java
new file mode 100644
index 00000000000..34f2d95d60a
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/AnubisKeyGeneratorImpl.java
new file mode 100644
index 00000000000..e8d7788e8b7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/AnubisSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..f9725eae033
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/BlowfishKeyGeneratorImpl.java
new file mode 100644
index 00000000000..a0e687acdf8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/BlowfishSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..4b3620bc17d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/Cast5KeyGeneratorImpl.java
new file mode 100644
index 00000000000..18d26e67fdb
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/Cast5SecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..4bd31711eea
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/DESKeyGeneratorImpl.java
new file mode 100644
index 00000000000..19c54653a07
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/DESSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..e0f1c586096
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/DESedeSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..15e10994020
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/KhazadKeyGeneratorImpl.java
new file mode 100644
index 00000000000..c01391e4486
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/KhazadSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..c86e01110c5
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/RijndaelKeyGeneratorImpl.java
new file mode 100644
index 00000000000..535e573ad8e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/RijndaelSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..4aab584a2cc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/SecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..72defe1d7f2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/SecretKeyGeneratorImpl.java
new file mode 100644
index 00000000000..0a62655734c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/SerpentKeyGeneratorImpl.java
new file mode 100644
index 00000000000..766860a96b0
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/SerpentSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..6e80671fac7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/SquareKeyGeneratorImpl.java
new file mode 100644
index 00000000000..4bfbeb66833
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/SquareSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..d1d5d551432
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/TripleDESKeyGeneratorImpl.java
new file mode 100644
index 00000000000..eb423fcd19c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/TwofishKeyGeneratorImpl.java
new file mode 100644
index 00000000000..ae7e22feec3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java b/libjava/classpath/gnu/javax/crypto/jce/key/TwofishSecretKeyFactoryImpl.java
new file mode 100644
index 00000000000..e6ca80b6363
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/keyring/GnuKeyring.java b/libjava/classpath/gnu/javax/crypto/jce/keyring/GnuKeyring.java
new file mode 100644
index 00000000000..d74d386b4f0
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacHavalSpi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacHavalSpi.java
new file mode 100644
index 00000000000..df1319cbfdb
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD2Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD2Spi.java
new file mode 100644
index 00000000000..935f5e5a3e2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD4Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD4Spi.java
new file mode 100644
index 00000000000..49507a6dd5f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD5Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacMD5Spi.java
new file mode 100644
index 00000000000..3bc0fea6b30
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacRipeMD128Spi.java
new file mode 100644
index 00000000000..6a57e6c9d4e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacRipeMD160Spi.java
new file mode 100644
index 00000000000..a47e1a5c74b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA160Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA160Spi.java
new file mode 100644
index 00000000000..e251dc373ab
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA256Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA256Spi.java
new file mode 100644
index 00000000000..7caa260415e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA384Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA384Spi.java
new file mode 100644
index 00000000000..d3e454b54d6
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA512Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacSHA512Spi.java
new file mode 100644
index 00000000000..f02267c847d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacTigerSpi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacTigerSpi.java
new file mode 100644
index 00000000000..e4eb26ca948
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/HMacWhirlpoolSpi.java
new file mode 100644
index 00000000000..8e2ef6d2f8d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/MacAdapter.java b/libjava/classpath/gnu/javax/crypto/jce/mac/MacAdapter.java
new file mode 100644
index 00000000000..c323413a4a8
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/jce/mac/MacAdapter.java
@@ -0,0 +1,156 @@
+/* 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.2 $
+ */
+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();
+ }
+
+ /**
+ * Private constructor for cloning purposes.
+ *
+ * @param mac a clone of the internal {@link IMac} instance.
+ * @param attributes a clone of the current {@link Map} of attributes.
+ */
+ private MacAdapter(IMac mac, Map attributes)
+ {
+ super();
+
+ this.mac = mac;
+ this.attributes = attributes;
+ }
+
+ // Class methods
+ // -----------------------------------------------------------------------
+
+ // Instance methods
+ // -----------------------------------------------------------------------
+
+ // Cloneable interface implementation ------------------------------------
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ return new MacAdapter((IMac) mac.clone(), new HashMap(attributes));
+ }
+
+ // 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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacAnubisImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacAnubisImpl.java
new file mode 100644
index 00000000000..4bfda4fd6cc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacBlowfishImpl.java
new file mode 100644
index 00000000000..8d168e57be5
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacCast5Impl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacCast5Impl.java
new file mode 100644
index 00000000000..3385d116bc4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacDESImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacDESImpl.java
new file mode 100644
index 00000000000..3fb23bdefde
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacImpl.java
new file mode 100644
index 00000000000..f91902ae543
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacKhazadImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacKhazadImpl.java
new file mode 100644
index 00000000000..82c047c25a3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacRijndaelImpl.java
new file mode 100644
index 00000000000..47d3f6aae70
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacSerpentImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacSerpentImpl.java
new file mode 100644
index 00000000000..bec2c1f5c74
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacSquareImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacSquareImpl.java
new file mode 100644
index 00000000000..0442b7caf25
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacTripleDESImpl.java
new file mode 100644
index 00000000000..0defdd1fd36
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/OMacTwofishImpl.java b/libjava/classpath/gnu/javax/crypto/jce/mac/OMacTwofishImpl.java
new file mode 100644
index 00000000000..a12f9f30e85
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/TMMH16Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/TMMH16Spi.java
new file mode 100644
index 00000000000..0a4222237ef
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/UHash32Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/UHash32Spi.java
new file mode 100644
index 00000000000..a24b8e59c9f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/mac/UMac32Spi.java b/libjava/classpath/gnu/javax/crypto/jce/mac/UMac32Spi.java
new file mode 100644
index 00000000000..52c58f36f75
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/params/BlockCipherParameters.java b/libjava/classpath/gnu/javax/crypto/jce/params/BlockCipherParameters.java
new file mode 100644
index 00000000000..bae7cbf88f4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/params/DEREncodingException.java b/libjava/classpath/gnu/javax/crypto/jce/params/DEREncodingException.java
new file mode 100644
index 00000000000..ddfa6e1dee7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/params/DERReader.java b/libjava/classpath/gnu/javax/crypto/jce/params/DERReader.java
new file mode 100644
index 00000000000..f61423255fc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/params/DERWriter.java b/libjava/classpath/gnu/javax/crypto/jce/params/DERWriter.java
new file mode 100644
index 00000000000..876c2cd6caa
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java b/libjava/classpath/gnu/javax/crypto/jce/prng/ARCFourRandomSpi.java
new file mode 100644
index 00000000000..0c071561b6f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/prng/CSPRNGSpi.java b/libjava/classpath/gnu/javax/crypto/jce/prng/CSPRNGSpi.java
new file mode 100644
index 00000000000..c0aa015b065
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/prng/FortunaImpl.java b/libjava/classpath/gnu/javax/crypto/jce/prng/FortunaImpl.java
new file mode 100644
index 00000000000..7006bbbaddc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/prng/ICMRandomSpi.java b/libjava/classpath/gnu/javax/crypto/jce/prng/ICMRandomSpi.java
new file mode 100644
index 00000000000..d04b782f9f5
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/prng/UMacRandomSpi.java b/libjava/classpath/gnu/javax/crypto/jce/prng/UMacRandomSpi.java
new file mode 100644
index 00000000000..7dad68b2f95
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyFactory.java b/libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyFactory.java
new file mode 100644
index 00000000000..701191adc34
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyFactory.java
@@ -0,0 +1,232 @@
+/* DHKeyFactory.java -- DH key-factory JCE Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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.sig;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.key.dh.DHKeyPairPKCS8Codec;
+import gnu.javax.crypto.key.dh.DHKeyPairX509Codec;
+import gnu.javax.crypto.key.dh.GnuDHPrivateKey;
+import gnu.javax.crypto.key.dh.GnuDHPublicKey;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactorySpi;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHPrivateKeySpec;
+import javax.crypto.spec.DHPublicKeySpec;
+
+/**
+ * Implementation of a JCE Adapter for DH a key-factory.
+ */
+public class DHKeyFactory
+ extends KeyFactorySpi
+{
+ // implicit 0-arguments constructor
+
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof DHPublicKeySpec)
+ {
+ DHPublicKeySpec spec = (DHPublicKeySpec) keySpec;
+ BigInteger p = spec.getP();
+ BigInteger g = spec.getG();
+ BigInteger y = spec.getY();
+ return new GnuDHPublicKey(Registry.X509_ENCODING_ID, null, p, g, y);
+ }
+
+ if (keySpec instanceof X509EncodedKeySpec)
+ {
+ X509EncodedKeySpec spec = (X509EncodedKeySpec) keySpec;
+ byte[] encoded = spec.getEncoded();
+ PublicKey result;
+ try
+ {
+ result = new DHKeyPairX509Codec().decodePublicKey(encoded);
+ return result;
+ }
+ catch (RuntimeException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ throw new InvalidKeySpecException("Unsupported (public) key specification");
+ }
+
+ protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof DHPrivateKeySpec)
+ {
+ DHPrivateKeySpec spec = (DHPrivateKeySpec) keySpec;
+ BigInteger p = spec.getP();
+ BigInteger g = spec.getG();
+ BigInteger x = spec.getX();
+ return new GnuDHPrivateKey(Registry.PKCS8_ENCODING_ID, null, p, g, x);
+ }
+
+ if (keySpec instanceof PKCS8EncodedKeySpec)
+ {
+ PKCS8EncodedKeySpec spec = (PKCS8EncodedKeySpec) keySpec;
+ byte[] encoded = spec.getEncoded();
+ PrivateKey result;
+ try
+ {
+ result = new DHKeyPairPKCS8Codec().decodePrivateKey(encoded);
+ return result;
+ }
+ catch (RuntimeException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ throw new InvalidKeySpecException("Unsupported (private) key specification");
+ }
+
+ protected KeySpec engineGetKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException
+ {
+ if (key instanceof DHPublicKey)
+ {
+ if (keySpec.isAssignableFrom(DHPublicKeySpec.class))
+ {
+ DHPublicKey dssKey = (DHPublicKey) key;
+ BigInteger p = dssKey.getParams().getP();
+ BigInteger g = dssKey.getParams().getG();
+ BigInteger y = dssKey.getY();
+ return new DHPublicKeySpec(y, p, g);
+ }
+
+ if (keySpec.isAssignableFrom(X509EncodedKeySpec.class))
+ {
+ if (key instanceof GnuDHPublicKey)
+ {
+ GnuDHPublicKey dhKey = (GnuDHPublicKey) key;
+ byte[] encoded = dhKey.getEncoded(Registry.X509_ENCODING_ID);
+ return new X509EncodedKeySpec(encoded);
+ }
+
+ if (Registry.X509_ENCODING_SORT_NAME.equalsIgnoreCase(key.getFormat()))
+ {
+ byte[] encoded = key.getEncoded();
+ return new X509EncodedKeySpec(encoded);
+ }
+
+ throw new InvalidKeySpecException("Wrong key type or unsupported (public) key specification");
+ }
+
+ throw new InvalidKeySpecException("Unsupported (public) key specification");
+ }
+
+ if (key instanceof DHPrivateKey)
+ {
+ if (keySpec.isAssignableFrom(DHPrivateKeySpec.class))
+ {
+ DHPrivateKey dhKey = (DHPrivateKey) key;
+ BigInteger p = dhKey.getParams().getP();
+ BigInteger g = dhKey.getParams().getG();
+ BigInteger x = dhKey.getX();
+ return new DHPrivateKeySpec(x, p, g);
+ }
+
+ if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class))
+ {
+ if (key instanceof GnuDHPrivateKey)
+ {
+ GnuDHPrivateKey dhKey = (GnuDHPrivateKey) key;
+ byte[] encoded = dhKey.getEncoded(Registry.PKCS8_ENCODING_ID);
+ return new PKCS8EncodedKeySpec(encoded);
+ }
+
+ if (Registry.PKCS8_ENCODING_SHORT_NAME.equalsIgnoreCase(key.getFormat()))
+ {
+ byte[] encoded = key.getEncoded();
+ return new PKCS8EncodedKeySpec(encoded);
+ }
+
+ throw new InvalidKeySpecException("Wrong key type or unsupported (private) key specification");
+ }
+
+ throw new InvalidKeySpecException("Unsupported (private) key specification");
+ }
+
+ throw new InvalidKeySpecException("Wrong key type or unsupported key specification");
+ }
+
+ protected Key engineTranslateKey(Key key) throws InvalidKeyException
+ {
+ if ((key instanceof GnuDHPublicKey) || (key instanceof GnuDHPrivateKey))
+ return key;
+
+ if (key instanceof DHPublicKey)
+ {
+ DHPublicKey dsaKey = (DHPublicKey) key;
+ BigInteger p = dsaKey.getParams().getP();
+ BigInteger g = dsaKey.getParams().getG();
+ BigInteger y = dsaKey.getY();
+ return new GnuDHPublicKey(Registry.X509_ENCODING_ID, null, p, g, y);
+ }
+
+ if (key instanceof DHPrivateKey)
+ {
+ DHPrivateKey dsaKey = (DHPrivateKey) key;
+ BigInteger p = dsaKey.getParams().getP();
+ BigInteger g = dsaKey.getParams().getG();
+ BigInteger x = dsaKey.getX();
+ return new GnuDHPrivateKey(Registry.PKCS8_ENCODING_ID, null, p, g, x);
+ }
+
+ throw new InvalidKeyException("Wrong key type");
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyPairGeneratorSpi.java b/libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyPairGeneratorSpi.java
new file mode 100644
index 00000000000..5b3badc8d83
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyPairGeneratorSpi.java
@@ -0,0 +1,91 @@
+/* DHKeyPairGeneratorSpi.java -- DH key-pair generator JCE Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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.sig;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.HashMap;
+
+import javax.crypto.spec.DHGenParameterSpec;
+
+import gnu.java.security.Registry;
+import gnu.java.security.jce.sig.KeyPairGeneratorAdapter;
+import gnu.javax.crypto.key.dh.GnuDHKeyPairGenerator;
+
+public class DHKeyPairGeneratorSpi
+ extends KeyPairGeneratorAdapter
+{
+ public DHKeyPairGeneratorSpi()
+ {
+ super(Registry.DH_KPG);
+ }
+
+ public void initialize(int keysize, SecureRandom random)
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(GnuDHKeyPairGenerator.PRIME_SIZE, new Integer(keysize));
+ if (random != null)
+ attributes.put(GnuDHKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+
+ attributes.put(GnuDHKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
+ adaptee.setup(attributes);
+ }
+
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ HashMap attributes = new HashMap();
+ if (params != null)
+ {
+ if (! (params instanceof DHGenParameterSpec))
+ throw new InvalidAlgorithmParameterException("params");
+
+ attributes.put(GnuDHKeyPairGenerator.DH_PARAMETERS, params);
+ }
+
+ if (random != null)
+ attributes.put(GnuDHKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+
+ attributes.put(GnuDHKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
+ adaptee.setup(attributes);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/jce/sig/DHParameters.java b/libjava/classpath/gnu/javax/crypto/jce/sig/DHParameters.java
new file mode 100644
index 00000000000..0357c163d41
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/jce/sig/DHParameters.java
@@ -0,0 +1,220 @@
+/* DHParameters.java -- DH parameters DAO
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.util.DerUtil;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.AlgorithmParametersSpi;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.ArrayList;
+
+import javax.crypto.spec.DHGenParameterSpec;
+import javax.crypto.spec.DHParameterSpec;
+
+/**
+ * A JCE-specific Data Access Object (DAO) for DH parameters.
+ */
+public class DHParameters
+ extends AlgorithmParametersSpi
+{
+ /** The prime public modulus. */
+ private BigInteger p;
+
+ /** The generator. */
+ private BigInteger g;
+
+ /** A prime factor of p-1. */
+ private BigInteger q;
+
+ /** The (private) random exponent's size (in bits). */
+ private int l;
+
+ // default 0-arguments constructor
+
+ protected void engineInit(AlgorithmParameterSpec spec)
+ throws InvalidParameterSpecException
+ {
+ if (! (spec instanceof DHParameterSpec))
+ throw new InvalidParameterSpecException("Wrong AlgorithmParameterSpec type: "
+ + spec.getClass().getName());
+ DHParameterSpec dhSpec = (DHParameterSpec) spec;
+ p = dhSpec.getP();
+ g = dhSpec.getG();
+ l = dhSpec.getL();
+ }
+
+ /**
+ * Decodes the set of DH parameters as per RFC-2459; i.e. the DER-encoded
+ * form of the following ASN.1 construct:
+ *
+ * <pre>
+ * DhParams ::= SEQUENCE {
+ * p INTEGER, -- odd prime, p=jq +1
+ * g INTEGER, -- generator, g
+ * q INTEGER -- factor of p-1
+ * }
+ * </pre>
+ */
+ protected void engineInit(byte[] params) throws IOException
+ {
+ DERReader der = new DERReader(params);
+
+ DERValue derParams = der.read();
+ DerUtil.checkIsConstructed(derParams, "Wrong DH Parameters field");
+
+ DERValue val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong P field");
+ p = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong G field");
+ g = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong Q field");
+ q = (BigInteger) val.getValue();
+ l = q.bitLength();
+ }
+
+ protected void engineInit(byte[] params, String format) throws IOException
+ {
+ if (format != null)
+ {
+ format = format.trim();
+ if (format.length() == 0)
+ throw new IOException("Format MUST NOT be an empty string");
+
+ if (! format.equalsIgnoreCase(Registry.ASN1_ENCODING_SHORT_NAME))
+ throw new IOException("Unknown or unsupported format: " + format);
+ }
+
+ engineInit(params);
+ }
+
+ protected AlgorithmParameterSpec engineGetParameterSpec(Class paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (paramSpec.isAssignableFrom(DHParameterSpec.class))
+ return new DHParameterSpec(p, g, l);
+
+ if (paramSpec.isAssignableFrom(DHGenParameterSpec.class))
+ return new DHGenParameterSpec(p.bitLength(), l);
+
+ throw new InvalidParameterSpecException("Wrong AlgorithmParameterSpec type: "
+ + paramSpec.getName());
+ }
+
+ /**
+ * Encodes the set of DH parameters as per RFC-2459; i.e. as the DER-encoded
+ * form of the following ASN.1 construct:
+ *
+ * <pre>
+ * DhParams ::= SEQUENCE {
+ * p INTEGER, -- odd prime, p=jq +1
+ * g INTEGER, -- generator, g
+ * q INTEGER -- factor of p-1
+ * }
+ * </pre>
+ */
+ protected byte[] engineGetEncoded() throws IOException
+ {
+ DERValue derP = new DERValue(DER.INTEGER, p);
+ DERValue derG = new DERValue(DER.INTEGER, g);
+ DERValue derQ = new DERValue(DER.INTEGER, q);
+
+ ArrayList params = new ArrayList(3);
+ params.add(derP);
+ params.add(derG);
+ params.add(derQ);
+ DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DERWriter.write(baos, derParams);
+ byte[] result = baos.toByteArray();
+
+ return result;
+ }
+
+ protected byte[] engineGetEncoded(String format) throws IOException
+ {
+ if (format != null)
+ {
+ format = format.trim();
+ if (format.length() == 0)
+ throw new IOException("Format MUST NOT be an empty string");
+
+ if (! format.equalsIgnoreCase(Registry.ASN1_ENCODING_SHORT_NAME))
+ throw new IOException("Unknown or unsupported format: " + format);
+ }
+
+ return engineGetEncoded();
+ }
+
+ protected String engineToString()
+ {
+ StringBuffer sb = new StringBuffer("p=");
+ if (p == null)
+ sb.append("???");
+ else
+ sb.append("0x").append(p.toString(16));
+
+ sb.append(", g=");
+ if (g == null)
+ sb.append("???");
+ else
+ sb.append("0x").append(g.toString(16));
+
+ sb.append(", q=");
+ if (q == null)
+ sb.append("???");
+ else
+ sb.append("0x").append(q.toString(16));
+
+ sb.append(", l=").append(l);
+
+ return sb.toString();
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/jce/sig/DHParametersGenerator.java b/libjava/classpath/gnu/javax/crypto/jce/sig/DHParametersGenerator.java
new file mode 100644
index 00000000000..3687ac3cac7
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/jce/sig/DHParametersGenerator.java
@@ -0,0 +1,152 @@
+/* DHParametersGenerator.java -- JCE Adapter for a generator of DH parameters
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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.sig;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.jce.GnuCrypto;
+import gnu.javax.crypto.key.dh.GnuDHKeyPairGenerator;
+import gnu.javax.crypto.key.dh.RFC2631;
+
+import java.math.BigInteger;
+import java.security.AlgorithmParameterGeneratorSpi;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+import javax.crypto.spec.DHGenParameterSpec;
+import javax.crypto.spec.DHParameterSpec;
+
+/**
+ * A JCE Adapter for a generator of DH parameters.
+ */
+public class DHParametersGenerator
+ extends AlgorithmParameterGeneratorSpi
+{
+ private static final Provider GNU_CRYPTO = new GnuCrypto();
+
+ /** Size of the prime (public) modulus in bits. */
+ private int modulusSize = -1;
+
+ /** Size of the prime (private) modulus in bits. */
+ private int exponentSize = -1;
+
+ /** User specified source of randomness. */
+ private SecureRandom rnd;
+
+ /** Our concrete DH parameters generator. */
+ private RFC2631 rfc2631;
+
+
+ protected void engineInit(int size, SecureRandom random)
+ {
+ if ((size % 256) != 0 || size < GnuDHKeyPairGenerator.DEFAULT_PRIME_SIZE)
+ throw new InvalidParameterException("Prime modulus (p) size (in bits) "
+ + "MUST be a multiple of 256, and "
+ + "greater than or equal to 1024");
+ this.modulusSize = size;
+ this.rnd = random;
+ }
+
+ protected void engineInit(AlgorithmParameterSpec spec, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ if (spec instanceof DHParameterSpec)
+ {
+ DHParameterSpec dhSpec = (DHParameterSpec) spec;
+ BigInteger p = dhSpec.getP();
+ int size = p.bitLength();
+ this.engineInit(size, random);
+ }
+ else if (spec instanceof DHGenParameterSpec)
+ {
+ DHGenParameterSpec dhSpec = (DHGenParameterSpec) spec;
+ int size = dhSpec.getPrimeSize();
+ this.engineInit(size, random);
+ exponentSize = dhSpec.getExponentSize();
+
+ if ((exponentSize % 8) != 0
+ || exponentSize < GnuDHKeyPairGenerator.DEFAULT_EXPONENT_SIZE)
+ throw new InvalidParameterException("Random exponent size (in bits) "
+ + "MUST be a multiple of 8, and "
+ + "greater than or equal to "
+ + GnuDHKeyPairGenerator.DEFAULT_EXPONENT_SIZE);
+ if (exponentSize > modulusSize)
+ throw new InvalidParameterException("Random exponent size (in bits) "
+ + "MUST be less than that of the "
+ + "public prime modulus (p)");
+ }
+
+ throw new InvalidAlgorithmParameterException("Wrong AlgorithmParameterSpec type: "
+ + spec.getClass().getName());
+ }
+
+ protected AlgorithmParameters engineGenerateParameters()
+ {
+ if (modulusSize < 1)
+ modulusSize = GnuDHKeyPairGenerator.DEFAULT_PRIME_SIZE;
+
+ if (exponentSize < 1)
+ exponentSize = GnuDHKeyPairGenerator.DEFAULT_EXPONENT_SIZE;
+
+ rfc2631 = new RFC2631(exponentSize, modulusSize, rnd);
+ BigInteger[] params = rfc2631.generateParameters();
+ BigInteger p = params[RFC2631.DH_PARAMS_P];
+ BigInteger g = params[RFC2631.DH_PARAMS_G];
+ int l = params[RFC2631.DH_PARAMS_Q].bitLength();
+ DHParameterSpec spec = new DHParameterSpec(p, g, l);
+ AlgorithmParameters result = null;
+ try
+ {
+ result = AlgorithmParameters.getInstance(Registry.DH_KPG, GNU_CRYPTO);
+ result.init(spec);
+ }
+ catch (NoSuchAlgorithmException ignore)
+ {
+ }
+ catch (InvalidParameterSpecException ignore)
+ {
+ }
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java b/libjava/classpath/gnu/javax/crypto/jce/spec/BlockCipherParameterSpec.java
new file mode 100644
index 00000000000..63e7740ec02
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/spec/TMMHParameterSpec.java b/libjava/classpath/gnu/javax/crypto/jce/spec/TMMHParameterSpec.java
new file mode 100644
index 00000000000..0ebec099107
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java b/libjava/classpath/gnu/javax/crypto/jce/spec/UMac32ParameterSpec.java
new file mode 100644
index 00000000000..47d807d4970
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/BaseKeyAgreementParty.java b/libjava/classpath/gnu/javax/crypto/key/BaseKeyAgreementParty.java
new file mode 100644
index 00000000000..bfd9378d2fc
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/BaseKeyAgreementParty.java
@@ -0,0 +1,208 @@
+/* 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 gnu.java.security.util.PRNG;
+
+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;
+
+ /** Our default source of randomness. */
+ private PRNG prng = 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;
+ getDefaultPRNG().nextBytes(buffer);
+ }
+ }
+ else
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/javax/crypto/key/GnuSecretKey.java b/libjava/classpath/gnu/javax/crypto/key/GnuSecretKey.java
new file mode 100644
index 00000000000..93b21a67cc3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/IKeyAgreementParty.java b/libjava/classpath/gnu/javax/crypto/key/IKeyAgreementParty.java
new file mode 100644
index 00000000000..05aef5e51d7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/IncomingMessage.java b/libjava/classpath/gnu/javax/crypto/key/IncomingMessage.java
new file mode 100644
index 00000000000..e04c85399fc
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/IncomingMessage.java
@@ -0,0 +1,356 @@
+/* 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.dss.DSSKeyPairPKCS8Codec;
+import gnu.java.security.key.dss.DSSKeyPairRawCodec;
+import gnu.java.security.key.dss.DSSKeyPairX509Codec;
+import gnu.java.security.key.rsa.RSAKeyPairPKCS8Codec;
+import gnu.java.security.key.rsa.RSAKeyPairRawCodec;
+import gnu.java.security.key.rsa.RSAKeyPairX509Codec;
+import gnu.javax.crypto.key.dh.DHKeyPairPKCS8Codec;
+import gnu.javax.crypto.key.dh.DHKeyPairRawCodec;
+import gnu.javax.crypto.key.dh.DHKeyPairX509Codec;
+import gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec;
+
+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);
+ }
+
+ /**
+ * Decodes a public key from the message.
+ * <p>
+ * See {@link OutgoingMessage#writePublicKey(java.security.PublicKey)} for
+ * more details on the internal format.
+ *
+ * @throws KeyAgreementException if an encoding size constraint is violated or
+ * a mismatch was detected in the encoding.
+ */
+ public PublicKey readPublicKey() throws KeyAgreementException
+ {
+ if (in.available() < 5)
+ 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");
+
+ int keyTypeAndFormatID = in.read() & 0xFF;
+ elementLength--;
+ byte[] kb = new byte[elementLength];
+ in.read(kb, 0, elementLength);
+
+ // instantiate the right codec and decode
+ IKeyPairCodec kpc = getKeyPairCodec(keyTypeAndFormatID);
+ return kpc.decodePublicKey(kb);
+ }
+
+ /**
+ * Decodes a private key from the message.
+ * <p>
+ * See {@link OutgoingMessage#writePrivateKey(java.security.PrivateKey)} for
+ * more details.
+ *
+ * @throws KeyAgreementException if an encoding size constraint is violated or
+ * a mismatch was detected in the encoding.
+ */
+ public PrivateKey readPrivateKey() throws KeyAgreementException
+ {
+ if (in.available() < 5)
+ 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");
+
+ int keyTypeAndFormatID = in.read() & 0xFF;
+ elementLength--;
+ byte[] kb = new byte[elementLength];
+ in.read(kb, 0, elementLength);
+
+ // instantiate the right codec and decode
+ IKeyPairCodec kpc = getKeyPairCodec(keyTypeAndFormatID);
+ 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;
+ }
+
+ private IKeyPairCodec getKeyPairCodec(int keyTypeAndFormatID)
+ throws KeyAgreementException
+ {
+ int keyType = (keyTypeAndFormatID >>> 4) & 0x0F;
+ int formatID = keyTypeAndFormatID & 0x0F;
+ switch (formatID)
+ {
+ case Registry.RAW_ENCODING_ID:
+ switch (keyType)
+ {
+ case 0:
+ return new DSSKeyPairRawCodec();
+ case 1:
+ return new RSAKeyPairRawCodec();
+ case 2:
+ return new DHKeyPairRawCodec();
+ case 3:
+ return new SRPKeyPairRawCodec();
+ default:
+ throw new KeyAgreementException("Unknown key-type for Raw format: "
+ + keyType);
+ }
+ case Registry.X509_ENCODING_ID:
+ switch (keyType)
+ {
+ case 0:
+ return new DSSKeyPairX509Codec();
+ case 1:
+ return new RSAKeyPairX509Codec();
+ case 2:
+ return new DHKeyPairX509Codec();
+ default:
+ throw new KeyAgreementException("Unknown key-type for X.509 format: "
+ + keyType);
+ }
+ case Registry.PKCS8_ENCODING_ID:
+ switch (keyType)
+ {
+ case 0:
+ return new DSSKeyPairPKCS8Codec();
+ case 1:
+ return new RSAKeyPairPKCS8Codec();
+ case 2:
+ return new DHKeyPairPKCS8Codec();
+ default:
+ throw new KeyAgreementException("Unknown key-type for PKCS#8 format: "
+ + keyType);
+ }
+ default:
+ throw new KeyAgreementException("Unknown format identifier: "
+ + formatID);
+ }
+ }
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/javax/crypto/key/KeyAgreementException.java b/libjava/classpath/gnu/javax/crypto/key/KeyAgreementException.java
new file mode 100644
index 00000000000..c2fa434a224
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/KeyAgreementFactory.java b/libjava/classpath/gnu/javax/crypto/key/KeyAgreementFactory.java
new file mode 100644
index 00000000000..e2a7faba18a
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/OutgoingMessage.java b/libjava/classpath/gnu/javax/crypto/key/OutgoingMessage.java
new file mode 100644
index 00000000000..588012120ce
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/OutgoingMessage.java
@@ -0,0 +1,255 @@
+/* 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.dss.DSSKey;
+import gnu.java.security.key.rsa.GnuRSAKey;
+import gnu.java.security.util.FormatUtil;
+import gnu.javax.crypto.key.dh.GnuDHKey;
+import gnu.javax.crypto.key.srp6.SRPKey;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.Key;
+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();
+ }
+
+ /**
+ * Encodes a public key into the message.
+ * <p>
+ * When a public key is encoded into an outgoing message, the byte array of
+ * the encoded key --according to its encoding/decoding format specified when
+ * the key was first instantiated-- are put in the message (a) preceeded by
+ * one byte representing both the type of key (upper 4-bit) and the identifier
+ * of the format used (lower 4-bit), and (b) preceeed by a 4-byte entity
+ * representing the total length, excluding these 4 bytes, of the bytes
+ * representing the encoded key and the one-byte representing the key-type and
+ * format; i.e.
+ *
+ * <pre>
+ * key --&gt; 4-byte-length || 1-byte-type-and-format || encoded-key-bytes
+ * </pre>
+ *
+ * @param k the public key to encode.
+ * @throws KeyAgreementException if an encoding size constraint is violated.
+ */
+ public void writePublicKey(PublicKey k) throws KeyAgreementException
+ {
+ writeKey(k);
+ }
+
+ /**
+ * Encodes a private key into the message.
+ * <p>
+ * When a private key is encoded into an outgoing message, the byte array of
+ * the encoded key --according to its encoding/decoding format specified when
+ * the key was first instantiated-- are put in the message (a) preceeded by
+ * one byte representing both the type of key (upper 4-bit) and the identifier
+ * of the format used (lower 4-bit), and (b) preceeed by a 4-byte entity
+ * representing the total length, excluding these 4 bytes, of the bytes
+ * representing the encoded key and the one-byte representing the key-type and
+ * format; i.e.
+ *
+ * <pre>
+ * key --&gt; 4-byte-length || 1-byte-type-and-format || encoded-key-bytes
+ * </pre>
+ *
+ * @param k the private key to encode.
+ * @throws KeyAgreementException if an encoding size constraint is violated.
+ */
+ public void writePrivateKey(PrivateKey k) throws KeyAgreementException
+ {
+ writeKey(k);
+ }
+
+ /**
+ * <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);
+ }
+
+ /**
+ * @param k the key to encode.
+ * @throws KeyAgreementException if an encoding size constraint is violated.
+ */
+ private void writeKey(Key k) throws KeyAgreementException
+ {
+ byte[] b = k.getEncoded();
+ int keyType = getKeyType(k);
+ int formatID = FormatUtil.getFormatID(k.getFormat());
+ int length = b.length + 1;
+ if (length > Registry.SASL_FOUR_BYTE_MAX_LIMIT)
+ throw new KeyAgreementException("Encoded key is too long");
+
+ byte[] lengthBytes = { (byte) (length >>> 24), (byte) (length >>> 16),
+ (byte) (length >>> 8), (byte) length };
+ out.write(lengthBytes, 0, 4);
+ out.write(((keyType & 0x0F) << 4) | (formatID & 0x0F));
+ out.write(b, 0, b.length);
+ }
+
+ /**
+ * @param k the key to find an identifier for.
+ * @return an integer from <code>0</code> to <code>3</code> identifying
+ * the type of key.
+ * @throws KeyAgreementException if the designated key is of unknown or
+ * unsupported type.
+ */
+ private int getKeyType(Key k) throws KeyAgreementException
+ {
+ if (k instanceof DSSKey)
+ return 0;
+ if (k instanceof GnuRSAKey)
+ return 1;
+ if (k instanceof GnuDHKey)
+ return 2;
+ if (k instanceof SRPKey)
+ return 3;
+ throw new KeyAgreementException("Unknown or unsupported key type: "
+ + k.getClass().getName());
+ }
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairPKCS8Codec.java b/libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairPKCS8Codec.java
new file mode 100644
index 00000000000..34fb007066b
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairPKCS8Codec.java
@@ -0,0 +1,229 @@
+/* DHKeyPairPKCS8Codec.java -- PKCS#8 encoder/decoder for DH keys
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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 java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+
+import gnu.java.security.OID;
+import gnu.java.security.Registry;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.util.DerUtil;
+import gnu.java.security.util.Util;
+
+public class DHKeyPairPKCS8Codec
+ implements IKeyPairCodec
+{
+ private static final OID DH_ALG_OID = new OID(Registry.DH_OID_STRING);
+
+ // implicit 0-arguments constructor
+
+ public int getFormatID()
+ {
+ return PKCS8_FORMAT;
+ }
+
+ /**
+ * @throws InvalidParameterException ALWAYS.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ throw new InvalidParameterException("Wrong format for public keys");
+ }
+
+ /**
+ * Returns the DER-encoded form of the PKCS#8 ASN.1 <i>PrivateKeyInfo</i>
+ * representation of a DH private key. The ASN.1 specification is as follows:
+ *
+ * <pre>
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version INTEGER, -- MUST be 0
+ * privateKeyAlgorithm AlgorithmIdentifier,
+ * privateKey OCTET STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DhParams ::= SEQUENCE {
+ * p INTEGER, -- odd prime, p=jq +1
+ * g INTEGER, -- generator, g
+ * q INTEGER -- factor of p-1
+ * }
+ * </pre>
+ *
+ * @return the DER encoded form of the ASN.1 representation of the
+ * <i>PrivateKeyInfo</i> field in an X.509 certificate.
+ * @throw InvalidParameterException if an error occurs during the marshalling
+ * process.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (! (key instanceof GnuDHPrivateKey))
+ throw new InvalidParameterException("Wrong key type");
+
+ DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DH_ALG_OID);
+
+ GnuDHPrivateKey pk = (GnuDHPrivateKey) key;
+ BigInteger p = pk.getParams().getP();
+ BigInteger g = pk.getParams().getG();
+ BigInteger q = pk.getQ();
+ BigInteger x = pk.getX();
+
+ ArrayList params = new ArrayList(3);
+ params.add(new DERValue(DER.INTEGER, p));
+ params.add(new DERValue(DER.INTEGER, g));
+ params.add(new DERValue(DER.INTEGER, q));
+ DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
+
+ ArrayList algorithmID = new ArrayList(2);
+ algorithmID.add(derOID);
+ algorithmID.add(derParams);
+ DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ algorithmID);
+
+ DERValue derPrivateKey = new DERValue(DER.OCTET_STRING, Util.trim(x));
+
+ ArrayList pki = new ArrayList(3);
+ pki.add(derVersion);
+ pki.add(derAlgorithmID);
+ pki.add(derPrivateKey);
+ DERValue derPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, pki);
+
+ byte[] result;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try
+ {
+ DERWriter.write(baos, derPKI);
+ result = baos.toByteArray();
+ }
+ catch (IOException e)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(e);
+ throw y;
+ }
+
+ return result;
+ }
+
+ /**
+ * @throws InvalidParameterException ALWAYS.
+ */
+ public PublicKey decodePublicKey(byte[] input)
+ {
+ throw new InvalidParameterException("Wrong format for public keys");
+ }
+
+ /**
+ * @param input the byte array to unmarshall into a valid DH
+ * {@link PrivateKey} instance. MUST NOT be null.
+ * @return a new instance of a {@link GnuDHPrivateKey} decoded from the
+ * <i>PrivateKeyInfo</i> material fed as <code>input</code>.
+ * @throw InvalidParameterException if an exception occurs during the
+ * unmarshalling process.
+ */
+ public PrivateKey decodePrivateKey(byte[] input)
+ {
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ BigInteger version, p, q, g, x;
+ DERReader der = new DERReader(input);
+ try
+ {
+ DERValue derPKI = der.read();
+ DerUtil.checkIsConstructed(derPKI, "Wrong PrivateKeyInfo field");
+
+ DERValue derVersion = der.read();
+ if (! (derVersion.getValue() instanceof BigInteger))
+ throw new InvalidParameterException("Wrong Version field");
+
+ version = (BigInteger) derVersion.getValue();
+ if (version.compareTo(BigInteger.ZERO) != 0)
+ throw new InvalidParameterException("Unexpected Version: " + version);
+
+ DERValue derAlgoritmID = der.read();
+ DerUtil.checkIsConstructed(derAlgoritmID, "Wrong AlgorithmIdentifier field");
+
+ DERValue derOID = der.read();
+ OID algOID = (OID) derOID.getValue();
+ if (! algOID.equals(DH_ALG_OID))
+ throw new InvalidParameterException("Unexpected OID: " + algOID);
+
+ DERValue derParams = der.read();
+ DerUtil.checkIsConstructed(derParams, "Wrong DSS Parameters field");
+
+ DERValue val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong P field");
+ p = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong G field");
+ g = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong Q field");
+ q = (BigInteger) val.getValue();
+
+ val = der.read();
+ byte[] xBytes = (byte[]) val.getValue();
+ x = new BigInteger(1, xBytes);
+ }
+ catch (IOException e)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(e);
+ throw y;
+ }
+
+ return new GnuDHPrivateKey(Registry.PKCS8_ENCODING_ID, q, p, g, x);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java b/libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairRawCodec.java
new file mode 100644
index 00000000000..c0ff82bea52
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairX509Codec.java b/libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairX509Codec.java
new file mode 100644
index 00000000000..7e8688bd3a4
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/dh/DHKeyPairX509Codec.java
@@ -0,0 +1,244 @@
+/* DHKeyPairX509Codec.java -- X.509 DER encoder/decoder for DH keys
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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 java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+
+import gnu.java.security.OID;
+import gnu.java.security.Registry;
+import gnu.java.security.der.BitString;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.util.DerUtil;
+
+public class DHKeyPairX509Codec
+ implements IKeyPairCodec
+{
+ private static final OID DH_ALG_OID = new OID(Registry.DH_OID_STRING);
+
+ // implicit 0-arguments constructor
+
+ public int getFormatID()
+ {
+ return X509_FORMAT;
+ }
+
+ /**
+ * Returns the DER-encoded form of the X.509 ASN.1 <i>SubjectPublicKeyInfo</i>
+ * representation of a DH public key. The ASN.1 specification, as defined in
+ * RFC-3280, and RFC-2459, is as follows:
+ *
+ * <pre>
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DhParams ::= SEQUENCE {
+ * p INTEGER, -- odd prime, p=jq +1
+ * g INTEGER, -- generator, g
+ * q INTEGER -- factor of p-1
+ * }
+ * </pre>
+ *
+ * <p>The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
+ * DER-encoded form of the DH public key as an INTEGER.</p>
+ *
+ * <pre>
+ * DHPublicKey ::= INTEGER -- public key, y = g^x mod p
+ * </pre>
+ *
+ * @param key the {@link PublicKey} instance to encode. MUST be an instance of
+ * {@link GnuDHPublicKey}.
+ * @return the DER-encoded form of the ASN.1 representation of the
+ * <i>SubjectPublicKeyInfo</i> in an X.509 certificate.
+ * @throw InvalidParameterException if <code>key</code> is not an instance
+ * of {@link GnuDHPublicKey} or if an exception occurs during the
+ * marshalling process.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (! (key instanceof GnuDHPublicKey))
+ throw new InvalidParameterException("Wrong key type");
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DH_ALG_OID);
+
+ GnuDHPublicKey dhKey = (GnuDHPublicKey) key;
+ BigInteger p = dhKey.getParams().getP();
+ BigInteger g = dhKey.getParams().getG();
+ BigInteger q = dhKey.getQ();
+ BigInteger y = dhKey.getY();
+
+ DERValue derP = new DERValue(DER.INTEGER, p);
+ DERValue derG = new DERValue(DER.INTEGER, g);
+ DERValue derQ = new DERValue(DER.INTEGER, q);
+
+ ArrayList params = new ArrayList(3);
+ params.add(derP);
+ params.add(derG);
+ params.add(derQ);
+ DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
+
+ ArrayList algorithmID = new ArrayList(2);
+ algorithmID.add(derOID);
+ algorithmID.add(derParams);
+ DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ algorithmID);
+
+ DERValue derDHPublicKey = new DERValue(DER.INTEGER, y);
+ byte[] yBytes = derDHPublicKey.getEncoded();
+ DERValue derSPK = new DERValue(DER.BIT_STRING, new BitString(yBytes));
+
+ ArrayList spki = new ArrayList(2);
+ spki.add(derAlgorithmID);
+ spki.add(derSPK);
+ DERValue derSPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, spki);
+
+ byte[] result;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try
+ {
+ DERWriter.write(baos, derSPKI);
+ result = baos.toByteArray();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException e = new InvalidParameterException();
+ e.initCause(x);
+ throw e;
+ }
+
+ return result;
+ }
+
+ /**
+ * @throws InvalidParameterException ALWAYS.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ throw new InvalidParameterException("Wrong format for private keys");
+ }
+
+ /**
+ * @param input the byte array to unmarshall into a valid DH
+ * {@link PublicKey} instance. MUST NOT be null.
+ * @return a new instance of a {@link GnuDHPublicKey} decoded from the
+ * <i>SubjectPublicKeyInfo</i> material in an X.509 certificate.
+ * @throw InvalidParameterException if an exception occurs during the
+ * unmarshalling process.
+ */
+ public PublicKey decodePublicKey(byte[] input)
+ {
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ BigInteger p, g, q, y;
+ DERReader der = new DERReader(input);
+ try
+ {
+ DERValue derSPKI = der.read();
+ DerUtil.checkIsConstructed(derSPKI, "Wrong SubjectPublicKeyInfo field");
+
+ DERValue derAlgorithmID = der.read();
+ DerUtil.checkIsConstructed(derAlgorithmID, "Wrong AlgorithmIdentifier field");
+
+ DERValue derOID = der.read();
+ if (! (derOID.getValue() instanceof OID))
+ throw new InvalidParameterException("Wrong Algorithm field");
+
+ OID algOID = (OID) derOID.getValue();
+ if (! algOID.equals(DH_ALG_OID))
+ throw new InvalidParameterException("Unexpected OID: " + algOID);
+
+ DERValue derParams = der.read();
+ DerUtil.checkIsConstructed(derParams, "Wrong DH Parameters field");
+
+ DERValue val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong P field");
+ p = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong G field");
+ g = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong Q field");
+ q = (BigInteger) val.getValue();
+
+ val = der.read();
+ if (! (val.getValue() instanceof BitString))
+ throw new InvalidParameterException("Wrong SubjectPublicKey field");
+
+ byte[] yBytes = ((BitString) val.getValue()).toByteArray();
+
+ DERReader dhPub = new DERReader(yBytes);
+ val = dhPub.read();
+ DerUtil.checkIsBigInteger(val, "Wrong Y field");
+ y = (BigInteger) val.getValue();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException e = new InvalidParameterException();
+ e.initCause(x);
+ throw e;
+ }
+
+ return new GnuDHPublicKey(Registry.X509_ENCODING_ID, q, p, g, y);
+ }
+
+ /**
+ * @throws InvalidParameterException ALWAYS.
+ */
+ public PrivateKey decodePrivateKey(byte[] input)
+ {
+ throw new InvalidParameterException("Wrong format for private keys");
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java b/libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanKeyAgreement.java
new file mode 100644
index 00000000000..5b1caa7d1b5
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java b/libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanReceiver.java
new file mode 100644
index 00000000000..4a3664d6a8d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanSender.java b/libjava/classpath/gnu/javax/crypto/key/dh/DiffieHellmanSender.java
new file mode 100644
index 00000000000..6b9cf70b67c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java b/libjava/classpath/gnu/javax/crypto/key/dh/ElGamalKeyAgreement.java
new file mode 100644
index 00000000000..1c4e11ce26b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/dh/ElGamalReceiver.java b/libjava/classpath/gnu/javax/crypto/key/dh/ElGamalReceiver.java
new file mode 100644
index 00000000000..24776cba174
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/dh/ElGamalSender.java b/libjava/classpath/gnu/javax/crypto/key/dh/ElGamalSender.java
new file mode 100644
index 00000000000..a2de80a6766
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHKey.java b/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHKey.java
new file mode 100644
index 00000000000..f1e42d93a3e
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHKey.java
@@ -0,0 +1,184 @@
+/* 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 gnu.java.security.util.FormatUtil;
+
+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;
+
+ /**
+ * Identifier of the default encoding format to use when externalizing the
+ * key material.
+ */
+ protected final int defaultFormat;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial protected constructor.
+ *
+ * @param defaultFormat the identifier of the encoding format to use by
+ * default when externalizing the key.
+ * @param q a prime divisor of p-1.
+ * @param p the public prime.
+ * @param g the generator of the group.
+ */
+ protected GnuDHKey(int defaultFormat, BigInteger q, BigInteger p, BigInteger g)
+ {
+ super();
+
+ this.defaultFormat = defaultFormat <= 0 ? Registry.RAW_ENCODING_ID
+ : defaultFormat;
+ 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;
+ }
+
+ /** @deprecated see getEncoded(int). */
+ public byte[] getEncoded()
+ {
+ return getEncoded(defaultFormat);
+ }
+
+ public String getFormat()
+ {
+ return FormatUtil.getEncodingShortName(defaultFormat);
+ }
+
+ // 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());
+ }
+
+ // abstract methods to be implemented by subclasses ------------------------
+
+ public abstract byte[] getEncoded(int format);
+}
diff --git a/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java b/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java
new file mode 100644
index 00000000000..eafc8d01c1f
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java
@@ -0,0 +1,290 @@
+/* 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 gnu.java.security.util.PRNG;
+
+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;
+import javax.crypto.spec.DHParameterSpec;
+
+/**
+ * <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} or
+ * {@link DHParameterSpec} 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";
+
+ /**
+ * Property name of the preferred encoding format to use when externalizing
+ * generated instance of key-pairs from this generator. The property is taken
+ * to be an {@link Integer} that encapsulates an encoding format identifier.
+ */
+ public static final String PREFERRED_ENCODING_FORMAT = "gnu.crypto.dh.encoding";
+
+ /** Default value for the size in bits of the public prime (p). */
+ // private static final int DEFAULT_PRIME_SIZE = 1024;
+ public static final int DEFAULT_PRIME_SIZE = 512;
+
+ /** Default value for the size in bits of the private exponent (x). */
+ public static final int DEFAULT_EXPONENT_SIZE = 160;
+
+ /** Default encoding format to use when none was specified. */
+ private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
+
+ /** 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;
+
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
+ /** Preferred encoding format of generated keys. */
+ private int preferredFormat;
+
+ // 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?
+ Object params = attributes.get(DH_PARAMETERS);
+
+ // find out the desired sizes
+ if (params instanceof DHGenParameterSpec)
+ {
+ DHGenParameterSpec jceSpec = (DHGenParameterSpec) params;
+ l = jceSpec.getPrimeSize();
+ m = jceSpec.getExponentSize();
+ }
+ else if (params instanceof DHParameterSpec)
+ {
+ DHParameterSpec jceSpec = (DHParameterSpec) params;
+ l = jceSpec.getP().bitLength();
+ m = jceSpec.getL();
+ }
+ 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");
+ }
+
+ // what is the preferred encoding format
+ Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
+ preferredFormat = formatID == null ? DEFAULT_ENCODING_FORMAT
+ : formatID.intValue();
+ }
+
+ 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(preferredFormat, q, p, g, x);
+ PublicKey pubK = new GnuDHPublicKey(preferredFormat, 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
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java b/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java
new file mode 100644
index 00000000000..0e71623b9f7
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java
@@ -0,0 +1,196 @@
+/* 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)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Convenience constructor. Calls the constructor with five arguments passing
+ * {@link Registry#RAW_ENCODING_ID} as the value of its first argument.
+ *
+ * @param q a prime divisor of p-1.
+ * @param p the public prime.
+ * @param g the generator of the group.
+ * @param x the private value x.
+ */
+ public GnuDHPrivateKey(BigInteger q, BigInteger p, BigInteger g, BigInteger x)
+ {
+ this(Registry.RAW_ENCODING_ID, q, p, g, x);
+ }
+
+ /**
+ * Constructs a new instance of <code>GnuDHPrivateKey</code> given the
+ * designated parameters.
+ *
+ * @param preferredFormat the identifier of the encoding format to use by
+ * default when externalizing the key.
+ * @param q a prime divisor of p-1.
+ * @param p the public prime.
+ * @param g the generator of the group.
+ * @param x the private value x.
+ */
+ public GnuDHPrivateKey(int preferredFormat,
+ BigInteger q, BigInteger p, BigInteger g, BigInteger x)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
+ : preferredFormat,
+ 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)
+ {
+ // try RAW codec
+ if (k[0] == Registry.MAGIC_RAW_DH_PRIVATE_KEY[0])
+ try
+ {
+ return (GnuDHPrivateKey) new DHKeyPairRawCodec().decodePrivateKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try PKCS#8 codec
+ return (GnuDHPrivateKey) new DHKeyPairPKCS8Codec().decodePrivateKey(k);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // 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;
+ case IKeyPairCodec.PKCS8_FORMAT:
+ result = new DHKeyPairPKCS8Codec().encodePrivateKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
+ }
+ return result;
+ }
+
+ /**
+ * Returns <code>true</code> if the designated object is an instance of
+ * {@link DHPrivateKey} and has the same parameter values as this one.
+ *
+ * @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 DHPrivateKey))
+ return false;
+
+ DHPrivateKey that = (DHPrivateKey) obj;
+ return super.equals(that) && x.equals(that.getX());
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHPublicKey.java b/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHPublicKey.java
new file mode 100644
index 00000000000..56516c9d0ea
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/dh/GnuDHPublicKey.java
@@ -0,0 +1,194 @@
+/* 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)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Convenience constructor. Calls the constructor with five arguments passing
+ * {@link Registry#RAW_ENCODING_ID} as the value of its first argument.
+ *
+ * @param q a prime divisor of p-1.
+ * @param p the public prime.
+ * @param g the generator of the group.
+ * @param y the public value y.
+ */
+ public GnuDHPublicKey(BigInteger q, BigInteger p, BigInteger g, BigInteger y)
+ {
+ this(Registry.RAW_ENCODING_ID, q, p, g, y);
+ }
+
+ /**
+ * Constructs a new instance of <code>GnuDHPublicKey</code> given the
+ * designated parameters.
+ *
+ * @param preferredFormat the identifier of the encoding format to use by
+ * default when externalizing the key.
+ * @param q a prime divisor of p-1.
+ * @param p the public prime.
+ * @param g the generator of the group.
+ * @param y the public value y.
+ */
+ public GnuDHPublicKey(int preferredFormat,
+ BigInteger q, BigInteger p, BigInteger g, BigInteger y)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
+ : preferredFormat,
+ 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)
+ {
+ // try RAW codec
+ if (k[0] == Registry.MAGIC_RAW_DH_PUBLIC_KEY[0])
+ try
+ {
+ return (GnuDHPublicKey) new DHKeyPairRawCodec().decodePublicKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try X.509 codec
+ return (GnuDHPublicKey) new DHKeyPairX509Codec().decodePublicKey(k);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // 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.
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new DHKeyPairRawCodec().encodePublicKey(this);
+ break;
+ case IKeyPairCodec.X509_FORMAT:
+ result = new DHKeyPairX509Codec().encodePublicKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
+ }
+ return result;
+ }
+
+ /**
+ * Returns <code>true</code> if the designated object is an instance of
+ * {@link DHPublicKey} and has the same parameter values as this one.
+ *
+ * @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 DHPublicKey))
+ return false;
+
+ DHPublicKey that = (DHPublicKey) obj;
+ return super.equals(that) && y.equals(that.getY());
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/key/dh/RFC2631.java b/libjava/classpath/gnu/javax/crypto/key/dh/RFC2631.java
new file mode 100644
index 00000000000..d6e30b4bc52
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/dh/RFC2631.java
@@ -0,0 +1,255 @@
+/* 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.PRNG;
+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;
+
+ /** Our default source of randomness. */
+ private PRNG prng = 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
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6Host.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6Host.java
new file mode 100644
index 00000000000..192e877b7ed
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java
new file mode 100644
index 00000000000..63c981d80ef
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslClient.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslClient.java
new file mode 100644
index 00000000000..ef460b13bc7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslServer.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslServer.java
new file mode 100644
index 00000000000..5e759964e08
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSClient.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSClient.java
new file mode 100644
index 00000000000..5474a1e8eb9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSServer.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSServer.java
new file mode 100644
index 00000000000..23e4440773b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6User.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6User.java
new file mode 100644
index 00000000000..d300d6f7664
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRPAlgorithm.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPAlgorithm.java
new file mode 100644
index 00000000000..b068863ed0a
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKey.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKey.java
new file mode 100644
index 00000000000..202ef33b7e2
--- /dev/null
+++ b/libjava/classpath/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);
+ }
+
+ /**
+ * Returns {@link Registry#RAW_ENCODING_SHORT_NAME} which is the sole format
+ * supported for this type of keys.
+ *
+ * @return {@link Registry#RAW_ENCODING_SHORT_NAME} ALWAYS.
+ */
+ public String getFormat()
+ {
+ return Registry.RAW_ENCODING_SHORT_NAME;
+ }
+
+ // 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/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java
new file mode 100644
index 00000000000..2957fc3c855
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java
@@ -0,0 +1,351 @@
+/* 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.PRNG;
+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;
+
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
+ // 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
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java
new file mode 100644
index 00000000000..39234b6271f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPrivateKey.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPrivateKey.java
new file mode 100644
index 00000000000..d9f7a19a6cf
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPublicKey.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPublicKey.java
new file mode 100644
index 00000000000..7283fd3dae2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/AuthenticatedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/AuthenticatedEntry.java
new file mode 100644
index 00000000000..22b42b3ea0b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/BaseKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/BaseKeyring.java
new file mode 100644
index 00000000000..5fe7dbf4deb
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/BinaryDataEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/BinaryDataEntry.java
new file mode 100644
index 00000000000..2dcd5454fb6
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/CertPathEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/CertPathEntry.java
new file mode 100644
index 00000000000..ef62347ec9d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/CertificateEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/CertificateEntry.java
new file mode 100644
index 00000000000..95a708ac53f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/CompressedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/CompressedEntry.java
new file mode 100644
index 00000000000..cce930d739d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/EncryptedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/EncryptedEntry.java
new file mode 100644
index 00000000000..fad5f54b236
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/Entry.java b/libjava/classpath/gnu/javax/crypto/keyring/Entry.java
new file mode 100644
index 00000000000..fa7f496798b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/EnvelopeEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/EnvelopeEntry.java
new file mode 100644
index 00000000000..25b1dc2a04d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/GnuPrivateKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/GnuPrivateKeyring.java
new file mode 100644
index 00000000000..d49bd09636d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/GnuPublicKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/GnuPublicKeyring.java
new file mode 100644
index 00000000000..318eb036fc8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/IKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/IKeyring.java
new file mode 100644
index 00000000000..56f467df26e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/IPrivateKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/IPrivateKeyring.java
new file mode 100644
index 00000000000..66bbd84f568
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/IPublicKeyring.java b/libjava/classpath/gnu/javax/crypto/keyring/IPublicKeyring.java
new file mode 100644
index 00000000000..ccf9ca73b55
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/MalformedKeyringException.java b/libjava/classpath/gnu/javax/crypto/keyring/MalformedKeyringException.java
new file mode 100644
index 00000000000..44c953946d4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/MaskableEnvelopeEntry.java
new file mode 100644
index 00000000000..7fed7c40c15
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/MeteredInputStream.java b/libjava/classpath/gnu/javax/crypto/keyring/MeteredInputStream.java
new file mode 100644
index 00000000000..fcf2be746c9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PasswordAuthenticatedEntry.java
new file mode 100644
index 00000000000..2e3a0d145c8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PasswordEncryptedEntry.java
new file mode 100644
index 00000000000..26b4032bdfb
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/PasswordProtectedEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PasswordProtectedEntry.java
new file mode 100644
index 00000000000..0dcf73eb8d2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/PrimitiveEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PrimitiveEntry.java
new file mode 100644
index 00000000000..4c9ff0ff1d9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/PrivateKeyEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PrivateKeyEntry.java
new file mode 100644
index 00000000000..30634991570
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/Properties.java b/libjava/classpath/gnu/javax/crypto/keyring/Properties.java
new file mode 100644
index 00000000000..646b5711df2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/keyring/PublicKeyEntry.java b/libjava/classpath/gnu/javax/crypto/keyring/PublicKeyEntry.java
new file mode 100644
index 00000000000..528e70cc648
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mac/BaseMac.java b/libjava/classpath/gnu/javax/crypto/mac/BaseMac.java
new file mode 100644
index 00000000000..1b42a1644c9
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/mac/BaseMac.java
@@ -0,0 +1,148 @@
+/* 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
+ {
+ BaseMac result = (BaseMac) super.clone();
+ if (this.underlyingHash != null)
+ result.underlyingHash = (IMessageDigest) this.underlyingHash.clone();
+
+ return result;
+ }
+
+ // 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/libjava/classpath/gnu/javax/crypto/mac/HMac.java b/libjava/classpath/gnu/javax/crypto/mac/HMac.java
new file mode 100644
index 00000000000..c1f97b54195
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/mac/HMac.java
@@ -0,0 +1,328 @@
+/* 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
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ HMac result = (HMac) super.clone();
+ if (this.ipadHash != null)
+ result.ipadHash = (IMessageDigest) this.ipadHash.clone();
+ if (this.opadHash != null)
+ result.opadHash = (IMessageDigest) this.opadHash.clone();
+ if (this.ipad != null)
+ result.ipad = (byte[]) this.ipad.clone();
+
+ return result;
+ }
+
+ // 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();
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/mac/HMacFactory.java b/libjava/classpath/gnu/javax/crypto/mac/HMacFactory.java
new file mode 100644
index 00000000000..156e6ced5e7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mac/IMac.java b/libjava/classpath/gnu/javax/crypto/mac/IMac.java
new file mode 100644
index 00000000000..c4170c42ce9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mac/MacFactory.java b/libjava/classpath/gnu/javax/crypto/mac/MacFactory.java
new file mode 100644
index 00000000000..d8f8bcfcee6
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mac/MacInputStream.java b/libjava/classpath/gnu/javax/crypto/mac/MacInputStream.java
new file mode 100644
index 00000000000..9acd18b19af
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mac/MacOutputStream.java b/libjava/classpath/gnu/javax/crypto/mac/MacOutputStream.java
new file mode 100644
index 00000000000..a48d25ba3a5
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mac/OMAC.java b/libjava/classpath/gnu/javax/crypto/mac/OMAC.java
new file mode 100644
index 00000000000..c83320a1bc4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mac/TMMH16.java b/libjava/classpath/gnu/javax/crypto/mac/TMMH16.java
new file mode 100644
index 00000000000..af6e78fcf87
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/mac/TMMH16.java
@@ -0,0 +1,402 @@
+/* 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();
+ }
+
+ // Cloneable interface implementation ---------------------------------------
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ TMMH16 result = (TMMH16) super.clone();
+
+ if (this.keystream != null)
+ result.keystream = (IRandom) this.keystream.clone();
+
+ if (this.prefix != null)
+ result.prefix = (byte[]) this.prefix.clone();
+
+ if (this.context != null)
+ result.context = (int[]) this.context.clone();
+
+ if (this.K0 != null)
+ result.K0 = (int[]) this.K0.clone();
+
+ if (this.Ki != null)
+ result.Ki = (int[]) this.Ki.clone();
+
+ return result;
+ }
+
+ // 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;
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/javax/crypto/mac/UHash32.java b/libjava/classpath/gnu/javax/crypto/mac/UHash32.java
new file mode 100644
index 00000000000..8abb0255ed4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mac/UMac32.java b/libjava/classpath/gnu/javax/crypto/mac/UMac32.java
new file mode 100644
index 00000000000..d20d4f4a9fc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/BaseMode.java b/libjava/classpath/gnu/javax/crypto/mode/BaseMode.java
new file mode 100644
index 00000000000..0a9ab2dab1c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/CBC.java b/libjava/classpath/gnu/javax/crypto/mode/CBC.java
new file mode 100644
index 00000000000..10578a6ef50
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/CFB.java b/libjava/classpath/gnu/javax/crypto/mode/CFB.java
new file mode 100644
index 00000000000..fef2b634cf2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/CTR.java b/libjava/classpath/gnu/javax/crypto/mode/CTR.java
new file mode 100644
index 00000000000..49f4b9f3c2a
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/EAX.java b/libjava/classpath/gnu/javax/crypto/mode/EAX.java
new file mode 100644
index 00000000000..bf260989825
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/ECB.java b/libjava/classpath/gnu/javax/crypto/mode/ECB.java
new file mode 100644
index 00000000000..3b33a1848fe
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/IAuthenticatedMode.java b/libjava/classpath/gnu/javax/crypto/mode/IAuthenticatedMode.java
new file mode 100644
index 00000000000..d89c0016d85
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/ICM.java b/libjava/classpath/gnu/javax/crypto/mode/ICM.java
new file mode 100644
index 00000000000..d37908b5dfd
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/IMode.java b/libjava/classpath/gnu/javax/crypto/mode/IMode.java
new file mode 100644
index 00000000000..4cb6ca64bd9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/ModeFactory.java b/libjava/classpath/gnu/javax/crypto/mode/ModeFactory.java
new file mode 100644
index 00000000000..0e949ed9e96
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/mode/OFB.java b/libjava/classpath/gnu/javax/crypto/mode/OFB.java
new file mode 100644
index 00000000000..68065d10b9c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/pad/BasePad.java b/libjava/classpath/gnu/javax/crypto/pad/BasePad.java
new file mode 100644
index 00000000000..49c5d050a85
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/pad/IPad.java b/libjava/classpath/gnu/javax/crypto/pad/IPad.java
new file mode 100644
index 00000000000..4b4c925e622
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/pad/PKCS1_V1_5.java b/libjava/classpath/gnu/javax/crypto/pad/PKCS1_V1_5.java
new file mode 100644
index 00000000000..03c3d61a303
--- /dev/null
+++ b/libjava/classpath/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.PRNG;
+import gnu.java.security.util.Util;
+
+import java.io.PrintWriter;
+
+/**
+ * <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]];
+ PRNG.getInstance().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/libjava/classpath/gnu/javax/crypto/pad/PKCS7.java b/libjava/classpath/gnu/javax/crypto/pad/PKCS7.java
new file mode 100644
index 00000000000..5697aff2712
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/pad/PadFactory.java b/libjava/classpath/gnu/javax/crypto/pad/PadFactory.java
new file mode 100644
index 00000000000..e122719b62b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/pad/SSL3.java b/libjava/classpath/gnu/javax/crypto/pad/SSL3.java
new file mode 100644
index 00000000000..25aeefa13d0
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/pad/TBC.java b/libjava/classpath/gnu/javax/crypto/pad/TBC.java
new file mode 100644
index 00000000000..25c3e4286bc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/pad/TLS1.java b/libjava/classpath/gnu/javax/crypto/pad/TLS1.java
new file mode 100644
index 00000000000..00a538f882a
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/pad/WrongPaddingException.java b/libjava/classpath/gnu/javax/crypto/pad/WrongPaddingException.java
new file mode 100644
index 00000000000..cc74dfb26bf
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/prng/ARCFour.java b/libjava/classpath/gnu/javax/crypto/prng/ARCFour.java
new file mode 100644
index 00000000000..22316ec8b9b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java b/libjava/classpath/gnu/javax/crypto/prng/CSPRNG.java
new file mode 100644
index 00000000000..197009232bc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/prng/Fortuna.java b/libjava/classpath/gnu/javax/crypto/prng/Fortuna.java
new file mode 100644
index 00000000000..6453a9d02d0
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/prng/ICMGenerator.java b/libjava/classpath/gnu/javax/crypto/prng/ICMGenerator.java
new file mode 100644
index 00000000000..0de38e256ea
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/prng/IPBE.java b/libjava/classpath/gnu/javax/crypto/prng/IPBE.java
new file mode 100644
index 00000000000..531e7ead88a
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/prng/PBKDF2.java b/libjava/classpath/gnu/javax/crypto/prng/PBKDF2.java
new file mode 100644
index 00000000000..5146bd4b9ab
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/prng/PRNGFactory.java b/libjava/classpath/gnu/javax/crypto/prng/PRNGFactory.java
new file mode 100644
index 00000000000..9ff6558b0e3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/prng/UMacGenerator.java b/libjava/classpath/gnu/javax/crypto/prng/UMacGenerator.java
new file mode 100644
index 00000000000..0e3725ce986
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/AuthInfo.java b/libjava/classpath/gnu/javax/crypto/sasl/AuthInfo.java
new file mode 100644
index 00000000000..1e942559dcf
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/AuthInfoProviderFactory.java b/libjava/classpath/gnu/javax/crypto/sasl/AuthInfoProviderFactory.java
new file mode 100644
index 00000000000..6ba5fc56296
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/ClientFactory.java b/libjava/classpath/gnu/javax/crypto/sasl/ClientFactory.java
new file mode 100644
index 00000000000..ef184632cc4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/ClientMechanism.java b/libjava/classpath/gnu/javax/crypto/sasl/ClientMechanism.java
new file mode 100644
index 00000000000..45873ae6b27
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/ConfidentialityException.java b/libjava/classpath/gnu/javax/crypto/sasl/ConfidentialityException.java
new file mode 100644
index 00000000000..561827d8d04
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/IAuthInfoProvider.java b/libjava/classpath/gnu/javax/crypto/sasl/IAuthInfoProvider.java
new file mode 100644
index 00000000000..2b913a137b8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java b/libjava/classpath/gnu/javax/crypto/sasl/IAuthInfoProviderFactory.java
new file mode 100644
index 00000000000..e630b8da14b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/IllegalMechanismStateException.java b/libjava/classpath/gnu/javax/crypto/sasl/IllegalMechanismStateException.java
new file mode 100644
index 00000000000..94d9269a1dc
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/InputBuffer.java b/libjava/classpath/gnu/javax/crypto/sasl/InputBuffer.java
new file mode 100644
index 00000000000..a64ea3e0e65
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/IntegrityException.java b/libjava/classpath/gnu/javax/crypto/sasl/IntegrityException.java
new file mode 100644
index 00000000000..4a56ca2d564
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/NoSuchMechanismException.java b/libjava/classpath/gnu/javax/crypto/sasl/NoSuchMechanismException.java
new file mode 100644
index 00000000000..65432082a4e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/NoSuchUserException.java b/libjava/classpath/gnu/javax/crypto/sasl/NoSuchUserException.java
new file mode 100644
index 00000000000..fe362c74261
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/OutputBuffer.java b/libjava/classpath/gnu/javax/crypto/sasl/OutputBuffer.java
new file mode 100644
index 00000000000..d219e7e9f0e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/SaslEncodingException.java b/libjava/classpath/gnu/javax/crypto/sasl/SaslEncodingException.java
new file mode 100644
index 00000000000..9f4c59f1c2b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/SaslInputStream.java b/libjava/classpath/gnu/javax/crypto/sasl/SaslInputStream.java
new file mode 100644
index 00000000000..57eb2b5c52d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/SaslOutputStream.java b/libjava/classpath/gnu/javax/crypto/sasl/SaslOutputStream.java
new file mode 100644
index 00000000000..6997201377a
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/SaslUtil.java b/libjava/classpath/gnu/javax/crypto/sasl/SaslUtil.java
new file mode 100644
index 00000000000..e70312c0d4d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/ServerFactory.java b/libjava/classpath/gnu/javax/crypto/sasl/ServerFactory.java
new file mode 100644
index 00000000000..e9b08dbd49a
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/ServerMechanism.java b/libjava/classpath/gnu/javax/crypto/sasl/ServerMechanism.java
new file mode 100644
index 00000000000..f12a075d949
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/UserAlreadyExistsException.java b/libjava/classpath/gnu/javax/crypto/sasl/UserAlreadyExistsException.java
new file mode 100644
index 00000000000..764a36df30e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousClient.java b/libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousClient.java
new file mode 100644
index 00000000000..f5b1faab299
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousServer.java b/libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousServer.java
new file mode 100644
index 00000000000..2c10f78a78b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java b/libjava/classpath/gnu/javax/crypto/sasl/anonymous/AnonymousUtil.java
new file mode 100644
index 00000000000..99e95eaeca0
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java b/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5AuthInfoProvider.java
new file mode 100644
index 00000000000..cf73b6f982f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Client.java b/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Client.java
new file mode 100644
index 00000000000..094109ff9aa
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java b/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Registry.java
new file mode 100644
index 00000000000..1c61cace491
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Server.java b/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Server.java
new file mode 100644
index 00000000000..d6622b6db4e
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Util.java b/libjava/classpath/gnu/javax/crypto/sasl/crammd5/CramMD5Util.java
new file mode 100644
index 00000000000..6e753934933
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/crammd5/PasswordFile.java b/libjava/classpath/gnu/javax/crypto/sasl/crammd5/PasswordFile.java
new file mode 100644
index 00000000000..081af461521
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/plain/PasswordFile.java b/libjava/classpath/gnu/javax/crypto/sasl/plain/PasswordFile.java
new file mode 100644
index 00000000000..4ef6b8541b1
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java b/libjava/classpath/gnu/javax/crypto/sasl/plain/PlainAuthInfoProvider.java
new file mode 100644
index 00000000000..9882ce9bb48
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/plain/PlainClient.java b/libjava/classpath/gnu/javax/crypto/sasl/plain/PlainClient.java
new file mode 100644
index 00000000000..066db377054
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/plain/PlainRegistry.java b/libjava/classpath/gnu/javax/crypto/sasl/plain/PlainRegistry.java
new file mode 100644
index 00000000000..0b48c0ad30d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/plain/PlainServer.java b/libjava/classpath/gnu/javax/crypto/sasl/plain/PlainServer.java
new file mode 100644
index 00000000000..20568847303
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/CALG.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/CALG.java
new file mode 100644
index 00000000000..6215783d6a9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/ClientStore.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/ClientStore.java
new file mode 100644
index 00000000000..ce16f4aa75d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/IALG.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/IALG.java
new file mode 100644
index 00000000000..cfaf22b1e02
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/KDF.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/KDF.java
new file mode 100644
index 00000000000..0d5eeacd182
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/sasl/srp/KDF.java
@@ -0,0 +1,169 @@
+/* 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.java.security.util.PRNG;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.prng.UMacGenerator;
+
+import java.util.HashMap;
+
+/**
+ * <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
+
+ private static final byte[] buffer = new byte[1];
+
+ /** Our default source of randomness. */
+ private static final PRNG prng = PRNG.getInstance();
+
+ /** 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];
+ while (ndx < 1 || ndx > 255)
+ ndx = (byte) nextByte();
+ }
+ return new KDF(keyMaterial, ndx);
+ }
+
+ private static synchronized final int nextByte()
+ {
+ prng.nextBytes(buffer);
+ return (buffer[0] & 0xFF);
+ }
+
+ // 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/libjava/classpath/gnu/javax/crypto/sasl/srp/PasswordFile.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/PasswordFile.java
new file mode 100644
index 00000000000..1628a4167ab
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/SRP.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/SRP.java
new file mode 100644
index 00000000000..d3eb596d4c3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPAuthInfoProvider.java
new file mode 100644
index 00000000000..9ea21efb6c2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPClient.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPClient.java
new file mode 100644
index 00000000000..1a1664ff79d
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPClient.java
@@ -0,0 +1,1211 @@
+/* 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.PRNG;
+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.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);
+
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
+ // 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 byte[16];
+ getDefaultPRNG().nextBytes(cn);
+ }
+ 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];
+ getDefaultPRNG().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));
+ }
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPRegistry.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPRegistry.java
new file mode 100644
index 00000000000..262cbcba305
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPServer.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPServer.java
new file mode 100644
index 00000000000..11902b82ed8
--- /dev/null
+++ b/libjava/classpath/gnu/javax/crypto/sasl/srp/SRPServer.java
@@ -0,0 +1,1156 @@
+/* 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.PRNG;
+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.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.2 $
+ */
+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);
+
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
+ // 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];
+ }
+ getDefaultPRNG().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)
+ getDefaultPRNG().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));
+ }
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/javax/crypto/sasl/srp/SecurityContext.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/SecurityContext.java
new file mode 100644
index 00000000000..feca25cadb8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/ServerStore.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/ServerStore.java
new file mode 100644
index 00000000000..99bf96a9444
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/sasl/srp/StoreEntry.java b/libjava/classpath/gnu/javax/crypto/sasl/srp/StoreEntry.java
new file mode 100644
index 00000000000..c5041fa4b38
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/Base64.java b/libjava/classpath/gnu/javax/net/ssl/Base64.java
new file mode 100644
index 00000000000..52989da69d3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/EntropySource.java b/libjava/classpath/gnu/javax/net/ssl/EntropySource.java
new file mode 100644
index 00000000000..be840e5d697
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/NullManagerParameters.java b/libjava/classpath/gnu/javax/net/ssl/NullManagerParameters.java
new file mode 100644
index 00000000000..0e933793262
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/PrivateCredentials.java b/libjava/classpath/gnu/javax/net/ssl/PrivateCredentials.java
new file mode 100644
index 00000000000..f602f98ae22
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/SRPManagerParameters.java b/libjava/classpath/gnu/javax/net/ssl/SRPManagerParameters.java
new file mode 100644
index 00000000000..a2a745e1b50
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/SRPTrustManager.java b/libjava/classpath/gnu/javax/net/ssl/SRPTrustManager.java
new file mode 100644
index 00000000000..664fa4cab19
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/StaticTrustAnchors.java b/libjava/classpath/gnu/javax/net/ssl/StaticTrustAnchors.java
new file mode 100644
index 00000000000..0c2c3cca8a8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Alert.java b/libjava/classpath/gnu/javax/net/ssl/provider/Alert.java
new file mode 100644
index 00000000000..c31e1bef5ca
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/AlertException.java b/libjava/classpath/gnu/javax/net/ssl/provider/AlertException.java
new file mode 100644
index 00000000000..666efe5ac0d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Certificate.java b/libjava/classpath/gnu/javax/net/ssl/provider/Certificate.java
new file mode 100644
index 00000000000..b1d6b2a0143
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/CertificateRequest.java b/libjava/classpath/gnu/javax/net/ssl/provider/CertificateRequest.java
new file mode 100644
index 00000000000..0f788039b0b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/CertificateType.java b/libjava/classpath/gnu/javax/net/ssl/provider/CertificateType.java
new file mode 100644
index 00000000000..c5705939f74
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/CertificateVerify.java b/libjava/classpath/gnu/javax/net/ssl/provider/CertificateVerify.java
new file mode 100644
index 00000000000..e0bf130f189
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/CipherSuite.java b/libjava/classpath/gnu/javax/net/ssl/provider/CipherSuite.java
new file mode 100644
index 00000000000..de916817b92
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/ClientHello.java b/libjava/classpath/gnu/javax/net/ssl/provider/ClientHello.java
new file mode 100644
index 00000000000..259051df129
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/ClientKeyExchange.java b/libjava/classpath/gnu/javax/net/ssl/provider/ClientKeyExchange.java
new file mode 100644
index 00000000000..828aa8d5e93
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/CompressionMethod.java b/libjava/classpath/gnu/javax/net/ssl/provider/CompressionMethod.java
new file mode 100644
index 00000000000..c2fdf05f9a3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Constructed.java b/libjava/classpath/gnu/javax/net/ssl/provider/Constructed.java
new file mode 100644
index 00000000000..ee3f56a7f47
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/ContentType.java b/libjava/classpath/gnu/javax/net/ssl/provider/ContentType.java
new file mode 100644
index 00000000000..336809467e4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Context.java b/libjava/classpath/gnu/javax/net/ssl/provider/Context.java
new file mode 100644
index 00000000000..2bd7193f265
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/DiffieHellman.java b/libjava/classpath/gnu/javax/net/ssl/provider/DiffieHellman.java
new file mode 100644
index 00000000000..ad48c795906
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/DigestInputStream.java b/libjava/classpath/gnu/javax/net/ssl/provider/DigestInputStream.java
new file mode 100644
index 00000000000..dd138b436a1
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/DigestOutputStream.java b/libjava/classpath/gnu/javax/net/ssl/provider/DigestOutputStream.java
new file mode 100644
index 00000000000..f1548459e8c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Enumerated.java b/libjava/classpath/gnu/javax/net/ssl/provider/Enumerated.java
new file mode 100644
index 00000000000..8875addab3f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Extension.java b/libjava/classpath/gnu/javax/net/ssl/provider/Extension.java
new file mode 100644
index 00000000000..1c79dd5cb26
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Extensions.java b/libjava/classpath/gnu/javax/net/ssl/provider/Extensions.java
new file mode 100644
index 00000000000..9ed9619f06f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Finished.java b/libjava/classpath/gnu/javax/net/ssl/provider/Finished.java
new file mode 100644
index 00000000000..8b9c220a527
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/GNUSecurityParameters.java b/libjava/classpath/gnu/javax/net/ssl/provider/GNUSecurityParameters.java
new file mode 100644
index 00000000000..a04c3fd5c15
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Handshake.java b/libjava/classpath/gnu/javax/net/ssl/provider/Handshake.java
new file mode 100644
index 00000000000..ef9e72381c1
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/JCESecurityParameters.java b/libjava/classpath/gnu/javax/net/ssl/provider/JCESecurityParameters.java
new file mode 100644
index 00000000000..6663c97b59d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/JDBCSessionContext.java b/libjava/classpath/gnu/javax/net/ssl/provider/JDBCSessionContext.java
new file mode 100644
index 00000000000..2b9b1403425
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Jessie.java b/libjava/classpath/gnu/javax/net/ssl/provider/Jessie.java
new file mode 100644
index 00000000000..14b671d0230
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/crypto/GnuDHPrivateKey.java b/libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java
index f70cd7d2aec..1997458dd24 100644
--- a/libjava/classpath/gnu/javax/crypto/GnuDHPrivateKey.java
+++ b/libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java
@@ -1,12 +1,12 @@
-/* GnuDHPrivateKey.java -- a Diffie-Hellman private key.
- Copyright (C) 2005 Free Software Foundation, Inc.
+/* JessieDHPrivateKey.java -- simple DH private key.
+ Copyright (C) 2006 Free Software Foundation, Inc.
-This file is part of GNU Classpath.
+This file is a part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,9 +14,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
@@ -33,58 +33,67 @@ module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
+exception statement from your version. */
-package gnu.javax.crypto;
+package gnu.javax.net.ssl.provider;
import java.math.BigInteger;
-import javax.crypto.interfaces.DHKey;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.spec.DHParameterSpec;
-/**
- * A Diffie-Hellman private key.
- *
- * @author Casey Marshall (csm@gnu.org)
- */
-public class GnuDHPrivateKey implements DHPrivateKey
+class JessieDHPrivateKey implements DHPrivateKey
{
- private final BigInteger x;
+ // Fields.
+ // -------------------------------------------------------------------------
+
private final DHParameterSpec params;
+ private final BigInteger x;
- public GnuDHPrivateKey (final BigInteger x, final DHParameterSpec params)
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ JessieDHPrivateKey(DHParameterSpec params, BigInteger x)
{
- x.getClass ();
- params.getClass ();
- this.x = x;
this.params = params;
+ this.x = x;
}
- public DHParameterSpec getParams()
- {
- return params;
- }
+ // Instance methods.
+ // -------------------------------------------------------------------------
public String getAlgorithm()
{
- return "DiffieHellman";
+ return "Diffie-Hellman";
}
- public String getFormat ()
+ public String getFormat()
{
return "NONE";
}
- public byte[] getEncoded ()
+ public byte[] getEncoded()
{
return null;
}
- public BigInteger getX ()
+ 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/libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPublicKey.java b/libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPublicKey.java
new file mode 100644
index 00000000000..dc6587288e6
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java b/libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java
new file mode 100644
index 00000000000..4ec71a7aad3
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java b/libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java
new file mode 100644
index 00000000000..19921d98c67
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/KeyPool.java b/libjava/classpath/gnu/javax/net/ssl/provider/KeyPool.java
new file mode 100644
index 00000000000..e342700c269
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/MacException.java b/libjava/classpath/gnu/javax/net/ssl/provider/MacException.java
new file mode 100644
index 00000000000..b8c479fdbe7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/OverflowException.java b/libjava/classpath/gnu/javax/net/ssl/provider/OverflowException.java
new file mode 100644
index 00000000000..93bdcaec5ed
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/ProtocolVersion.java b/libjava/classpath/gnu/javax/net/ssl/provider/ProtocolVersion.java
new file mode 100644
index 00000000000..5f5d1d979aa
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Random.java b/libjava/classpath/gnu/javax/net/ssl/provider/Random.java
new file mode 100644
index 00000000000..c42592b147b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/RecordInput.java b/libjava/classpath/gnu/javax/net/ssl/provider/RecordInput.java
new file mode 100644
index 00000000000..d4ba5b596d6
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/RecordInputStream.java b/libjava/classpath/gnu/javax/net/ssl/provider/RecordInputStream.java
new file mode 100644
index 00000000000..14cf829ac67
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/RecordOutputStream.java b/libjava/classpath/gnu/javax/net/ssl/provider/RecordOutputStream.java
new file mode 100644
index 00000000000..3bf228f2d69
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/RecordingInputStream.java b/libjava/classpath/gnu/javax/net/ssl/provider/RecordingInputStream.java
new file mode 100644
index 00000000000..d81b652d516
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java b/libjava/classpath/gnu/javax/net/ssl/provider/SRPTrustManagerFactory.java
new file mode 100644
index 00000000000..5822afe0596
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLHMac.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLHMac.java
new file mode 100644
index 00000000000..002b3077fcb
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLRSASignature.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLRSASignature.java
new file mode 100644
index 00000000000..2f8c6cfe665
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLRandom.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLRandom.java
new file mode 100644
index 00000000000..0b28f1044a7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLServerSocket.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLServerSocket.java
new file mode 100644
index 00000000000..ee96b8d1bdf
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java
new file mode 100644
index 00000000000..72fb512c582
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLSocket.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLSocket.java
new file mode 100644
index 00000000000..a564659c02c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketFactory.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketFactory.java
new file mode 100644
index 00000000000..24a8389c117
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketInputStream.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketInputStream.java
new file mode 100644
index 00000000000..69202ca33d8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java b/libjava/classpath/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java
new file mode 100644
index 00000000000..fe769a85fba
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SecurityParameters.java b/libjava/classpath/gnu/javax/net/ssl/provider/SecurityParameters.java
new file mode 100644
index 00000000000..aa06680e200
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/ServerHello.java b/libjava/classpath/gnu/javax/net/ssl/provider/ServerHello.java
new file mode 100644
index 00000000000..8b7853c7f40
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/ServerKeyExchange.java b/libjava/classpath/gnu/javax/net/ssl/provider/ServerKeyExchange.java
new file mode 100644
index 00000000000..58304159300
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Session.java b/libjava/classpath/gnu/javax/net/ssl/provider/Session.java
new file mode 100644
index 00000000000..e13758b0330
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SessionContext.java b/libjava/classpath/gnu/javax/net/ssl/provider/SessionContext.java
new file mode 100644
index 00000000000..9e265429aab
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Signature.java b/libjava/classpath/gnu/javax/net/ssl/provider/Signature.java
new file mode 100644
index 00000000000..c9be641431f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/SynchronizedRandom.java b/libjava/classpath/gnu/javax/net/ssl/provider/SynchronizedRandom.java
new file mode 100644
index 00000000000..4e22f08be08
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/TLSHMac.java b/libjava/classpath/gnu/javax/net/ssl/provider/TLSHMac.java
new file mode 100644
index 00000000000..18aa8f5f4c7
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/TLSRandom.java b/libjava/classpath/gnu/javax/net/ssl/provider/TLSRandom.java
new file mode 100644
index 00000000000..ded632928f1
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/Util.java b/libjava/classpath/gnu/javax/net/ssl/provider/Util.java
new file mode 100644
index 00000000000..15790dd26f8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java b/libjava/classpath/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java
new file mode 100644
index 00000000000..476655c45da
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java b/libjava/classpath/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java
new file mode 100644
index 00000000000..4f049e916d9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/net/ssl/provider/XMLSessionContext.java b/libjava/classpath/gnu/javax/net/ssl/provider/XMLSessionContext.java
new file mode 100644
index 00000000000..dcfa9d4adc9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/security/auth/Password.java b/libjava/classpath/gnu/javax/security/auth/Password.java
new file mode 100644
index 00000000000..7284b7d6823
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/security/auth/callback/AWTCallbackHandler.java b/libjava/classpath/gnu/javax/security/auth/callback/AWTCallbackHandler.java
new file mode 100644
index 00000000000..539c4a17e1c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/security/auth/callback/AbstractCallbackHandler.java b/libjava/classpath/gnu/javax/security/auth/callback/AbstractCallbackHandler.java
new file mode 100644
index 00000000000..eeedf2605db
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/security/auth/callback/ConsoleCallbackHandler.java b/libjava/classpath/gnu/javax/security/auth/callback/ConsoleCallbackHandler.java
new file mode 100644
index 00000000000..4ce22cb3033
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/security/auth/callback/DefaultCallbackHandler.java b/libjava/classpath/gnu/javax/security/auth/callback/DefaultCallbackHandler.java
new file mode 100644
index 00000000000..fc48782fe47
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/security/auth/callback/GnuCallbacks.java b/libjava/classpath/gnu/javax/security/auth/callback/GnuCallbacks.java
new file mode 100644
index 00000000000..9fd72f92682
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/security/auth/callback/SwingCallbackHandler.java b/libjava/classpath/gnu/javax/security/auth/callback/SwingCallbackHandler.java
new file mode 100644
index 00000000000..8e3e46eff73
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/gnu/javax/security/auth/login/ConfigFileParser.java b/libjava/classpath/gnu/javax/security/auth/login/ConfigFileParser.java
new file mode 100644
index 00000000000..f6c39bb3d7b
--- /dev/null
+++ b/libjava/classpath/gnu/javax/security/auth/login/ConfigFileParser.java
@@ -0,0 +1,338 @@
+/* ConfigFileParser.java -- JAAS Login Configuration default syntax parser
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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.login;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.login.AppConfigurationEntry;
+
+/**
+ * A parser that knows how to interpret JAAS Login Module Configuration files
+ * written in the <i>default syntax</i> which is interpreted as adhering to
+ * the following grammar:
+ *
+ * <pre>
+ * CONFIG ::= APP_OR_OTHER_ENTRY+
+ * APP_OR_OTHER_ENTRY ::= APP_NAME_OR_OTHER JAAS_CONFIG_BLOCK
+ * APP_NAME_OR_OTHER ::= APP_NAME
+ * | 'other'
+ * JAAS_CONFIG_BLOCK ::= '{' (LOGIN_MODULE_ENTRY ';')+ '}' ';'
+ * LOGIN_MODULE_ENTRY ::= MODULE_CLASS FLAG MODULE_OPTION* ';'
+ * FLAG ::= 'required'
+ * | 'requisite'
+ * | 'sufficient'
+ * | 'optional'
+ * MODULE_OPTION ::= PARAM_NAME '=' PARAM_VALUE
+ *
+ * APP_NAME ::= JAVA_IDENTIFIER
+ * MODULE_CLASS ::= JAVA_IDENTIFIER ('.' JAVA_IDENTIFIER)*
+ * PARAM_NAME ::= STRING
+ * PARAM_VALUE ::= '"' STRING '"' | ''' STRING ''' | STRING
+ * </pre>
+ *
+ * <p>This parser handles UTF-8 entities when used as APP_NAME and PARAM_VALUE.
+ * It also checks for the use of Java identifiers used in MODULE_CLASS, thus
+ * minimizing the risks of having {@link java.lang.ClassCastException}s thrown
+ * at runtime due to syntactically invalid names.</p>
+ *
+ * <p>In the above context, a JAVA_IDENTIFIER is a sequence of tokens,
+ * separated by the character '.'. Each of these tokens obeys the following:</p>
+ *
+ * <ol>
+ * <li>its first character yields <code>true</code> when used as an input to
+ * the {@link java.lang.Character#isJavaIdentifierStart(char)}, and</li>
+ * <li>all remaining characters, yield <code>true</code> when used as an
+ * input to {@link java.lang.Character#isJavaIdentifierPart(char)}.</li>
+ * </ol>
+ */
+public final class ConfigFileParser
+{
+ // Constants and fields
+ // --------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+ private static final void debug(String m) {if (DEBUG) System.err.println(m);};
+
+ private ConfigFileTokenizer cft;
+ private Map map = new HashMap();
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ // default 0-arguments constructor
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ /**
+ * Returns the parse result as a {@link Map} where the keys are application
+ * names, and the entries are {@link List}s of {@link AppConfigurationEntry}
+ * entries, one for each login module entry, in the order they were
+ * encountered, for that application name in the just parsed configuration
+ * file.
+ */
+ public Map getLoginModulesMap()
+ {
+ return map;
+ }
+
+ /**
+ * Parses the {@link Reader}'s contents assuming it is in the <i>default
+ * syntax</i>.
+ *
+ * @param r the {@link Reader} whose contents are assumed to be a JAAS Login
+ * Configuration Module file written in the <i>default syntax</i>.
+ * @throws IOException if an exception occurs while parsing the input.
+ */
+ public void parse(Reader r) throws IOException
+ {
+ initParser(r);
+
+ while (parseAppOrOtherEntry())
+ ; // do nothing
+ }
+
+ private void initParser(Reader r) throws IOException
+ {
+ map.clear();
+
+ cft = new ConfigFileTokenizer(r);
+ }
+
+ /**
+ * @return <code>true</code> if an APP_OR_OTHER_ENTRY was correctly parsed.
+ * Returns <code>false</code> otherwise.
+ * @throws IOException if an exception occurs while parsing the input.
+ */
+ private boolean parseAppOrOtherEntry() throws IOException
+ {
+ int c = cft.nextToken();
+ if (c == ConfigFileTokenizer.TT_EOF)
+ return false;
+
+ if (c != ConfigFileTokenizer.TT_WORD)
+ {
+ cft.pushBack();
+ return false;
+ }
+
+ String appName = cft.sval;
+ debug("DEBUG: APP_NAME_OR_OTHER = " + appName);
+ if (cft.nextToken() != '{')
+ abort("Missing '{' after APP_NAME_OR_OTHER");
+
+ List lmis = new ArrayList();
+ while (parseACE(lmis))
+ ; // do nothing
+
+ c = cft.nextToken();
+ if (c != '}')
+ abort("Was expecting '}' but found " + (char) c);
+
+ c = cft.nextToken();
+ if (c != ';')
+ abort("Was expecting ';' but found " + (char) c);
+
+ List listOfACEs = (List) map.get(appName);
+ if (listOfACEs == null)
+ {
+ listOfACEs = new ArrayList();
+ map.put(appName, listOfACEs);
+ }
+ listOfACEs.addAll(lmis);
+ return !appName.equalsIgnoreCase("other");
+ }
+
+ /**
+ * @return <code>true</code> if a LOGIN_MODULE_ENTRY was correctly parsed.
+ * Returns <code>false</code> otherwise.
+ * @throws IOException if an exception occurs while parsing the input.
+ */
+ private boolean parseACE(List listOfACEs) throws IOException
+ {
+ int c = cft.nextToken();
+ if (c != ConfigFileTokenizer.TT_WORD)
+ {
+ cft.pushBack();
+ return false;
+ }
+
+ String clazz = validateClassName(cft.sval);
+ debug("DEBUG: MODULE_CLASS = " + clazz);
+
+ if (cft.nextToken() != ConfigFileTokenizer.TT_WORD)
+ abort("Was expecting FLAG but found none");
+
+ String flag = cft.sval;
+ debug("DEBUG: FLAG = " + flag);
+ AppConfigurationEntry.LoginModuleControlFlag f = null;
+ if (flag.equalsIgnoreCase("required"))
+ f = AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
+ else if (flag.equalsIgnoreCase("requisite"))
+ f = AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
+ else if (flag.equalsIgnoreCase("sufficient"))
+ f = AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
+ else if (flag.equalsIgnoreCase("optional"))
+ f = AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
+ else
+ abort("Unknown Flag: " + flag);
+
+ Map options = new HashMap();
+ String paramName, paramValue;
+ c = cft.nextToken();
+ while (c != ';')
+ {
+ if (c != ConfigFileTokenizer.TT_WORD)
+ abort("Was expecting PARAM_NAME but got '" + ((char) c) + "'");
+
+ paramName = cft.sval;
+ debug("DEBUG: PARAM_NAME = " + paramName);
+ if (cft.nextToken() != '=')
+ abort("Missing '=' after PARAM_NAME");
+
+ c = cft.nextToken();
+ if (c != '"' && c != '\'')
+ debug(" WARN: Was expecting a quoted string but got no quote " +
+ "character. Assume unquoted string");
+
+ paramValue = expandParamValue(cft.sval);
+ debug("DEBUG: PARAM_VALUE = " + paramValue);
+ options.put(paramName, paramValue);
+
+ c = cft.nextToken();
+ }
+
+ AppConfigurationEntry ace = new AppConfigurationEntry(clazz, f, options);
+ debug("DEBUG: LOGIN_MODULE_ENTRY = " + ace);
+ listOfACEs.add(ace);
+ return true;
+ }
+
+ private void abort(String m) throws IOException
+ {
+ debug("ERROR: " + m);
+ debug("DEBUG: Map (so far) = " + String.valueOf(map));
+ throw new IOException(m);
+ }
+
+ private String validateClassName(String cn) throws IOException
+ {
+ if (cn.startsWith(".") || cn.endsWith("."))
+ abort("MODULE_CLASS MUST NOT start or end with a '.'");
+
+ String[] tokens = cn.split(".");
+ for (int i = 0; i < tokens.length; i++)
+ {
+ String t = tokens[i];
+ if (Character.isJavaIdentifierStart(cn.toCharArray()[0]))
+ abort("");
+
+ // we dont check the rest of the characters for isJavaIdentifierPart()
+ // because that's what the tokenizer does.
+ }
+
+ return cn;
+ }
+
+ /**
+ * The documentation of the {@link javax.security.auth.login.Configuration}
+ * states that: <i>"...If a String in the form, ${system.property}, occurs in
+ * the value, it will be expanded to the value of the system property."</i>.
+ * This method ensures this is the case. If such a string can not be expanded
+ * then it is left AS IS, assuming the LoginModule knows what to do with it.
+ *
+ * <p><b>IMPORTANT</b>: This implementation DOES NOT handle embedded ${}
+ * constructs.
+ *
+ * @param s the raw parameter value, incl. eventually strings of the form
+ * <code>${system.property}</code>.
+ * @return the input string with every occurence of
+ * <code>${system.property}</code> replaced with the value of the
+ * corresponding System property at the time of this method invocation. If
+ * the string is not a known System property name, then the complete sequence
+ * (incl. the ${} characters are passed AS IS.
+ */
+ private String expandParamValue(String s)
+ {
+ String result = s;
+ try
+ {
+ int searchNdx = 0;
+ while (searchNdx < result.length())
+ {
+ int i = s.indexOf("${", searchNdx);
+ if (i == -1)
+ break;
+
+ int j = s.indexOf("}", i + 2);
+ if (j == -1)
+ {
+ debug(" WARN: Found a ${ prefix with no } suffix. Ignore");
+ break;
+ }
+
+ String sysPropName = s.substring(i + 2, j);
+ debug("DEBUG: Found a reference to System property " + sysPropName);
+ String sysPropValue = System.getProperty(sysPropName);
+ debug("DEBUG: Resolved " + sysPropName + " to '" + sysPropValue + "'");
+ if (sysPropValue != null)
+ {
+ result = s.substring(0, i) + sysPropValue + s.substring(j + 1);
+ searchNdx = i + sysPropValue.length();
+ }
+ else
+ searchNdx = j + 1;
+ }
+ }
+ catch (Exception x)
+ {
+ debug(" WARN: Exception while expanding " + s + ". Ignore: " + x);
+ }
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/javax/security/auth/login/ConfigFileTokenizer.java b/libjava/classpath/gnu/javax/security/auth/login/ConfigFileTokenizer.java
new file mode 100644
index 00000000000..2cfe916e400
--- /dev/null
+++ b/libjava/classpath/gnu/javax/security/auth/login/ConfigFileTokenizer.java
@@ -0,0 +1,243 @@
+/* ConfigFileTokenizer.java -- JAAS Login Configuration default syntax tokenizer
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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.login;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * A UTF-8 friendly, JAAS Login Module Configuration file tokenizer written in
+ * the deault syntax. This class emulates, to a certain extent, the behavior of
+ * a {@link java.io.SrteamTokenizer} instance <code>st</code>, when set as
+ * follows:
+ *
+ * <pre>
+ * st.resetSyntax();
+ * st.lowerCaseMode(false);
+ * st.slashSlashComments(true);
+ * st.slashStarComments(true);
+ * st.eolIsSignificant(false);
+ * st.wordChars('_', '_');
+ * st.wordChars('$', '$');
+ * st.wordChars('A', 'Z');
+ * st.wordChars('a', 'z');
+ * st.wordChars('0', '9');
+ * st.wordChars('.', '.');
+ * st.whitespaceChars(' ', ' ');
+ * st.whitespaceChars('\t', '\t');
+ * st.whitespaceChars('\f', '\f');
+ * st.whitespaceChars('\r', '\r');
+ * st.whitespaceChars('\n', '\n');
+ * st.quoteChar('"');
+ * st.quoteChar('\'');
+ * </pre>
+ *
+ * <p>The most important (negative) difference with a
+ * {@link java.io.StreamTokenizer} is that this tokenizer does not properly
+ * handle C++ and Java // style comments in the middle of the line. It only
+ * ignores them if/when found at the start of the line.</p>
+ */
+public class ConfigFileTokenizer
+{
+ // Constants and fields
+ // --------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+ private static final void debug(String m) {if (DEBUG) System.err.println(m);};
+
+ /** A constant indicating that the end of the stream has been read. */
+ public static final int TT_EOF = -1;
+ /** A constant indicating that a word token has been read. */
+ public static final int TT_WORD = -3;
+ /** A constant indicating that no tokens have been read yet. */
+ private static final int TT_NONE = -4;
+
+ public String sval;
+ public int ttype;
+
+ private BufferedReader br;
+ boolean initialised;
+ private StringBuffer sb;
+ private int sbNdx;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /** Trivial constructor. */
+ ConfigFileTokenizer(Reader r)
+ {
+ super();
+
+ br = r instanceof BufferedReader ? (BufferedReader) r : new BufferedReader(r);
+ initialised = false;
+ }
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ public int nextToken() throws IOException
+ {
+ if (!initialised)
+ init();
+
+ if (sbNdx >= sb.length())
+ return TT_EOF;
+
+ skipWhitespace();
+
+ if (sbNdx >= sb.length())
+ return TT_EOF;
+
+ int endNdx;
+ if (Character.isJavaIdentifierPart(sb.charAt(sbNdx)))
+ {
+ endNdx = sbNdx + 1;
+ while (Character.isJavaIdentifierPart(sb.charAt(endNdx))
+ || sb.charAt(endNdx) == '.')
+ endNdx++;
+
+ ttype = TT_WORD;
+ sval = sb.substring(sbNdx, endNdx);
+ sbNdx = endNdx;
+ return ttype;
+ }
+
+ int c = sb.charAt(sbNdx);
+ if (c == '{' || c == '}' || c == ';' || c == '=')
+ {
+ ttype = c;
+ sbNdx++;
+ return ttype;
+ }
+
+ if (c == '"' || c == '\'')
+ {
+ ttype = c;
+ String quote = sb.substring(sbNdx, sbNdx + 1);
+ int i = sbNdx + 1;
+ while (true)
+ {
+ // find a candidate
+ endNdx = sb.indexOf(quote, i);
+ if (endNdx == -1)
+ abort("Missing closing quote: " + quote);
+
+ // found one; is it escaped?
+ if (sb.charAt(endNdx - 1) != '\\')
+ break;
+
+ i++;
+ continue;
+ }
+
+ endNdx++;
+ sval = sb.substring(sbNdx, endNdx);
+ sbNdx = endNdx;
+ return ttype;
+ }
+
+ abort("Unknown character: " + sb.charAt(sbNdx));
+ return Integer.MIN_VALUE;
+ }
+
+ public void pushBack()
+ {
+ sbNdx -= ttype != TT_WORD ? 1 : sval.length();
+ }
+
+ private void init() throws IOException
+ {
+ sb = new StringBuffer();
+ String line;
+ while ((line = br.readLine()) != null)
+ {
+ line = line.trim();
+ if (line.length() == 0)
+ continue;
+
+ if (line.startsWith("#") || line.startsWith("//"))
+ continue;
+
+ sb.append(line).append(" ");
+ }
+
+ sbNdx = 0;
+ sval = null;
+ ttype = TT_NONE;
+
+ initialised = true;
+ }
+
+ private void skipWhitespace() throws IOException
+ {
+ int endNdx;
+ while (sbNdx < sb.length())
+ if (Character.isWhitespace(sb.charAt(sbNdx)))
+ {
+ sbNdx++;
+ while (sbNdx < sb.length() && Character.isWhitespace(sb.charAt(sbNdx)))
+ sbNdx++;
+
+ continue;
+ }
+ else if (sb.charAt(sbNdx) == '/' && sb.charAt(sbNdx + 1) == '*')
+ {
+ endNdx = sb.indexOf("*/", sbNdx + 2);
+ if (endNdx == -1)
+ abort("Missing closing */ sequence");
+
+ sbNdx = endNdx + 2;
+ continue;
+ }
+ else
+ break;
+ }
+
+ private void abort(String m) throws IOException
+ {
+ debug("DEBUG: " + m);
+ debug("DEBUG: sb = " + sb);
+ debug("DEBUG: sbNdx = " + sbNdx);
+ throw new IOException(m);
+ }
+}
diff --git a/libjava/classpath/gnu/javax/security/auth/login/GnuConfiguration.java b/libjava/classpath/gnu/javax/security/auth/login/GnuConfiguration.java
new file mode 100644
index 00000000000..f0b8594a0df
--- /dev/null
+++ b/libjava/classpath/gnu/javax/security/auth/login/GnuConfiguration.java
@@ -0,0 +1,450 @@
+/* GnuConfiguration.java -- GNU Classpath implementation of JAAS Configuration
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you 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.login;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.Security;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.AuthPermission;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
+/**
+ * An implementation of the {@link Configuration} class which interprets JAAS
+ * Login Configuration files written in the <i>default</i> syntax described in
+ * the publicly available documentation of that class. A more formal definition
+ * of this syntax is as follows:
+ *
+ * <pre>
+ * CONFIG ::= APP_OR_OTHER_ENTRY+
+ * APP_OR_OTHER_ENTRY ::= APP_NAME_OR_OTHER JAAS_CONFIG_BLOCK
+ * APP_NAME_OR_OTHER ::= APP_NAME
+ * | 'other'
+ * JAAS_CONFIG_BLOCK ::= '{' (LOGIN_MODULE_ENTRY ';')+ '}' ';'
+ * LOGIN_MODULE_ENTRY ::= MODULE_CLASS FLAG MODULE_OPTION* ';'
+ * FLAG ::= 'required'
+ * | 'requisite'
+ * | 'sufficient'
+ * | 'optional'
+ * MODULE_OPTION ::= PARAM_NAME '=' PARAM_VALUE
+ *
+ * APP_NAME ::= JAVA_IDENTIFIER
+ * MODULE_CLASS ::= JAVA_IDENTIFIER ('.' JAVA_IDENTIFIER)*
+ * PARAM_NAME ::= STRING
+ * PARAM_VALUE ::= '"' STRING '"' | ''' STRING ''' | STRING
+ * </pre>
+ *
+ * <p>This implementation will specifically attempt to process one or more
+ * Login Configuration files in the following locations, and when found parse
+ * them and merge their contents. The locations, and the order in which they are
+ * investigated, follows:</p>
+ *
+ * <ol>
+ * <li>If the following Security properties:
+ * <i>java.security.auth.login.config.url.<b>N</b></i>, where <i><b>N</b></i>
+ * is a digit, from <code>1</code> to an arbitrary number, are defined, then
+ * the value of each of those properties will be considered as a JAAS Login
+ * Configuration file written in the default syntax. This implementation will
+ * attempt parsing all such files.
+ *
+ * <p>It is worth noting the following:
+ * <ul>
+ * <li>The GNU Classpath security file, named <i>classpath.security</i>,
+ * where all Security properties are encoded, is usually located in
+ * <i>/usr/local/classpath/lib/security</i> folder.</li>
+ *
+ * <li>The numbers used in the properties
+ * <i>java.security.auth.login.config.url.<b>N</b></i> MUST be sequential,
+ * with no breaks in-between.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>If at least one of the designated Configuration files was found, and
+ * was parsed correctly, then no other location will be inspected.</p></li>
+ *
+ * <li>If the System property named <i>java.security.auth.login.config</i>
+ * is not null or empty, its contents are then interpreted as a URL to a
+ * JAAS Login Configuration file written in the default syntax.
+ *
+ * <p>If this System property is defined, and the file it refers to was
+ * parsed correctly, then no other location will be inspected.</p></li>
+ *
+ * <li>If a file named <i>.java.login.config</i> or <i>java.login.config</i>
+ * (in that order) is found in the location referenced by the value of the
+ * System property <i>user.home</i>, then that file is parsed as a JAAS Login
+ * Configuration written in the default syntax.</li>
+ *
+ * <li>If none of the above resulted in a correctly parsed JAAS Login
+ * Configuration file, then this implementation will install a <i>Null
+ * Configuration</i> which basically does not recognize any Application.</li>
+ * </ol>
+ */
+public final class GnuConfiguration extends Configuration
+{
+ // Constants and fields
+ // --------------------------------------------------------------------------
+
+ private static final boolean DEBUG = true;
+ private static final void debug(String m) {if (DEBUG) System.err.println(m);};
+
+ /**
+ * The internal map of login modules keyed by application name. Each entry in
+ * this map is a {@link List} of {@link AppConfigurationEntry}s for that
+ * application name.
+ */
+ private Map loginModulesMap;
+ /** Our reference to our default syntax parser. */
+ private ConfigFileParser cp;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /** Trivial 0-arguments Constructor. */
+ public GnuConfiguration()
+ {
+ super();
+
+ loginModulesMap = new HashMap();
+ cp = new ConfigFileParser();
+ init();
+ }
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ // Configuration abstract methods implementation ----------------------------
+
+ /* (non-Javadoc)
+ * @see javax.security.auth.login.Configuration#getAppConfigurationEntry(java.lang.String)
+ */
+ public AppConfigurationEntry[] getAppConfigurationEntry(String appName)
+ {
+ if (appName == null)
+ return null;
+
+ appName = appName.trim();
+ if (appName.length() == 0)
+ return null;
+
+ List loginModules = (List) loginModulesMap.get(appName);
+ if (loginModules == null || loginModules.size() == 0)
+ return null;
+
+ debug("DEBUG: " + appName + " -> " + loginModules.size() + " entry(ies)");
+ return (AppConfigurationEntry[]) loginModules.toArray(new AppConfigurationEntry[0]);
+ }
+
+ /**
+ * Refreshes and reloads this <code>Configuration</code>.
+ *
+ * <p>This method causes this <code>Configuration</code> object to refresh /
+ * reload its contents following the locations and logic described above in
+ * the class documentation section.</p>
+ *
+ * @throws SecurityException if the caller does not have an
+ * {@link AuthPermission} for the action named
+ * <code>refreshLoginConfiguration</code>.
+ * @see {@link AuthPermission}
+ */
+ public void refresh()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AuthPermission("refreshLoginConfiguration"));
+
+ loginModulesMap.clear();
+ init();
+ }
+
+ // helper methods -----------------------------------------------------------
+
+ /**
+ * Attempts to find and parse JAAS Login Configuration file(s) written in
+ * the default syntax. The locations searched are as descibed in the class
+ * documentation.
+ */
+ private void init()
+ {
+ if (processSecurityProperties())
+ debug(" INFO: Using login configuration defined by Security property(ies)");
+ else if (processSystemProperty())
+ debug(" INFO: Using login configuration defined by System property");
+ else if (processUserHome())
+ debug(" INFO: Using login configuration defined in ${user.home}");
+ else
+ debug(" WARN: No login configuration file found");
+ }
+
+ /**
+ * Attempts to locate and parse one or more JAAS Login Configuration files
+ * defined as the values of the Security properties
+ * <i>java.security.auth.login.config.url.N</i>.
+ *
+ * @return <code>true</code> if it succeeds, and <code>false</code>
+ * otherwsie.
+ */
+ private boolean processSecurityProperties()
+ {
+ boolean result = false;
+ int counter = 0;
+ String s;
+ while (true)
+ try
+ {
+ counter++;
+ s = Security.getProperty("java.security.auth.login.config.url."
+ + counter);
+ if (s == null)
+ break;
+
+ s = s.trim();
+ if (s.length() != 0)
+ {
+ debug("DEBUG: java.security.auth.login.config.url." + counter
+ + " = " + s);
+ parseConfig(getInputStreamFromURL(s));
+ result = true;
+ }
+ }
+ catch (Throwable t)
+ {
+ debug(" WARN: Exception while handling Security property at #"
+ + counter + ". Continue: " + t);
+ }
+ return result;
+ }
+
+ /**
+ * Attempts to open a designated string as a well-formed {@link URL}. If a
+ * {@link MalformedURLException} occurs, this method then tries to open that
+ * string as a {@link File} (with the same name). If it succeeds, an
+ * {@link InputStream} is constructed and returned.
+ *
+ * @param s
+ * the designated name of either a {@link URL} or a {@link File}
+ * assumed to contain a JAAS Login Configuration in the default
+ * syntax.
+ * @return an {@link InputStream} around the data source.
+ * @throws IOException
+ * if an exception occurs during the operation.
+ */
+ private InputStream getInputStreamFromURL(String s) throws IOException
+ {
+ InputStream result = null;
+ try
+ {
+ URL url = new URL(s);
+ result = url.openStream();
+ }
+ catch (MalformedURLException x)
+ {
+ debug(" WARN: Failed opening as URL: " + s + ". Will try as File");
+ result = new FileInputStream(s);
+ }
+ return result;
+ }
+
+ /**
+ * Attempts to locate and parse a JAAS Login Configuration file defined as the
+ * value of the System property <i>java.security.auth.login.config</i>.
+ *
+ * @return <code>true</code> if it succeeds, and <code>false</code>
+ * otherwsie.
+ */
+ private boolean processSystemProperty()
+ {
+ boolean result = false;
+ try
+ {
+ String s = System.getProperty("java.security.auth.login.config");
+ if (s != null)
+ {
+ s = s.trim();
+ if (s.length() != 0)
+ {
+ debug("DEBUG: java.security.auth.login.config = " + s);
+ parseConfig(getInputStreamFromURL(s));
+ result = true;
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ debug(" WARN: Exception while handling System property. Continue: " + t);
+ }
+ return result;
+ }
+
+ /**
+ * Attempts to locate and parse a JAAS Login Configuration file named either
+ * as <i>.java.login.config</i> or <i>java.login.config</i> (without the
+ * leading dot) in the folder referenced by the System property
+ * <code>user.home</code>.
+ *
+ * @return <code>true</code> if it succeeds, and <code>false</code>
+ * otherwsie.
+ */
+ private boolean processUserHome()
+ {
+ boolean result = false;
+ try
+ {
+ File userHome = getUserHome();
+ if (userHome == null)
+ return result;
+
+ File jaasFile;
+ jaasFile = getConfigFromUserHome(userHome, ".java.login.config");
+ if (jaasFile == null)
+ jaasFile = getConfigFromUserHome(userHome, "java.login.config");
+
+ if (jaasFile == null)
+ {
+ debug(" WARN: Login Configuration file, in " + userHome
+ + ", does not exist or is inaccessible");
+ return result;
+ }
+
+ FileInputStream fis = new FileInputStream(jaasFile);
+ parseConfig(fis);
+ result = true;
+ }
+ catch (Throwable t)
+ {
+ debug(" WARN: Exception while handling ${user.home}: " + t);
+ }
+ return result;
+ }
+
+ private void parseConfig(InputStream configStream) throws IOException
+ {
+ cp.parse(new InputStreamReader(configStream, "UTF-8"));
+ Map loginModulesMap = cp.getLoginModulesMap();
+ mergeLoginModules(loginModulesMap);
+ }
+
+ private void mergeLoginModules(Map otherLoginModules)
+ {
+ if (otherLoginModules == null || otherLoginModules.size() < 1)
+ return;
+
+ for (Iterator it = otherLoginModules.keySet().iterator(); it.hasNext();)
+ {
+ String appName = (String) it.next();
+ List thatListOfACEs = (List) otherLoginModules.get(appName);
+ if (thatListOfACEs == null || thatListOfACEs.size() < 1)
+ continue;
+
+ List thisListsOfACEs = (List) loginModulesMap.get(appName);
+ if (thisListsOfACEs == null)
+ loginModulesMap.put(appName, thatListOfACEs);
+ else
+ thisListsOfACEs.addAll(thatListOfACEs);
+ }
+ }
+
+ private File getUserHome()
+ {
+ String uh = System.getProperty("user.home");
+ if (uh == null || uh.trim().length() == 0)
+ {
+ debug(" WARN: User home path is not set or is empty");
+ return null;
+ }
+
+ uh = uh.trim();
+ File result = new File(uh);
+ if (!result.exists())
+ {
+ debug(" WARN: User home '" + uh + "' does not exist");
+ return null;
+ }
+
+ if (!result.isDirectory())
+ {
+ debug(" WARN: User home '" + uh + "' is not a directory");
+ return null;
+ }
+
+ if (!result.canRead())
+ {
+ debug(" WARN: User home '" + uh + "' is not readable");
+ return null;
+ }
+
+ return result;
+ }
+
+ private File getConfigFromUserHome(File userHome, String fileName)
+ {
+ File result = new File(userHome, fileName);
+ if (!result.exists())
+ {
+ debug(" WARN: File '" + fileName + "' does not exist in user's home");
+ return null;
+ }
+
+ if (!result.isFile())
+ {
+ debug(" WARN: File '" + fileName + "' in user's home is not a file");
+ return null;
+ }
+
+ if (!result.canRead())
+ {
+ debug(" WARN: File '" + fileName + "' in user's home is not readable");
+ return null;
+ }
+
+ return result;
+ }
+}
OpenPOWER on IntegriCloud