summaryrefslogtreecommitdiff
path: root/libjava/classpath/gnu
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu')
-rw-r--r--libjava/classpath/gnu/CORBA/IOR.java54
-rw-r--r--libjava/classpath/gnu/CORBA/NamingService/NamingMap.java13
-rw-r--r--libjava/classpath/gnu/CORBA/NamingService/NamingServiceTransient.java2
-rw-r--r--libjava/classpath/gnu/CORBA/NamingService/TransientContext.java35
-rw-r--r--libjava/classpath/gnu/classpath/ServiceFactory.java7
-rw-r--r--libjava/classpath/gnu/classpath/ServiceProviderLoadingAction.java6
-rw-r--r--libjava/classpath/gnu/classpath/debug/Component.java4
-rw-r--r--libjava/classpath/gnu/classpath/debug/Simple1LineFormatter.java153
-rw-r--r--libjava/classpath/gnu/classpath/jdwp/Jdwp.java6
-rw-r--r--libjava/classpath/gnu/classpath/jdwp/event/EventRequest.java15
-rw-r--r--libjava/classpath/gnu/classpath/jdwp/id/JdwpId.java12
-rw-r--r--libjava/classpath/gnu/classpath/jdwp/id/ObjectId.java10
-rw-r--r--libjava/classpath/gnu/classpath/jdwp/id/ReferenceTypeId.java10
-rw-r--r--libjava/classpath/gnu/classpath/jdwp/processor/VirtualMachineCommandSet.java14
-rw-r--r--libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java6
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java7
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java9
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java57
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java157
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java25
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java31
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java13
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java39
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java20
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java9
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java9
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java79
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java59
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java99
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java32
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java33
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java7
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java22
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java6
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java2
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java170
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java54
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java224
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingCanvasPeer.java64
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java89
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java994
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java241
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingFramePeer.java196
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java196
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingMenuBarPeer.java295
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingMenuItemPeer.java157
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingMenuPeer.java284
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java67
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java367
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java165
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java72
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/package.html71
-rw-r--r--libjava/classpath/gnu/java/beans/DefaultExceptionListener.java (renamed from libjava/classpath/gnu/java/beans/decoder/DefaultExceptionListener.java)25
-rw-r--r--libjava/classpath/gnu/java/lang/CharData.java2228
-rw-r--r--libjava/classpath/gnu/java/net/CRLFInputStream.java19
-rw-r--r--libjava/classpath/gnu/java/net/LineInputStream.java31
-rw-r--r--libjava/classpath/gnu/java/net/protocol/file/Connection.java18
-rw-r--r--libjava/classpath/gnu/java/net/protocol/ftp/ActiveModeDTP.java1
-rw-r--r--libjava/classpath/gnu/java/net/protocol/ftp/FTPURLConnection.java45
-rw-r--r--libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java102
-rw-r--r--libjava/classpath/gnu/java/net/protocol/http/HTTPConnection.java274
-rw-r--r--libjava/classpath/gnu/java/net/protocol/http/HTTPURLConnection.java186
-rw-r--r--libjava/classpath/gnu/java/net/protocol/http/Headers.java283
-rw-r--r--libjava/classpath/gnu/java/net/protocol/http/Request.java58
-rw-r--r--libjava/classpath/gnu/java/net/protocol/http/Response.java24
-rw-r--r--libjava/classpath/gnu/java/net/protocol/http/ResponseHeaderHandler.java2
-rw-r--r--libjava/classpath/gnu/java/net/protocol/jar/Connection.java8
-rw-r--r--libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java2
-rw-r--r--libjava/classpath/gnu/java/nio/charset/Provider.java3
-rw-r--r--libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java1
-rw-r--r--libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java1
-rw-r--r--libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java2
-rw-r--r--libjava/classpath/gnu/java/rmi/dgc/DGCImpl.java178
-rw-r--r--libjava/classpath/gnu/java/rmi/registry/RegistryImpl.java2
-rw-r--r--libjava/classpath/gnu/java/rmi/server/CombinedClassLoader.java149
-rw-r--r--libjava/classpath/gnu/java/rmi/server/RMIObjectInputStream.java64
-rw-r--r--libjava/classpath/gnu/java/rmi/server/UnicastServerRef.java650
-rw-r--r--libjava/classpath/gnu/java/security/Properties.java374
-rw-r--r--libjava/classpath/gnu/java/security/Registry.java455
-rw-r--r--libjava/classpath/gnu/java/security/der/DERValue.java29
-rw-r--r--libjava/classpath/gnu/java/security/der/DERWriter.java10
-rw-r--r--libjava/classpath/gnu/java/security/hash/BaseHash.java206
-rw-r--r--libjava/classpath/gnu/java/security/hash/HashFactory.java178
-rw-r--r--libjava/classpath/gnu/java/security/hash/Haval.java759
-rw-r--r--libjava/classpath/gnu/java/security/hash/IMessageDigest.java135
-rw-r--r--libjava/classpath/gnu/java/security/hash/MD2.java301
-rw-r--r--libjava/classpath/gnu/java/security/hash/MD4.java328
-rw-r--r--libjava/classpath/gnu/java/security/hash/MD5.java365
-rw-r--r--libjava/classpath/gnu/java/security/hash/RipeMD128.java291
-rw-r--r--libjava/classpath/gnu/java/security/hash/RipeMD160.java328
-rw-r--r--libjava/classpath/gnu/java/security/hash/Sha160.java308
-rw-r--r--libjava/classpath/gnu/java/security/hash/Sha256.java278
-rw-r--r--libjava/classpath/gnu/java/security/hash/Sha384.java322
-rw-r--r--libjava/classpath/gnu/java/security/hash/Sha512.java322
-rw-r--r--libjava/classpath/gnu/java/security/hash/Tiger.java943
-rw-r--r--libjava/classpath/gnu/java/security/hash/Whirlpool.java626
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/HavalSpi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/MD2Spi.java69
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/MD4Spi.java69
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/MD5Spi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/MessageDigestAdapter.java147
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/RipeMD128Spi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/RipeMD160Spi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/Sha160Spi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/Sha256Spi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/Sha384Spi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/Sha512Spi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/TigerSpi.java69
-rw-r--r--libjava/classpath/gnu/java/security/jce/hash/WhirlpoolSpi.java68
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/HavalRandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/MD2RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/MD4RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/MD5RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/RipeMD128RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/RipeMD160RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/SecureRandomAdapter.java126
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/Sha160RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/Sha256RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/Sha384RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/Sha512RandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/TigerRandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/prng/WhirlpoolRandomSpi.java66
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/DSSKeyFactory.java238
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java169
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/DSSParameters.java220
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/DSSParametersGenerator.java125
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/DSSRawSignatureSpi.java70
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/EncodedKeyFactory.java453
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java109
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/MD2withRSA.java56
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/MD5withRSA.java56
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/RSAKeyFactory.java265
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java115
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java69
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/SHA160withDSS.java54
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/SHA160withRSA.java56
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/SHA256withRSA.java56
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/SHA384withRSA.java56
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/SHA512withRSA.java56
-rw-r--r--libjava/classpath/gnu/java/security/jce/sig/SignatureAdapter.java263
-rw-r--r--libjava/classpath/gnu/java/security/key/IKeyPairCodec.java132
-rw-r--r--libjava/classpath/gnu/java/security/key/IKeyPairGenerator.java82
-rw-r--r--libjava/classpath/gnu/java/security/key/KeyPairCodecFactory.java362
-rw-r--r--libjava/classpath/gnu/java/security/key/KeyPairGeneratorFactory.java148
-rw-r--r--libjava/classpath/gnu/java/security/key/dss/DSSKey.java182
-rw-r--r--libjava/classpath/gnu/java/security/key/dss/DSSKeyPairGenerator.java445
-rw-r--r--libjava/classpath/gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java235
-rw-r--r--libjava/classpath/gnu/java/security/key/dss/DSSKeyPairRawCodec.java383
-rw-r--r--libjava/classpath/gnu/java/security/key/dss/DSSKeyPairX509Codec.java248
-rw-r--r--libjava/classpath/gnu/java/security/key/dss/DSSPrivateKey.java201
-rw-r--r--libjava/classpath/gnu/java/security/key/dss/DSSPublicKey.java201
-rw-r--r--libjava/classpath/gnu/java/security/key/dss/FIPS186.java296
-rw-r--r--libjava/classpath/gnu/java/security/key/rsa/GnuRSAKey.java181
-rw-r--r--libjava/classpath/gnu/java/security/key/rsa/GnuRSAPrivateKey.java299
-rw-r--r--libjava/classpath/gnu/java/security/key/rsa/GnuRSAPublicKey.java185
-rw-r--r--libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairGenerator.java264
-rw-r--r--libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java284
-rw-r--r--libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java332
-rw-r--r--libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairX509Codec.java248
-rw-r--r--libjava/classpath/gnu/java/security/prng/BasePRNG.java199
-rw-r--r--libjava/classpath/gnu/java/security/prng/EntropySource.java62
-rw-r--r--libjava/classpath/gnu/java/security/prng/IRandom.java180
-rw-r--r--libjava/classpath/gnu/java/security/prng/LimitReachedException.java69
-rw-r--r--libjava/classpath/gnu/java/security/prng/MDGenerator.java135
-rw-r--r--libjava/classpath/gnu/java/security/prng/PRNGFactory.java109
-rw-r--r--libjava/classpath/gnu/java/security/prng/RandomEvent.java82
-rw-r--r--libjava/classpath/gnu/java/security/prng/RandomEventListener.java50
-rw-r--r--libjava/classpath/gnu/java/security/provider/DSAKeyFactory.java134
-rw-r--r--libjava/classpath/gnu/java/security/provider/DSAKeyPairGenerator.java194
-rw-r--r--libjava/classpath/gnu/java/security/provider/DSAParameters.java150
-rw-r--r--libjava/classpath/gnu/java/security/provider/DSASignature.java251
-rw-r--r--libjava/classpath/gnu/java/security/provider/DiffieHellmanKeyFactoryImpl.java123
-rw-r--r--libjava/classpath/gnu/java/security/provider/EncodedKeyFactory.java303
-rw-r--r--libjava/classpath/gnu/java/security/provider/Gnu.java248
-rw-r--r--libjava/classpath/gnu/java/security/provider/GnuDSAPrivateKey.java147
-rw-r--r--libjava/classpath/gnu/java/security/provider/GnuDSAPublicKey.java137
-rw-r--r--libjava/classpath/gnu/java/security/provider/GnuRSAPrivateKey.java164
-rw-r--r--libjava/classpath/gnu/java/security/provider/MD5.java338
-rw-r--r--libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java9
-rw-r--r--libjava/classpath/gnu/java/security/provider/RSA.java311
-rw-r--r--libjava/classpath/gnu/java/security/provider/RSAKeyFactory.java181
-rw-r--r--libjava/classpath/gnu/java/security/provider/SHA.java242
-rw-r--r--libjava/classpath/gnu/java/security/provider/SHA1PRNG.java137
-rw-r--r--libjava/classpath/gnu/java/security/sig/BaseSignature.java261
-rw-r--r--libjava/classpath/gnu/java/security/sig/ISignature.java169
-rw-r--r--libjava/classpath/gnu/java/security/sig/ISignatureCodec.java68
-rw-r--r--libjava/classpath/gnu/java/security/sig/SignatureCodecFactory.java226
-rw-r--r--libjava/classpath/gnu/java/security/sig/SignatureFactory.java113
-rw-r--r--libjava/classpath/gnu/java/security/sig/dss/DSSSignature.java347
-rw-r--r--libjava/classpath/gnu/java/security/sig/dss/DSSSignatureRawCodec.java191
-rw-r--r--libjava/classpath/gnu/java/security/sig/dss/DSSSignatureX509Codec.java193
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java306
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java299
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/EMSA_PSS.java432
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/RSA.java356
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java247
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5SignatureRawCodec.java153
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5SignatureX509Codec.java128
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/RSAPSSSignature.java348
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java159
-rw-r--r--libjava/classpath/gnu/java/security/sig/rsa/RSASignatureFactory.java176
-rw-r--r--libjava/classpath/gnu/java/security/util/Base64.java396
-rw-r--r--libjava/classpath/gnu/java/security/util/DerUtil.java64
-rw-r--r--libjava/classpath/gnu/java/security/util/ExpirableObject.java172
-rw-r--r--libjava/classpath/gnu/java/security/util/FormatUtil.java140
-rw-r--r--libjava/classpath/gnu/java/security/util/PRNG.java156
-rw-r--r--libjava/classpath/gnu/java/security/util/Prime2.java417
-rw-r--r--libjava/classpath/gnu/java/security/util/Sequence.java149
-rw-r--r--libjava/classpath/gnu/java/security/util/SimpleList.java171
-rw-r--r--libjava/classpath/gnu/java/security/util/Util.java692
-rw-r--r--libjava/classpath/gnu/java/security/x509/X509Certificate.java8
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java21
-rw-r--r--libjava/classpath/gnu/java/util/prefs/EventDispatcher.java112
-rw-r--r--libjava/classpath/gnu/java/util/prefs/FileBasedFactory.java12
-rw-r--r--libjava/classpath/gnu/java/util/prefs/FileBasedPreferences.java273
-rw-r--r--libjava/classpath/gnu/java/util/prefs/MemoryBasedFactory.java2
-rw-r--r--libjava/classpath/gnu/java/util/prefs/MemoryBasedPreferences.java4
-rw-r--r--libjava/classpath/gnu/java/util/prefs/NodeWriter.java33
-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.java (renamed from libjava/classpath/gnu/java/security/provider/DiffieHellmanKeyPairGeneratorImpl.java)75
-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.java99
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPublicKey.java (renamed from libjava/classpath/gnu/java/security/provider/GnuDHPublicKey.java)80
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java98
-rw-r--r--libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java (renamed from libjava/classpath/gnu/java/security/provider/GnuRSAPublicKey.java)81
-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
-rw-r--r--libjava/classpath/gnu/regexp/CharIndexed.java14
-rw-r--r--libjava/classpath/gnu/regexp/CharIndexedCharArray.java11
-rw-r--r--libjava/classpath/gnu/regexp/CharIndexedInputStream.java12
-rw-r--r--libjava/classpath/gnu/regexp/CharIndexedString.java11
-rw-r--r--libjava/classpath/gnu/regexp/CharIndexedStringBuffer.java11
-rw-r--r--libjava/classpath/gnu/regexp/RE.java778
-rw-r--r--libjava/classpath/gnu/regexp/REMatch.java60
-rw-r--r--libjava/classpath/gnu/regexp/RESyntax.java40
-rw-r--r--libjava/classpath/gnu/regexp/REToken.java15
-rw-r--r--libjava/classpath/gnu/regexp/RETokenAny.java4
-rw-r--r--libjava/classpath/gnu/regexp/RETokenBackRef.java16
-rw-r--r--libjava/classpath/gnu/regexp/RETokenChar.java6
-rw-r--r--libjava/classpath/gnu/regexp/RETokenEnd.java4
-rw-r--r--libjava/classpath/gnu/regexp/RETokenEndSub.java4
-rw-r--r--libjava/classpath/gnu/regexp/RETokenIndependent.java76
-rw-r--r--libjava/classpath/gnu/regexp/RETokenLookAhead.java4
-rw-r--r--libjava/classpath/gnu/regexp/RETokenLookBehind.java116
-rw-r--r--libjava/classpath/gnu/regexp/RETokenNamedProperty.java301
-rw-r--r--libjava/classpath/gnu/regexp/RETokenOneOf.java181
-rw-r--r--libjava/classpath/gnu/regexp/RETokenPOSIX.java4
-rw-r--r--libjava/classpath/gnu/regexp/RETokenRange.java21
-rw-r--r--libjava/classpath/gnu/regexp/RETokenRepeated.java310
-rw-r--r--libjava/classpath/gnu/regexp/RETokenStart.java4
-rw-r--r--libjava/classpath/gnu/regexp/RETokenWordBoundary.java5
-rw-r--r--libjava/classpath/gnu/xml/aelfred2/XmlParser.java1
-rw-r--r--libjava/classpath/gnu/xml/dom/DomCharacterData.java37
-rw-r--r--libjava/classpath/gnu/xml/dom/DomDocumentBuilder.java18
-rw-r--r--libjava/classpath/gnu/xml/dom/DomDocumentBuilderFactory.java23
-rw-r--r--libjava/classpath/gnu/xml/dom/JAXPFactory.java23
-rw-r--r--libjava/classpath/gnu/xml/libxmlj/dom/GnomeDocumentBuilderFactory.java26
-rw-r--r--libjava/classpath/gnu/xml/stream/CRLFReader.java9
-rw-r--r--libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java46
-rw-r--r--libjava/classpath/gnu/xml/stream/FilteredEventReader.java21
-rw-r--r--libjava/classpath/gnu/xml/stream/SAXParser.java83
-rw-r--r--libjava/classpath/gnu/xml/stream/UnicodeReader.java6
-rw-r--r--libjava/classpath/gnu/xml/stream/XIncludeFilter.java21
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java13
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java9
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventImpl.java12
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java39
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java2
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java78
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java40
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLParser.java179
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLStreamReaderImpl.java1037
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java331
-rw-r--r--libjava/classpath/gnu/xml/transform/AbstractNumberNode.java2
-rw-r--r--libjava/classpath/gnu/xml/transform/ApplyImportsNode.java27
-rw-r--r--libjava/classpath/gnu/xml/transform/ApplyTemplatesNode.java46
-rw-r--r--libjava/classpath/gnu/xml/transform/AttributeNode.java2
-rw-r--r--libjava/classpath/gnu/xml/transform/CallTemplateNode.java86
-rw-r--r--libjava/classpath/gnu/xml/transform/ChooseNode.java28
-rw-r--r--libjava/classpath/gnu/xml/transform/CommentNode.java31
-rw-r--r--libjava/classpath/gnu/xml/transform/CopyNode.java73
-rw-r--r--libjava/classpath/gnu/xml/transform/CopyOfNode.java48
-rw-r--r--libjava/classpath/gnu/xml/transform/DocumentFunction.java30
-rw-r--r--libjava/classpath/gnu/xml/transform/ElementNode.java4
-rw-r--r--libjava/classpath/gnu/xml/transform/ForEachNode.java36
-rw-r--r--libjava/classpath/gnu/xml/transform/IfNode.java36
-rw-r--r--libjava/classpath/gnu/xml/transform/LiteralNode.java7
-rw-r--r--libjava/classpath/gnu/xml/transform/MessageNode.java12
-rw-r--r--libjava/classpath/gnu/xml/transform/OtherwiseNode.java31
-rw-r--r--libjava/classpath/gnu/xml/transform/ParameterNode.java65
-rw-r--r--libjava/classpath/gnu/xml/transform/ProcessingInstructionNode.java32
-rw-r--r--libjava/classpath/gnu/xml/transform/Stylesheet.java60
-rw-r--r--libjava/classpath/gnu/xml/transform/Template.java133
-rw-r--r--libjava/classpath/gnu/xml/transform/TemplateNode.java38
-rw-r--r--libjava/classpath/gnu/xml/transform/TextNode.java42
-rw-r--r--libjava/classpath/gnu/xml/transform/TransformerImpl.java12
-rw-r--r--libjava/classpath/gnu/xml/transform/ValueOfNode.java2
-rw-r--r--libjava/classpath/gnu/xml/transform/WhenNode.java36
-rw-r--r--libjava/classpath/gnu/xml/util/XHTMLWriter.java2
-rw-r--r--libjava/classpath/gnu/xml/util/XMLWriter.java2
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/Annotation.java (renamed from libjava/classpath/gnu/java/security/provider/MD5withRSA.java)31
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/AnySimpleType.java59
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/AnyType.java58
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/AnyURIType.java94
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/AtomicSimpleType.java78
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/Base64BinaryType.java131
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/BooleanType.java91
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/ByteType.java133
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/DateTimeType.java335
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/DateType.java222
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/DecimalType.java121
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/DoubleType.java112
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/DurationType.java239
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/EntitiesType.java107
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/EntityType.java88
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/EnumerationFacet.java69
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/Facet.java78
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/FloatType.java112
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/FractionDigitsFacet.java (renamed from libjava/classpath/gnu/xml/stream/StartEntityImpl.java)46
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/GDayType.java175
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/GMonthDayType.java184
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/GMonthType.java164
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/GYearMonthType.java177
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/GYearType.java152
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/HexBinaryType.java92
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/IDRefType.java87
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/IDRefsType.java87
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/IDType.java (renamed from libjava/classpath/gnu/javax/crypto/GnuDHPrivateKey.java)67
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/IntType.java133
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/IntegerType.java110
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/LanguageType.java87
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/LengthFacet.java72
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/ListSimpleType.java83
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/LongType.java133
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/MaxExclusiveFacet.java111
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/MaxInclusiveFacet.java112
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/MaxLengthFacet.java72
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/MinExclusiveFacet.java111
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/MinInclusiveFacet.java112
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/MinLengthFacet.java72
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NCNameType.java111
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NMTokenType.java102
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NMTokensType.java124
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NameType.java104
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NegativeIntegerType.java111
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NonNegativeIntegerType.java121
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NonPositiveIntegerType.java121
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NormalizedStringType.java88
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/NotationType.java90
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/PatternFacet.java71
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/PositiveIntegerType.java111
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/QNameType.java122
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/ShortType.java133
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/SimpleType.java257
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/StringType.java77
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/TimeType.java303
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/TokenType.java96
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/TotalDigitsFacet.java72
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/Type.java65
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/TypeBuilder.java279
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/TypeLibrary.java173
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/TypeLibraryFactory.java60
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/UnionSimpleType.java83
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/UnsignedByteType.java121
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/UnsignedIntType.java121
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/UnsignedLongType.java121
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/UnsignedShortType.java122
-rw-r--r--libjava/classpath/gnu/xml/validation/datatype/WhiteSpaceFacet.java (renamed from libjava/classpath/gnu/xml/stream/LocationImpl.java)60
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/AnyNameNameClass.java58
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/AttributePattern.java53
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/ChoiceNameClass.java59
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/ChoicePattern.java53
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/DataPattern.java60
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/Define.java52
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/ElementPattern.java53
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/EmptyPattern.java52
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/FullSyntaxBuilder.java1651
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/Grammar.java70
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/GrammarException.java (renamed from libjava/classpath/gnu/xml/stream/EndEntityImpl.java)40
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/GrammarValidator.java97
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/GroupPattern.java53
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/InterleavePattern.java53
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/ListPattern.java52
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/NSNameNameClass.java61
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/NameClass.java50
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/NameNameClass.java (renamed from libjava/classpath/gnu/java/security/provider/MD2withRSA.java)30
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/NotAllowedPattern.java53
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/OneOrMorePattern.java52
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/Param.java52
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/Pattern.java48
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/RELAXNGSchemaFactory.java151
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/RefPattern.java52
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/TextPattern.java52
-rw-r--r--libjava/classpath/gnu/xml/validation/relaxng/ValuePattern.java58
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/AnyAttribute.java (renamed from libjava/classpath/gnu/java/security/provider/SHA1withRSA.java)38
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/AttributeDeclaration.java99
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/AttributeUse.java79
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/ComplexType.java102
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/ElementDeclaration.java125
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/Particle.java (renamed from libjava/classpath/gnu/java/security/provider/MD4withRSA.java)31
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/ValidationException.java58
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchema.java134
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaAttributeTypeInfo.java100
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaBuilder.java844
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaElementTypeInfo.java93
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaSchemaFactory.java159
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaTypeInfo.java77
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaTypeInfoProvider.java82
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaValidator.java98
-rw-r--r--libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaValidatorHandler.java394
-rw-r--r--libjava/classpath/gnu/xml/xpath/LangFunction.java12
-rw-r--r--libjava/classpath/gnu/xml/xpath/NodeTypeTest.java1
-rw-r--r--libjava/classpath/gnu/xml/xpath/Selector.java41
740 files changed, 122904 insertions, 7405 deletions
diff --git a/libjava/classpath/gnu/CORBA/IOR.java b/libjava/classpath/gnu/CORBA/IOR.java
index 5d6d3152f8f..917e1983289 100644
--- a/libjava/classpath/gnu/CORBA/IOR.java
+++ b/libjava/classpath/gnu/CORBA/IOR.java
@@ -140,6 +140,27 @@ public class IOR
b.append(' ');
return b.toString();
}
+
+ /**
+ * Get a better formatted multiline string representation.
+ */
+ public String toStringFormatted()
+ {
+ StringBuffer b = new StringBuffer();
+ b.append("\n Native set " + name(native_set));
+ if (conversion != null && conversion.length > 0)
+ {
+ b.append("\n Other supported sets:\n ");
+ for (int i = 0; i < conversion.length; i++)
+ {
+ b.append(name(conversion[i]));
+ b.append(' ');
+ }
+ }
+ b.append("\n");
+ return b.toString();
+ }
+
/**
* Write into CDR stream.
@@ -590,6 +611,39 @@ public class IOR
return b.toString();
}
+
+ /**
+ * Returns a multiline formatted human readable string representation of
+ * this IOR object.
+ */
+ public String toStringFormatted()
+ {
+ StringBuffer b = new StringBuffer();
+ b.append("\nObject Id:\n ");
+ b.append(Id);
+ b.append("\nObject is accessible at:\n ");
+ b.append(Internet);
+
+ if (Big_Endian)
+ b.append("\n Big endian encoding");
+ else
+ b.append("\n Little endian encoding.");
+
+ b.append("\nObject Key\n ");
+
+ for (int i = 0; i < key.length; i++)
+ {
+ b.append(Integer.toHexString(key[i] & 0xFF));
+ }
+
+ b.append("\nSupported code sets:");
+ b.append("\n Wide:");
+ b.append(Internet.CodeSets.wide.toStringFormatted());
+ b.append(" Narrow:");
+ b.append(Internet.CodeSets.wide.toStringFormatted());
+
+ return b.toString();
+ }
/**
* Returs a stringified reference.
diff --git a/libjava/classpath/gnu/CORBA/NamingService/NamingMap.java b/libjava/classpath/gnu/CORBA/NamingService/NamingMap.java
index 95deb0096bd..f4e940ea907 100644
--- a/libjava/classpath/gnu/CORBA/NamingService/NamingMap.java
+++ b/libjava/classpath/gnu/CORBA/NamingService/NamingMap.java
@@ -58,11 +58,11 @@ public class NamingMap
/**
* The actual map.
*/
- private final TreeMap map;
+ protected final TreeMap map;
/**
* Creates an instance of the naming map, intialising the comparator
- * to the {@link cmpNameComparator}.
+ * to the {@link NameComponentComparator}.
*/
public NamingMap()
{
@@ -70,7 +70,7 @@ public class NamingMap
}
/**
- * Put the given CORBA object, specifying the given name as a key.
+ * Put the given GIOP object, specifying the given name as a key.
* If the entry with the given name already exists, or if the given
* object is already mapped under another name, the
* {@link AlreadyBound} exception will be thrown.
@@ -93,8 +93,11 @@ public class NamingMap
else
{
if (containsValue(object))
- throw new AlreadyBound("Tha object has another name");
+ throw new AlreadyBound("The object has another name");
}
+
+ // There are no restrictions in binding the object.
+ rebind(name, object);
}
/**
@@ -141,7 +144,7 @@ public class NamingMap
}
/**
- * Put the given CORBA object, specifying the given name as a key.
+ * Put the given GIOP object, specifying the given name as a key.
* Remove all pre - existing mappings for the given name and object.
*
* @param name the name.
diff --git a/libjava/classpath/gnu/CORBA/NamingService/NamingServiceTransient.java b/libjava/classpath/gnu/CORBA/NamingService/NamingServiceTransient.java
index bf72637d7d7..3669879f22a 100644
--- a/libjava/classpath/gnu/CORBA/NamingService/NamingServiceTransient.java
+++ b/libjava/classpath/gnu/CORBA/NamingService/NamingServiceTransient.java
@@ -136,7 +136,7 @@ public class NamingServiceTransient
System.out.println("GNU Classpath transient naming service "
+ "started at " + iorr.Internet.host + ":" + iorr.Internet.port
+ " key 'NameService'.\n\n"
- + "Copyright (C) 2005 Free Software Foundation\n"
+ + "Copyright (C) 2006 Free Software Foundation\n"
+ "This tool comes with ABSOLUTELY NO WARRANTY. "
+ "This is free software, and you are\nwelcome to "
+ "redistribute it under conditions, defined in "
diff --git a/libjava/classpath/gnu/CORBA/NamingService/TransientContext.java b/libjava/classpath/gnu/CORBA/NamingService/TransientContext.java
index 4b7c1938fde..c2d8275e001 100644
--- a/libjava/classpath/gnu/CORBA/NamingService/TransientContext.java
+++ b/libjava/classpath/gnu/CORBA/NamingService/TransientContext.java
@@ -59,7 +59,7 @@ import java.util.Map;
/**
* This class implements the transient naming service, defined by
- * {@link NamingContex}. The 'transient' means that the service does
+ * {@link NamingContext}. The 'transient' means that the service does
* not store its state into the persistent memory. If the service is
* restarted, the named objects must be re-registered again.
*
@@ -72,14 +72,39 @@ public class TransientContext
implements NamingContext, NamingContextOperations
{
/**
+ * Use serial version UID for interoperability.
+ */
+ private static final long serialVersionUID = 2;
+
+ /**
* The already named contexts.
*/
- protected final NamingMap named_contexts = new NamingMap();
+ protected final NamingMap named_contexts;
/**
* The already named objects.
*/
- protected final NamingMap named_objects = new NamingMap();
+ protected final NamingMap named_objects;
+
+ /**
+ * Create the naming conetxt with default (transient) naming maps.
+ */
+ public TransientContext()
+ {
+ this(new NamingMap(), new NamingMap());
+ }
+
+ /**
+ * Create the naming conetxt with the two provided naming maps.
+ *
+ * @param context_map the map for contexts
+ * @param object_map the map for objectss
+ */
+ public TransientContext(NamingMap context_map, NamingMap object_map)
+ {
+ named_contexts = context_map;
+ named_objects = object_map;
+ }
/**
* Gives the object a name, valid in this context.
@@ -376,7 +401,7 @@ public class TransientContext
/**
* Create a binding.
*
- * @param entry the entry, defining the bound object.
+ * @param an_entry the entry, defining the bound object.
* @param type the binding type.
* @return the created binding.
*/
@@ -396,7 +421,7 @@ public class TransientContext
* name, and pass the remainder (without the first node)
* of the name for that context to resolve.
*
- * @param name the name to resolve.
+ * @param a_name the name to resolve.
*
* @return the resolved context
*/
diff --git a/libjava/classpath/gnu/classpath/ServiceFactory.java b/libjava/classpath/gnu/classpath/ServiceFactory.java
index 711a9042cbf..122a79c96ed 100644
--- a/libjava/classpath/gnu/classpath/ServiceFactory.java
+++ b/libjava/classpath/gnu/classpath/ServiceFactory.java
@@ -282,7 +282,7 @@ public final class ServiceFactory
* An iterator over service providers that are listed in service
* provider configuration files, which get passed as an Enumeration
* of URLs. This is a helper class for {@link
- * ServiceFactory#lookupProviders}.
+ * ServiceFactory#lookupProviders(Class, ClassLoader)}.
*
* @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
*/
@@ -314,7 +314,8 @@ public final class ServiceFactory
* The security context used when loading and initializing service
* providers. We want to load and initialize all plug-in service
* providers under the same security context, namely the one that
- * was active when {@link #lookupProviders} has been called.
+ * was active when {@link #lookupProviders(Class, ClassLoader)} has
+ * been called.
*/
private final AccessControlContext securityContext;
@@ -527,7 +528,7 @@ public final class ServiceFactory
* framework. This call returns very quickly if no log message will
* be produced, so there is not much overhead in the standard case.
*
- * @param the severity of the message, for instance {@link
+ * @param level the severity of the message, for instance {@link
* Level#WARNING}.
*
* @param msg the log message, for instance <code>&#x201c;Could not
diff --git a/libjava/classpath/gnu/classpath/ServiceProviderLoadingAction.java b/libjava/classpath/gnu/classpath/ServiceProviderLoadingAction.java
index b5e59cb4b6f..9f9dc51cb68 100644
--- a/libjava/classpath/gnu/classpath/ServiceProviderLoadingAction.java
+++ b/libjava/classpath/gnu/classpath/ServiceProviderLoadingAction.java
@@ -48,9 +48,9 @@ import java.security.PrivilegedExceptionAction;
* <code>PriviledgedAction</code> in order to restrict the loaded
* service providers to the {@link java.security.AccessControlContext}
* that was active when {@link
- * gnu.classpath.ServiceFactory#lookupProviders} was called, even
- * though the actual loading is delayed to the time when the provider
- * is actually needed.
+ * gnu.classpath.ServiceFactory#lookupProviders(Class, ClassLoader)} was
+ * called, even though the actual loading is delayed to the time when the
+ * provider is actually needed.
*
* @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
*/
diff --git a/libjava/classpath/gnu/classpath/debug/Component.java b/libjava/classpath/gnu/classpath/debug/Component.java
index 242419ce4ae..af030ed2772 100644
--- a/libjava/classpath/gnu/classpath/debug/Component.java
+++ b/libjava/classpath/gnu/classpath/debug/Component.java
@@ -89,9 +89,9 @@ public final class Component extends Level
public static final Component SSL_HANDSHAKE = new Component ("SSL HANDSHAKE", 0);
/**
- * Traces the application messages during SSL communications.
+ * Traces record layer messages during SSL communications.
*/
- public static final Component SSL_APPLICATION = new Component ("SSL APPLICATION", 1);
+ public static final Component SSL_RECORD_LAYER = new Component ("SSL RECORD LAYER", 1);
/**
* Trace details about the SSL key exchange.
diff --git a/libjava/classpath/gnu/classpath/debug/Simple1LineFormatter.java b/libjava/classpath/gnu/classpath/debug/Simple1LineFormatter.java
new file mode 100644
index 00000000000..0bdf22a1950
--- /dev/null
+++ b/libjava/classpath/gnu/classpath/debug/Simple1LineFormatter.java
@@ -0,0 +1,153 @@
+/* Simple1LineFormatter.java -- A simple 1-line logging formatter
+ 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.classpath.debug;
+
+import gnu.classpath.SystemProperties;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+/**
+ * A simple 1-line formatter to use instead of the 2-line SimpleFormatter used
+ * by default in the JDK logging handlers.
+ * <p>
+ * The fixed format of this formatter is as follows:
+ * <p>
+ * <ol>
+ * <li>Date: As a yyyy-MM-dd string.</li>
+ * <li>Time: As a HH:mm:ss.SSSS Z string.</li>
+ * <li>Thread identifier, right-justified, and framed in an 11-digit field.</li>
+ * <li>Class name, without its package name, left-justified, and framed in a
+ * 32-character field.</li>
+ * <li>Method name, left-justified, and framed in a 32-character field.</li>
+ * <li>Level name, left-justified, and framed in a 6-character field.</li>
+ * <li>User message and arguments.</li>
+ * <li>Platform-dependent line-separator.</li>
+ * <li>Optionally, if the log-record contains a thrown exception, that
+ * exception's stack trace is appended to the output.</li>
+ * </ol>
+ * <p>
+ * Here is an example of the output generated by this formatter:
+ * <p>
+ * <pre>
+ * 2006-02-27 21:59:12.0881 +1100 -1343151280 EncodedKeyFactory engineGeneratePublic() FINER - ENTRY java.security.spec.X509EncodedKeySpec@b00d7fc0
+ * 2006-02-27 21:59:12.0887 +1100 -1343151280 EncodedKeyFactory engineGeneratePublic() FINE - Exception in DSSPublicKey.valueOf(). Ignore
+ * java.security.InvalidParameterException: Unexpected OID: 1.2.840.113549.1.1.1
+ * at gnu.java.security.key.dss.DSSKeyPairX509Codec.decodePublicKey (DSSKeyPairX509Codec.java:205)
+ * at gnu.java.security.key.dss.DSSPublicKey.valueOf (DSSPublicKey.java:136)
+ * at gnu.java.security.jce.sig.EncodedKeyFactory.engineGeneratePublic (EncodedKeyFactory.java:218)
+ * at java.security.KeyFactory.generatePublic (KeyFactory.java:219)
+ * at gnu.java.security.x509.X509Certificate.parse (X509Certificate.java:657)
+ * at gnu.java.security.x509.X509Certificate.<init> (X509Certificate.java:163)
+ * ...
+ * 2006-02-27 21:59:12.0895 +1100 -1343151280 RSAKeyPairX509Codec decodePublicKey() FINER - ENTRY [B@b00d7fd0
+ * 2006-02-27 21:59:12.0897 +1100 -1343151280 RSAKeyPairX509Codec decodePublicKey() FINER - RETURN gnu.java.security.key.rsa.GnuRSAPublicKey@b00fb940
+ * </pre>
+ */
+public class Simple1LineFormatter
+ extends Formatter
+{
+ private static final String DAT_PATTERN = "yyyy-MM-dd HH:mm:ss.SSSS Z ";
+ private static final DateFormat DAT_FORMAT = new SimpleDateFormat(DAT_PATTERN);
+ private static final String THREAD_PATTERN = " #########0;-#########0";
+ private static final NumberFormat THREAD_FORMAT = new DecimalFormat(THREAD_PATTERN);
+ private static final String SPACES_32 = " ";
+ private static final String SPACES_6 = " ";
+ private static final String LS = SystemProperties.getProperty("line.separator");
+
+ // default 0-arguments constructor
+
+ public String format(LogRecord record)
+ {
+ StringBuffer sb = new StringBuffer(180)
+ .append(DAT_FORMAT.format(new Date(record.getMillis())))
+ .append(THREAD_FORMAT.format(record.getThreadID()))
+ .append(" ");
+ String s = record.getSourceClassName();
+ if (s == null)
+ sb.append(SPACES_32);
+ else
+ {
+ s = s.trim();
+ int i = s.lastIndexOf(".");
+ if (i != - 1)
+ s = s.substring(i + 1);
+
+ s = (s + SPACES_32).substring(0, 32);
+ }
+
+ sb.append(s).append(" ");
+ s = record.getSourceMethodName();
+ if (s == null)
+ sb.append(SPACES_32);
+ else
+ {
+ s = s.trim();
+ if (s.endsWith("()"))
+ s = (s.trim() + SPACES_32).substring(0, 32);
+ else
+ s = (s.trim() + "()" + SPACES_32).substring(0, 32);
+ }
+
+ sb.append(s).append(" ");
+ s = String.valueOf(record.getLevel());
+ if (s == null)
+ sb.append(SPACES_6);
+ else
+ s = (s.trim() + SPACES_6).substring(0, 6);
+
+ sb.append(s).append(" - ").append(formatMessage(record)).append(LS);
+ Throwable cause = record.getThrown();
+ if (cause != null)
+ {
+ StringWriter sw = new StringWriter();
+ cause.printStackTrace(new PrintWriter(sw, true));
+ sb.append(sw.toString());
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/libjava/classpath/gnu/classpath/jdwp/Jdwp.java b/libjava/classpath/gnu/classpath/jdwp/Jdwp.java
index 43a37de2435..f73e0961027 100644
--- a/libjava/classpath/gnu/classpath/jdwp/Jdwp.java
+++ b/libjava/classpath/gnu/classpath/jdwp/Jdwp.java
@@ -1,5 +1,5 @@
/* Jdwp.java -- Virtual machine to JDWP back-end programming interface
- Copyright (C) 2005 Free Software Foundation
+ Copyright (C) 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -159,7 +159,7 @@ public class Jdwp
{
AccessController.doPrivileged (_packetProcessor);
}
- });
+ }, "packet processor");
_ppThread.start ();
}
@@ -258,7 +258,7 @@ public class Jdwp
break;
case EventRequest.SUSPEND_THREAD:
- VMVirtualMachine.suspendThread (this);
+ VMVirtualMachine.suspendThread (Thread.currentThread ());
break;
case EventRequest.SUSPEND_ALL:
diff --git a/libjava/classpath/gnu/classpath/jdwp/event/EventRequest.java b/libjava/classpath/gnu/classpath/jdwp/event/EventRequest.java
index eadad2840b6..6c2acf3c4e5 100644
--- a/libjava/classpath/gnu/classpath/jdwp/event/EventRequest.java
+++ b/libjava/classpath/gnu/classpath/jdwp/event/EventRequest.java
@@ -1,5 +1,5 @@
/* EventRequest.java -- an event request from the debugger
- Copyright (C) 2005 Free Software Foundation
+ Copyright (C) 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -44,8 +44,9 @@ import gnu.classpath.jdwp.event.filters.*;
import gnu.classpath.jdwp.exception.JdwpIllegalArgumentException;
import gnu.classpath.jdwp.id.*;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.LinkedList;
-import java.util.ListIterator;
/**
* A class which represents a request by the debugger for an event
@@ -320,6 +321,14 @@ public class EventRequest
}
/**
+ * Returns the filters attached to this request
+ */
+ public Collection getFilters ()
+ {
+ return _filters;
+ }
+
+ /**
* Returns the suspend policy for this request
*/
public byte getSuspendPolicy ()
@@ -363,7 +372,7 @@ public class EventRequest
// Loop through filters; all must match
// Note that we must allow EVERY filter to evaluate. This way
// things like CountFilter will work.
- ListIterator iter = _filters.listIterator ();
+ Iterator iter = _filters.iterator ();
while (iter.hasNext ())
{
IEventFilter filter = (IEventFilter) iter.next ();
diff --git a/libjava/classpath/gnu/classpath/jdwp/id/JdwpId.java b/libjava/classpath/gnu/classpath/jdwp/id/JdwpId.java
index 7f610e353a1..472650de868 100644
--- a/libjava/classpath/gnu/classpath/jdwp/id/JdwpId.java
+++ b/libjava/classpath/gnu/classpath/jdwp/id/JdwpId.java
@@ -1,5 +1,5 @@
/* JdwpId.java -- base class for all object ID types
- Copyright (C) 2005 Free Software Foundation
+ Copyright (C) 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -51,6 +51,11 @@ import java.lang.ref.SoftReference;
public abstract class JdwpId
{
/**
+ * The size of an ID. The default is 8 bytes (a long).
+ */
+ public static final int SIZE = 8;
+
+ /**
* ID assigned to this object
*/
protected long _id;
@@ -122,11 +127,6 @@ public abstract class JdwpId
}
/**
- * Returns size of this type (used by IDSizes)
- */
- public abstract int size ();
-
- /**
* Writes the contents of this type to the <code>DataOutputStream</code>
* @param outStream the <code>DataOutputStream</code> to use
* @throws IOException when an error occurs on the <code>OutputStream</code>
diff --git a/libjava/classpath/gnu/classpath/jdwp/id/ObjectId.java b/libjava/classpath/gnu/classpath/jdwp/id/ObjectId.java
index 3e2abd4f630..a4a37fd1312 100644
--- a/libjava/classpath/gnu/classpath/jdwp/id/ObjectId.java
+++ b/libjava/classpath/gnu/classpath/jdwp/id/ObjectId.java
@@ -1,5 +1,5 @@
/* ObjectId.java -- object IDs
- Copyright (C) 2005 Free Software Foundation
+ Copyright (C) 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -83,14 +83,6 @@ public class ObjectId
}
/**
- * Returns the size of this id type
- */
- public int size ()
- {
- return 8;
- }
-
- /**
* Returns the object referred to by this ID
*
* @returns the object
diff --git a/libjava/classpath/gnu/classpath/jdwp/id/ReferenceTypeId.java b/libjava/classpath/gnu/classpath/jdwp/id/ReferenceTypeId.java
index e7a5d2c3d83..b82acf34ab1 100644
--- a/libjava/classpath/gnu/classpath/jdwp/id/ReferenceTypeId.java
+++ b/libjava/classpath/gnu/classpath/jdwp/id/ReferenceTypeId.java
@@ -1,5 +1,5 @@
/* ReferenceTypeId.java -- a base class for all reference type IDs
- Copyright (C) 2005 Free Software Foundation
+ Copyright (C) 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -62,14 +62,6 @@ public class ReferenceTypeId
}
/**
- * Returns the size of this ID type
- */
- public int size ()
- {
- return 8;
- }
-
- /**
* Gets the class associated with this ID
*
* @returns the class
diff --git a/libjava/classpath/gnu/classpath/jdwp/processor/VirtualMachineCommandSet.java b/libjava/classpath/gnu/classpath/jdwp/processor/VirtualMachineCommandSet.java
index 6bdb236818c..a7edb287a56 100644
--- a/libjava/classpath/gnu/classpath/jdwp/processor/VirtualMachineCommandSet.java
+++ b/libjava/classpath/gnu/classpath/jdwp/processor/VirtualMachineCommandSet.java
@@ -1,6 +1,6 @@
/* VirtualMachineCommandSet.java -- class to implement the VirtualMachine
Command Set
- Copyright (C) 2005 Free Software Foundation
+ Copyright (C) 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -40,6 +40,7 @@ exception statement from your version. */
package gnu.classpath.jdwp.processor;
import gnu.classpath.jdwp.JdwpConstants;
+import gnu.classpath.jdwp.VMFrame;
import gnu.classpath.jdwp.VMVirtualMachine;
import gnu.classpath.jdwp.exception.JdwpException;
import gnu.classpath.jdwp.exception.JdwpInternalErrorException;
@@ -298,12 +299,11 @@ public class VirtualMachineCommandSet
private void executeIDsizes(ByteBuffer bb, DataOutputStream os)
throws JdwpException, IOException
{
- ObjectId oid = new ObjectId();
- os.writeInt(oid.size()); // fieldId
- os.writeInt(oid.size()); // methodId
- os.writeInt(oid.size()); // objectId
- os.writeInt(new ReferenceTypeId((byte) 0x00).size()); // referenceTypeId
- os.writeInt(oid.size()); // frameId
+ os.writeInt(ObjectId.SIZE); // fieldId FIXME
+ os.writeInt(ObjectId.SIZE); // methodId FIXME
+ os.writeInt(ObjectId.SIZE); // objectId
+ os.writeInt(ReferenceTypeId.SIZE); // referenceTypeId
+ os.writeInt(VMFrame.SIZE); // frameId
}
private void executeSuspend(ByteBuffer bb, DataOutputStream os)
diff --git a/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java
index 25735bb745f..daaa143d03b 100644
--- a/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java
@@ -229,9 +229,9 @@ public class GLightweightPeer
public void repaint(long tm, int x, int y, int width, int height)
{
- Component p = comp.getParent ();
- if(p != null)
- p.repaint(tm,x+comp.getX(),y+comp.getY(),width,height);
+ Component p = comp.getParent();
+ if (p != null)
+ p.repaint(tm, x + comp.getX(), y + comp.getY(), width, height);
}
public void requestFocus() {}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java
index 054ead6d601..63d9cd48715 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java
@@ -1,5 +1,5 @@
/* GtkButtonPeer.java -- Implements ButtonPeer with GTK
- Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -57,7 +57,10 @@ public class GtkButtonPeer extends GtkComponentPeer
public native void connectSignals ();
- native void gtkWidgetModifyFont (String name, int style, int size);
+ /**
+ * Overridden to set Font of Label inside Button inside EventBox.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
native void gtkSetLabel (String label);
native void gtkWidgetSetForeground (int red, int green, int blue);
native void gtkWidgetSetBackground (int red, int green, int blue);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java
index 01a6e3102d9..be9247e8d86 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java
@@ -1,5 +1,5 @@
/* GtkCheckboxMenuItemPeer.java -- Implements CheckboxMenuItemPeer with GTK+
- Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -46,7 +46,7 @@ import java.awt.peer.CheckboxMenuItemPeer;
public class GtkCheckboxMenuItemPeer extends GtkMenuItemPeer
implements CheckboxMenuItemPeer
{
- native void create (String label);
+ protected native void create (String label);
public GtkCheckboxMenuItemPeer (CheckboxMenuItem menu)
{
@@ -56,6 +56,11 @@ public class GtkCheckboxMenuItemPeer extends GtkMenuItemPeer
public native void setState(boolean t);
+ /**
+ * Called from the signal handler of the gtk widget. Posts a
+ * ItemEvent to indicate a state changed, then calls super to post
+ * an ActionEvent.
+ */
protected void postMenuActionEvent ()
{
CheckboxMenuItem item = (CheckboxMenuItem)awtWidget;
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
index 3e05cf8ab07..094aa3c0391 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
@@ -1,5 +1,5 @@
/* GtkCheckboxPeer.java -- Implements CheckboxPeer with GTK
- Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,6 +42,8 @@ import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.peer.CheckboxPeer;
+import java.awt.event.ItemEvent;
+
public class GtkCheckboxPeer extends GtkComponentPeer
implements CheckboxPeer
{
@@ -49,12 +51,15 @@ public class GtkCheckboxPeer extends GtkComponentPeer
public GtkCheckboxGroupPeer old_group;
// The current state of the GTK checkbox.
private boolean currentState;
- private boolean changing = false;
public native void create (GtkCheckboxGroupPeer group);
public native void nativeSetCheckboxGroup (GtkCheckboxGroupPeer group);
public native void connectSignals ();
- native void gtkWidgetModifyFont (String name, int style, int size);
+
+ /**
+ * Overridden to set Font of label inside button.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
native void gtkButtonSetLabel (String label);
native void gtkToggleButtonSetActive (boolean is_active);
@@ -71,23 +76,24 @@ public class GtkCheckboxPeer extends GtkComponentPeer
CheckboxGroup g = checkbox.getCheckboxGroup ();
old_group = GtkCheckboxGroupPeer.getCheckboxGroupPeer (g);
create (old_group);
- gtkToggleButtonSetActive (checkbox.getState ());
+ currentState = checkbox.getState();
+ gtkToggleButtonSetActive(currentState);
gtkButtonSetLabel (checkbox.getLabel ());
}
- public void setState (boolean state)
+ /**
+ * Sets native GtkCheckButton is state is different from current
+ * state. Will set currentState to state to prevent posting an
+ * event since events should only be posted for user initiated
+ * clicks on the GtkCheckButton.
+ */
+ synchronized public void setState (boolean state)
{
- // prevent item_toggled_cb -> postItemEvent ->
- // awtComponent.setState -> this.setState ->
- // gtkToggleButtonSetActive self-deadlock on the GDK lock.
- if (changing && Thread.currentThread() == GtkToolkit.mainThread)
+ if (currentState != state)
{
- changing = false;
- return;
+ currentState = state;
+ gtkToggleButtonSetActive(state);
}
-
- if (currentState != state)
- gtkToggleButtonSetActive (state);
}
public void setLabel (String label)
@@ -111,22 +117,15 @@ public class GtkCheckboxPeer extends GtkComponentPeer
// Override the superclass postItemEvent so that the peer doesn't
// need information that we have.
// called back by native side: item_toggled_cb
- public void postItemEvent (Object item, int stateChange)
+ synchronized public void postItemEvent(Object item, boolean state)
{
- Checkbox currentCheckBox = ((Checkbox)awtComponent);
- // A firing of the event is only desired if the state has changed due to a
- // button press. The currentCheckBox's state must be different from the
- // one that the stateChange is changing to.
- // stateChange = 1 if it goes from false -> true
- // stateChange = 2 if it goes from true -> false
- if (( !currentCheckBox.getState() && stateChange == 1)
- || (currentCheckBox.getState() && stateChange == 2))
- {
- super.postItemEvent (awtComponent, stateChange);
- currentState = !currentCheckBox.getState();
- changing = true;
- currentCheckBox.setState(currentState);
- }
+ // Only fire event is state actually changed.
+ if (currentState != state)
+ {
+ currentState = state;
+ super.postItemEvent(awtComponent,
+ state ? ItemEvent.SELECTED : ItemEvent.DESELECTED);
+ }
}
public void dispose ()
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java
index fe0dae70dd0..821183927b0 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java
@@ -1,5 +1,6 @@
/* GtkComponentPeer.java -- Implements ComponentPeer with GTK
- Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -46,10 +47,10 @@ import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
+import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
-import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Insets;
@@ -87,8 +88,6 @@ public class GtkComponentPeer extends GtkGenericPeer
boolean isInRepaint;
- static final Timer repaintTimer = new Timer (true);
-
/* this isEnabled differs from Component.isEnabled, in that it
knows if a parent is disabled. In that case Component.isEnabled
may return true, but our isEnabled will always return false */
@@ -146,12 +145,7 @@ public class GtkComponentPeer extends GtkGenericPeer
Component parent = awtComponent.getParent ();
- // Only set our parent on the GTK side if our parent on the AWT
- // side is not showing. Otherwise the gtk peer will be shown
- // before we've had a chance to position and size it properly.
- if (awtComponent instanceof Window
- || (parent != null && ! parent.isShowing ()))
- setParentAndBounds ();
+ setParentAndBounds ();
setNativeEventMask ();
@@ -202,11 +196,6 @@ public class GtkComponentPeer extends GtkGenericPeer
void setComponentBounds ()
{
Rectangle bounds = awtComponent.getBounds ();
-
- if (bounds.x == 0 && bounds.y == 0
- && bounds.width == 0 && bounds.height == 0)
- return;
-
setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
}
@@ -303,29 +292,29 @@ public class GtkComponentPeer extends GtkGenericPeer
{
case PaintEvent.PAINT:
case PaintEvent.UPDATE:
- {
- try
- {
- Graphics g = getGraphics ();
-
- // Some peers like GtkFileDialogPeer are repainted by Gtk itself
- if (g == null)
- break;
-
- g.setClip (((PaintEvent) event).getUpdateRect());
-
- if (id == PaintEvent.PAINT)
- awtComponent.paint (g);
- else
- awtComponent.update (g);
-
- g.dispose ();
- }
- catch (InternalError e)
- {
- System.err.println (e);
- }
- }
+ {
+ try
+ {
+ Graphics g = getGraphics();
+
+ if (!awtComponent.isShowing() || awtComponent.getWidth() < 1
+ || awtComponent.getHeight() < 1 || g == null)
+ break;
+
+ g.setClip(((PaintEvent) event).getUpdateRect());
+
+ if (id == PaintEvent.PAINT)
+ awtComponent.paint(g);
+ else
+ awtComponent.update(g);
+
+ g.dispose();
+ }
+ catch (InternalError e)
+ {
+ System.err.println(e);
+ }
+ }
break;
case KeyEvent.KEY_PRESSED:
ke = (KeyEvent) event;
@@ -383,19 +372,30 @@ public class GtkComponentPeer extends GtkGenericPeer
if (x == 0 && y == 0 && width == 0 && height == 0)
return;
- repaintTimer.schedule(new RepaintTimerTask(x, y, width, height), tm);
+ if (tm <= 0)
+ q().postEvent(new PaintEvent(awtComponent, PaintEvent.UPDATE,
+ new Rectangle(x, y, width, height)));
+ else
+ RepaintTimerTask.schedule(tm, x, y, width, height, awtComponent);
}
- private class RepaintTimerTask extends TimerTask
+ /**
+ * Used for scheduling delayed paint updates on the event queue.
+ */
+ private static class RepaintTimerTask extends TimerTask
{
+ private static final Timer repaintTimer = new Timer(true);
+
private int x, y, width, height;
+ private Component awtComponent;
- RepaintTimerTask(int x, int y, int width, int height)
+ RepaintTimerTask(Component c, int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
+ this.awtComponent = c;
}
public void run()
@@ -403,6 +403,12 @@ public class GtkComponentPeer extends GtkGenericPeer
q().postEvent (new PaintEvent (awtComponent, PaintEvent.UPDATE,
new Rectangle (x, y, width, height)));
}
+
+ static void schedule(long tm, int x, int y, int width, int height,
+ Component c)
+ {
+ repaintTimer.schedule(new RepaintTimerTask(c, x, y, width, height), tm);
+ }
}
public void requestFocus ()
@@ -429,8 +435,7 @@ public class GtkComponentPeer extends GtkGenericPeer
int new_y = y;
Component parent = awtComponent.getParent ();
- Component next_parent;
-
+
// Heavyweight components that are children of one or more
// lightweight containers have to be handled specially. Because
// calls to GLightweightPeer.setBounds do nothing, GTK has no
@@ -441,33 +446,19 @@ public class GtkComponentPeer extends GtkGenericPeer
// so we need to continue adding offsets until we reach a
// container whose position GTK knows -- that is, the first
// non-lightweight.
- boolean lightweightChild = false;
- Insets i;
- while (parent.isLightweight ())
+ Insets i;
+ while (parent.isLightweight())
{
- lightweightChild = true;
-
- next_parent = parent.getParent ();
-
- i = ((Container) parent).getInsets ();
-
- if (next_parent instanceof Window)
- {
- new_x += i.left;
- new_y += i.top;
- }
- else
- {
- new_x += parent.getX () + i.left;
- new_y += parent.getY () + i.top;
- }
-
- parent = next_parent;
+ i = ((Container) parent).getInsets();
+
+ new_x += parent.getX() + i.left;
+ new_y += parent.getY() + i.top;
+
+ parent = parent.getParent();
}
-
// We only need to convert from Java to GTK coordinates if we're
// placing a heavyweight component in a Window.
- if (parent instanceof Window && !lightweightChild)
+ if (parent instanceof Window)
{
GtkWindowPeer peer = (GtkWindowPeer) parent.getPeer ();
// important: we want the window peer's insets here, not the
@@ -479,12 +470,17 @@ public class GtkComponentPeer extends GtkGenericPeer
int menuBarHeight = 0;
if (peer instanceof GtkFramePeer)
menuBarHeight = ((GtkFramePeer) peer).getMenuBarHeight ();
-
- new_x = x - insets.left;
- new_y = y - insets.top + menuBarHeight;
+
+ new_x -= insets.left;
+ new_y -= insets.top;
+ new_y += menuBarHeight;
}
setNativeBounds (new_x, new_y, width, height);
+
+ // If the height or width were (or are now) smaller than zero
+ // then we want to adjust the visibility.
+ setVisible(awtComponent.isVisible());
}
void setCursor ()
@@ -535,6 +531,13 @@ public class GtkComponentPeer extends GtkGenericPeer
public void setVisible (boolean b)
{
+ // Only really set visible when component is bigger than zero pixels.
+ if (b)
+ {
+ Rectangle bounds = awtComponent.getBounds();
+ b = (bounds.width > 0) && (bounds.height > 0);
+ }
+
if (Thread.currentThread() == GtkToolkit.mainThread)
setVisibleNativeUnlocked (b);
else
@@ -571,6 +574,8 @@ public class GtkComponentPeer extends GtkGenericPeer
KeyEvent keyEvent = new KeyEvent (awtComponent, id, when, mods,
keyCode, keyChar, keyLocation);
+ EventQueue q = q();
+
// Also post a KEY_TYPED event if keyEvent is a key press that
// doesn't represent an action or modifier key.
if (keyEvent.getID () == KeyEvent.KEY_PRESSED
@@ -579,15 +584,17 @@ public class GtkComponentPeer extends GtkGenericPeer
&& keyCode != KeyEvent.VK_CONTROL
&& keyCode != KeyEvent.VK_ALT))
{
- synchronized (q)
- {
- q().postEvent (keyEvent);
- q().postEvent (new KeyEvent (awtComponent, KeyEvent.KEY_TYPED, when, mods,
- KeyEvent.VK_UNDEFINED, keyChar, keyLocation));
+ synchronized(q)
+ {
+ q.postEvent(keyEvent);
+ keyEvent = new KeyEvent(awtComponent, KeyEvent.KEY_TYPED, when,
+ mods, KeyEvent.VK_UNDEFINED, keyChar,
+ keyLocation);
+ q.postEvent(keyEvent);
}
}
else
- q().postEvent (keyEvent);
+ q.postEvent(keyEvent);
}
protected void postFocusEvent (int id, boolean temporary)
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java
index b035a9814c7..23737b0b0a0 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java
@@ -1,5 +1,5 @@
/* GtkContainerPeer.java -- Implements ContainerPeer with GTK
- Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -65,29 +65,6 @@ public class GtkContainerPeer extends GtkComponentPeer
public void endValidate ()
{
- Component parent = awtComponent.getParent ();
-
- // Only set our parent on the GTK side if our parent on the AWT
- // side is not showing. Otherwise the gtk peer will be shown
- // before we've had a chance to position and size it properly.
- if (parent != null && parent.isShowing ())
- {
- Component[] components = ((Container) awtComponent).getComponents ();
- int ncomponents = components.length;
-
- for (int i = 0; i < ncomponents; i++)
- {
- ComponentPeer peer = components[i].getPeer ();
-
- // Skip lightweight peers.
- if (peer instanceof GtkComponentPeer)
- ((GtkComponentPeer) peer).setParentAndBounds ();
- }
-
- // GTK windows don't have parents.
- if (!(awtComponent instanceof Window))
- setParentAndBounds ();
- }
}
public Insets getInsets()
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
index 333407b247f..a0ae9e9eef5 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
@@ -41,8 +41,6 @@ package gnu.java.awt.peer.gtk;
import java.awt.Dialog;
import java.awt.FileDialog;
import java.awt.Graphics;
-import java.awt.Window;
-import java.awt.event.ComponentEvent;
import java.awt.peer.FileDialogPeer;
import java.io.File;
import java.io.FilenameFilter;
@@ -68,7 +66,8 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
((FileDialog) awtComponent).getMode());
FileDialog fd = (FileDialog) awtComponent;
-
+
+ nativeSetDirectory(System.getProperty("user.dir"));
setDirectory(fd.getDirectory());
setFile(fd.getFile());
@@ -117,13 +116,9 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
// is not absolute, let's construct it based on current directory.
currentFile = fileName;
if (fileName.indexOf(FS) == 0)
- {
- nativeSetFile (fileName);
- }
+ nativeSetFile(fileName);
else
- {
- nativeSetFile (nativeGetDirectory() + FS + fileName);
- }
+ nativeSetFile(nativeGetDirectory() + FS + fileName);
}
public void setDirectory (String directory)
@@ -132,18 +127,24 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
the only way we have to set the directory in FileDialog is by
calling its setDirectory which will call us back. */
if ((directory == null && currentDirectory == null)
- || (directory != null && directory.equals (currentDirectory)))
+ || (directory != null && directory.equals(currentDirectory)))
return;
- if (directory == null || directory.equals (""))
+ if (directory == null || directory.equals(""))
{
currentDirectory = FS;
- nativeSetFile (FS);
- return;
+ nativeSetDirectory(FS);
+ return;
}
-
+
+ // GtkFileChooser requires absolute directory names. If the given directory
+ // name is not absolute, construct it based on current directory if it is not
+ // null. Otherwise, use FS.
currentDirectory = directory;
- nativeSetDirectory (directory);
+ if (directory.indexOf(FS) == 0)
+ nativeSetDirectory(directory);
+ else
+ nativeSetDirectory(nativeGetDirectory() + FS + directory);
}
public void setFilenameFilter (FilenameFilter filter)
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java
index 99cca0cffa7..f59e781c2a4 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java
@@ -43,10 +43,7 @@ import java.awt.Graphics;
import java.awt.Image;
import java.awt.MenuBar;
import java.awt.Rectangle;
-import java.awt.Window;
-import java.awt.event.ComponentEvent;
import java.awt.event.PaintEvent;
-import java.awt.image.ColorModel;
import java.awt.peer.FramePeer;
import java.awt.peer.MenuBarPeer;
@@ -77,7 +74,10 @@ public class GtkFramePeer extends GtkWindowPeer
removeMenuBarPeer ();
insets.top -= menuBarHeight;
menuBarHeight = 0;
- awtComponent.validate ();
+ // if component has already been validated, we need to revalidate.
+ // otherwise, it will be validated when it is shown.
+ if (awtComponent.isValid())
+ awtComponent.validate ();
gtkFixedSetVisible (true);
}
else if (bar != null && menuBar == null)
@@ -92,7 +92,10 @@ public class GtkFramePeer extends GtkWindowPeer
setMenuBarWidth (menuBar, menuBarWidth);
menuBarHeight = getMenuBarHeight ();
insets.top += menuBarHeight;
- awtComponent.validate ();
+ // if component has already been validated, we need to revalidate.
+ // otherwise, it will be validated when it is shown.
+ if (awtComponent.isValid())
+ awtComponent.validate ();
gtkFixedSetVisible (true);
}
else if (bar != null && menuBar != null)
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java
index 705eed2351b..468c46dc4af 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java
@@ -1,5 +1,5 @@
/* GtkGenericPeer.java - Has a hashcode. Yuck.
- Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2002, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,23 +39,28 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.EventQueue;
+import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
public class GtkGenericPeer
{
+ // Used by Native State Association (NSA) functions to map
+ // gtk_widget to peer object.
final int native_state = getUniqueInteger ();
// Next native state value we will assign.
private static int next_native_state = 0;
// The widget or other java-side object we wrap.
- protected Object awtWidget;
-
- // Global event queue.
- protected static EventQueue q = null;
-
- // Dispose of our native state.
+ protected final Object awtWidget;
+
+ /**
+ * Dispose of our native state. Calls gtk_widget_destroy on the
+ * native widget and removes the awtWidget from the native state
+ * tables. Should be overridden by subclasses if this is not (all)
+ * that needs to be done.
+ */
public native void dispose ();
static EventQueue q ()
@@ -68,12 +73,6 @@ public class GtkGenericPeer
this.awtWidget = awtWidget;
}
- public static void enableQueue (EventQueue sq)
- {
- if (q == null)
- q = sq;
- }
-
protected void postActionEvent (String command, int mods)
{
q().postEvent (new ActionEvent (awtWidget, ActionEvent.ACTION_PERFORMED,
@@ -88,8 +87,20 @@ public class GtkGenericPeer
// Let's assume this will never wrap.
return next_native_state++;
}
+
+ /**
+ * Helper method to set Font for Gtk Widget.
+ */
+ protected void gtkWidgetModifyFont(Font f)
+ {
+ gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize());
+ }
- native void gtkWidgetModifyFont (String name, int style, int size);
+ /**
+ * Sets font for this Gtk Widget. Should be overridden by peers which
+ * are composed of different widgets or are contained in bins.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
static void printCurrentThread ()
{
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java
index 82a346304ea..b48a2049e27 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java
@@ -1,5 +1,5 @@
/* GtkImage.java
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -329,6 +329,24 @@ public class GtkImage extends Image
props = new Hashtable();
}
+ // The singleton GtkImage that is returned on errors by GtkToolkit.
+ private static GtkImage errorImage;
+
+ /**
+ * Returns an empty GtkImage with the errorLoading flag set.
+ * Called from GtkToolKit when some error occured, but an image needs
+ * to be returned anyway.
+ */
+ static synchronized GtkImage getErrorImage()
+ {
+ if (errorImage == null)
+ {
+ errorImage = new GtkImage();
+ errorImage.errorLoading = true;
+ }
+ return errorImage;
+ }
+
/**
* Native helper function for constructor that takes a pixbuf Pointer.
*/
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java
index 3d099e9ca00..bbf4230b3ca 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java
@@ -1,5 +1,5 @@
/* GtkLabelPeer.java -- Implements LabelPeer with GTK
- Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -48,7 +48,12 @@ public class GtkLabelPeer extends GtkComponentPeer
implements LabelPeer
{
native void create (String text, float alignment);
- native void gtkWidgetModifyFont (String name, int style, int size);
+
+ /**
+ * Overridden to set the Font of the label inside the gtk_event_box.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+
native void nativeSetAlignment (float alignment);
public native void setText(String text);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java
index ff12fe34bba..285f79416f3 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java
@@ -1,5 +1,5 @@
/* GtkListPeer.java -- Implements ListPeer with GTK
- Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -59,7 +59,12 @@ public class GtkListPeer extends GtkComponentPeer
native void create (int rows);
native void connectSignals ();
- native void gtkWidgetModifyFont (String name, int style, int size);
+
+ /**
+ * Overridden to set the Font of the text insode the gtk_scrolled_window.
+ */
+ protected native void gtkWidgetModifyFont (String name, int style, int size);
+
native void gtkWidgetRequestFocus ();
native void getSize (int rows, int visibleRows, int dims[]);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
index a1a1cbd6d7c..d203b437f38 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
@@ -1,5 +1,5 @@
/* GtkMenuBarPeer.java -- Implements MenuBarPeer with GTK+
- Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -48,38 +48,69 @@ import java.awt.peer.MenuPeer;
public class GtkMenuBarPeer extends GtkMenuComponentPeer
implements MenuBarPeer
{
-
- native void create ();
- native void addMenu (MenuPeer menu);
-
- public GtkMenuBarPeer (MenuBar target)
+ /** Whether we already have an help menu set on this peer. */
+ private boolean hasHelpMenu;
+
+ /**
+ * Creates the gtk+ widget for this peer and puts it in the nsa
+ * table. Called from the (super class) constructor.
+ */
+ protected native void create();
+
+ /**
+ * Adds a new GtkMenuPeer to the end of the GtkMenuBarPeer.
+ */
+ private native void addMenu(GtkMenuPeer menu);
+
+ /**
+ * Creates a new GtkMenuBarPeer associated with the given MenuBar.
+ */
+ public GtkMenuBarPeer(MenuBar menubar)
{
- super (target);
+ super(menubar);
}
- void setFont ()
- {
- MenuComponent mc = (MenuComponent) awtWidget;
- Font f = mc.getFont ();
-
- if (f == null)
- mc.setFont (new Font ("Dialog", Font.PLAIN, 12));
- }
-
- // FIXME: remove this method or replace it with one that does
- // something useful.
- /* In Gnome, help menus are no longer right flushed. */
- native void nativeSetHelpMenu(MenuPeer menuPeer);
-
+ /**
+ * Adds a help menu to this MenuBar. Gnome styleguides say the help
+ * menu is just the last item in the menubar (they are NOT right
+ * justified).
+ */
public void addHelpMenu (Menu menu)
{
- // nativeSetHelpMenu((MenuPeer) menu.getPeer());
+ if (hasHelpMenu)
+ {
+ // Remove the (help) menu, which is after all the other items.
+ delMenu(((MenuBar) awtWidget).getMenuCount());
+ hasHelpMenu = false;
+ }
+
+ if (menu != null)
+ {
+ addMenu(menu);
+ hasHelpMenu = true;
+ }
}
+ /**
+ * Deletes the menu at (zero-based) index from this GtkMenuBar.
+ */
public native void delMenu(int index);
- public void addMenu (Menu m)
+ /**
+ * Adds the GtkMenuPeer associated with the Menu to this
+ * GtkMenuBarPeer. Makes sure that any help menus keep the last menu
+ * on the bar.
+ */
+ public void addMenu(Menu m)
{
- // FIXME: implement
+ // Make sure the help menu is the last one.
+ if (hasHelpMenu)
+ {
+ addHelpMenu(null);
+ addMenu((GtkMenuPeer) m.getPeer());
+ addHelpMenu(((MenuBar) awtWidget).getHelpMenu());
+ }
+ else
+ addMenu((GtkMenuPeer) m.getPeer());
}
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java
index 4c6335933a8..55b95a18d0f 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java
@@ -1,5 +1,5 @@
/* GtkMenuComponentPeer.java -- Implements MenuComponentPeer with GTK+
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,31 +39,66 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Font;
+import java.awt.MenuComponent;
+import java.awt.MenuContainer;
import java.awt.peer.MenuComponentPeer;
-public class GtkMenuComponentPeer extends GtkGenericPeer
+public abstract class GtkMenuComponentPeer extends GtkGenericPeer
implements MenuComponentPeer
{
- void create ()
- {
- throw new RuntimeException ();
- }
+ /**
+ * Creates the associated gtk+ widget and stores it in the nsa table
+ * for this peer. Called by the constructor.
+ */
+ protected abstract void create ();
- void setFont ()
+ /**
+ * Sets font based on MenuComponent font, or containing menu(bar)
+ * parent font.
+ */
+ private void setFont()
{
+ MenuComponent mc = ((MenuComponent) awtWidget);
+ Font f = mc.getFont();
+
+ if (f == null)
+ {
+ MenuContainer parent = mc.getParent ();
+ // Submenus inherit the font of their containing Menu(Bar).
+ if (parent instanceof MenuComponent)
+ f = parent.getFont ();
+ }
+
+ setFont(f);
}
- public GtkMenuComponentPeer (Object awtWidget)
+ /**
+ * Will call the abstract <code>create()</code> that needs to be
+ * overridden by subclasses, to create the MenuComponent. It will
+ * then correctly setup the font for the component based on the
+ * component and/or its containing parent component.
+ */
+ public GtkMenuComponentPeer(MenuComponent component)
{
- super (awtWidget);
- create ();
- setFont ();
+ super(component);
+ create();
+ setFont();
}
+ /**
+ * Removes the awtWidget components from the native state tables.
+ * Subclasses should call <code>super.dispose()</code> if they don't
+ * remove these themselves.
+ */
public native void dispose();
+ /**
+ * Sets the font for this particular MenuComponent only (not any
+ * containing items, if any).
+ */
public void setFont(Font font)
{
- // FIXME: implement
+ if (font != null)
+ gtkWidgetModifyFont(font);
}
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java
index 5728f262b13..251bab233d7 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java
@@ -1,5 +1,5 @@
/* GtkMenuItemPeer.java -- Implements MenuItemPeer with GTK+
- Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,70 +49,71 @@ import java.awt.peer.MenuPeer;
public class GtkMenuItemPeer extends GtkMenuComponentPeer
implements MenuItemPeer
{
- native void create (String label);
- native void connectSignals ();
- native void gtkWidgetModifyFont (String name, int style, int size);
-
- void create ()
+ /**
+ * Creates the associated gtk+ widget and stores it in the nsa table
+ * for this peer. Called by the create() method with the label name
+ * of the associated MenuItem. Needs to be overridden my subclasses
+ * that want to create a different gtk+ widget.
+ */
+ protected native void create (String label);
+
+ /**
+ * Called from constructor to enable signals from an item. If a
+ * subclass needs different (or no) signals connected this method
+ * should be overridden.
+ */
+ protected native void connectSignals ();
+
+ /**
+ * Overridden to set font on menu item label.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+
+ /**
+ * Creates the associated gtk+ widget and stores it in the nsa table
+ * for this peer. Called by the (super class) constructor.
+ * Overridden to get the label if the assiociated MenuItem and to
+ * call create(String).
+ */
+ protected void create()
{
create (((MenuItem) awtWidget).getLabel());
}
- public GtkMenuItemPeer (MenuItem item)
- {
- super (item);
- setEnabled (item.isEnabled ());
- setParent (item);
-
- if (item.getParent() instanceof Menu && ! (item instanceof Menu))
- connectSignals();
- }
-
- void setFont ()
+ /**
+ * Creates a new GtkMenuItemPeer associated with the given MenuItem.
+ * It will call create(), setFont(), setEnabled() and
+ * connectSignals() in that order.
+ */
+ public GtkMenuItemPeer(MenuItem item)
{
- MenuComponent mc = ((MenuComponent) awtWidget);
- Font f = mc.getFont ();
-
- if (f == null)
- {
- MenuComponent parent = (MenuComponent) mc.getParent ();
- Font pf = parent.getFont ();
- gtkWidgetModifyFont (pf.getName (), pf.getStyle (), pf.getSize ());
- }
- else
- gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize());
+ super(item);
+ setEnabled (item.isEnabled());
+ connectSignals();
}
- void setParent (MenuItem item)
+ /**
+ * Calls setEnabled(false).
+ */
+ public void disable()
{
- // add ourself differently, based on what type of parent we have
- // yes, the typecasting here is nasty.
- Object parent = item.getParent ();
- if (parent instanceof MenuBar)
- {
- ((GtkMenuBarPeer)((MenuBar)parent).getPeer ()).addMenu ((MenuPeer) this);
- }
- else // parent instanceof Menu
- {
- ((GtkMenuPeer)((Menu)parent).getPeer ()).addItem (this,
- item.getShortcut ());
- }
+ setEnabled(false);
}
- public void disable ()
+ /**
+ * Calls setEnabled(true).
+ */
+ public void enable()
{
- setEnabled (false);
- }
-
- public void enable ()
- {
- setEnabled (true);
+ setEnabled(true);
}
public native void setEnabled(boolean b);
-
public native void setLabel(String label);
+ /**
+ * Callback setup through connectSignals().
+ */
protected void postMenuActionEvent ()
{
postActionEvent (((MenuItem)awtWidget).getActionCommand (), 0);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java
index fabcf1f090b..1d581c1a15c 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java
@@ -1,5 +1,5 @@
/* GtkMenuPeer.java -- Implements MenuPeer with GTK+
- Copyright (C) 1999, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,10 +49,28 @@ import java.awt.peer.MenuPeer;
public class GtkMenuPeer extends GtkMenuItemPeer
implements MenuPeer
{
- native void create (String label);
- native void addItem (MenuItemPeer item, int key, boolean shiftModifier);
+ /**
+ * Creates the associated gtk+ widget and stores it in the nsa table
+ * for this peer. Called by the create() method with the label name
+ * of the associated MenuItem. Overridden to greate a Menu widget.
+ */
+ protected native void create (String label);
+
+ private native void addItem(MenuItemPeer item, int key,
+ boolean shiftModifier);
+
+ /** XXX - Document this and the override in GtkPopupMenuPeer. */
native void setupAccelGroup (GtkGenericPeer container);
- native void addTearOff ();
+
+ private native void addTearOff ();
+
+ /**
+ * Overridden to not connect any signals.
+ */
+ protected void connectSignals()
+ {
+ // No signals to connect.
+ }
public GtkMenuPeer (Menu menu)
{
@@ -63,11 +81,11 @@ public class GtkMenuPeer extends GtkMenuItemPeer
MenuContainer parent = menu.getParent ();
if (parent instanceof Menu)
- setupAccelGroup ((GtkGenericPeer)((Menu)parent).getPeer ());
+ setupAccelGroup ((GtkMenuPeer)((Menu)parent).getPeer ());
else if (parent instanceof Component)
- setupAccelGroup ((GtkGenericPeer)((Component)parent).getPeer ());
+ setupAccelGroup ((GtkComponentPeer)((Component)parent).getPeer ());
else
- setupAccelGroup (null);
+ setupAccelGroup (null); // XXX, should we warn about unknown parent?
}
public void addItem (MenuItem item)
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java
index fb5addeb442..88bb715694d 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java
@@ -39,8 +39,11 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.AWTEvent;
+import java.awt.Graphics;
import java.awt.Panel;
+import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
+import java.awt.event.PaintEvent;
import java.awt.peer.PanelPeer;
public class GtkPanelPeer extends GtkContainerPeer
@@ -53,17 +56,39 @@ public class GtkPanelPeer extends GtkContainerPeer
super (p);
}
- public void handleEvent (AWTEvent event)
+ public void handleEvent(AWTEvent event)
{
int id = event.getID();
-
switch (id)
{
case MouseEvent.MOUSE_PRESSED:
- awtComponent.requestFocusInWindow ();
+ awtComponent.requestFocusInWindow();
break;
+ case PaintEvent.UPDATE:
+ case PaintEvent.PAINT:
+ {
+ try
+ {
+ Graphics g = getGraphics();
+ if (! awtComponent.isShowing() || awtComponent.getWidth() < 1
+ || awtComponent.getHeight() < 1 || g == null)
+ return;
+
+ g.setClip(((PaintEvent) event).getUpdateRect());
+
+ // Do not want to clear anything before painting.);
+ awtComponent.paint(g);
+
+ g.dispose();
+ return;
+ }
+ catch (InternalError e)
+ {
+ System.err.println(e);
+ }
+ }
}
- super.handleEvent (event);
+ super.handleEvent(event);
}
native void connectSignals ();
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java
index d14c16dd79d..525a910bc1b 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java
@@ -1,5 +1,5 @@
/* GtkPopupMenuPeer.java -- Implements PopupMenuPeer with GTK+
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -55,11 +55,6 @@ public class GtkPopupMenuPeer extends GtkMenuPeer
native void setupAccelGroup (GtkGenericPeer container);
- void setParent (MenuItem item)
- {
- // we don't need to "add" ourselves to our parent
- }
-
native void show (int x, int y, long time);
public void show (Component origin, int x, int y)
{
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
index aa3a26e34ad..9b31a7390e0 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
@@ -1,5 +1,5 @@
/* GtkScrollbarPeer.java -- Implements ScrollbarPeer with GTK+
- Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Adjustable;
+import java.awt.EventQueue;
import java.awt.Scrollbar;
import java.awt.event.AdjustmentEvent;
import java.awt.peer.ScrollbarPeer;
@@ -69,12 +70,25 @@ public class GtkScrollbarPeer extends GtkComponentPeer
public native void setLineIncrement(int amount);
public native void setPageIncrement(int amount);
- public native void setValues(int value, int visible, int min, int max);
+ public void setValues(int value, int visible, int min, int max)
+ {
+ Scrollbar sb = (Scrollbar) awtComponent;
+ if (!sb.getValueIsAdjusting())
+ setBarValues(value, visible, min, max);
+ }
+
+ private native void setBarValues(int value, int visible, int min, int max);
+
+ /**
+ * Called from the native site when the scrollbar changed.
+ * Posts a "user generated" AdjustmentEvent to the queue.
+ */
protected void postAdjustmentEvent (int type, int value)
{
- q().postEvent (new AdjustmentEvent ((Adjustable)awtComponent,
+ Scrollbar bar = (Scrollbar) awtComponent;
+ q().postEvent(new AdjustmentEvent(bar,
AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
- type, value));
+ type, value, true));
}
}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
index e6896c9136c..5d9be1aec63 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
@@ -55,7 +55,11 @@ public class GtkTextAreaPeer extends GtkComponentPeer
native void create (int width, int height, int scrollbarVisibility);
- native void gtkWidgetModifyFont (String name, int style, int size);
+ /**
+ * Overridden to set Font for text widget inside scrolled window.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+
native void gtkWidgetRequestFocus ();
public native void connectSignals ();
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
index 4afdae82e5e..763304864e0 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
@@ -112,8 +112,6 @@ public class GtkTextFieldPeer extends GtkComponentPeer
native int gtkEntryGetBorderWidth ();
- native void gtkWidgetModifyFont (String name, int style, int size);
-
public GtkTextFieldPeer (TextField tf)
{
super (tf);
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java
index 0889d85f4bc..70e25a31957 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java
@@ -1,5 +1,6 @@
/* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers
- Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -159,137 +160,93 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
}
/**
- * A helper class to return to clients in cases where a BufferedImage is
- * desired but its construction fails.
+ * Helper to return either a Image -- the argument -- or a
+ * GtkImage with the errorLoading flag set if the argument is null.
*/
- private class GtkErrorImage extends Image
- {
- public GtkErrorImage()
- {
- }
-
- public int getWidth(ImageObserver observer)
- {
- return -1;
- }
-
- public int getHeight(ImageObserver observer)
- {
- return -1;
- }
-
- public ImageProducer getSource()
- {
-
- return new ImageProducer()
- {
- HashSet consumers = new HashSet();
- public void addConsumer(ImageConsumer ic)
- {
- consumers.add(ic);
- }
-
- public boolean isConsumer(ImageConsumer ic)
- {
- return consumers.contains(ic);
- }
-
- public void removeConsumer(ImageConsumer ic)
- {
- consumers.remove(ic);
- }
-
- public void startProduction(ImageConsumer ic)
- {
- consumers.add(ic);
- Iterator i = consumers.iterator();
- while(i.hasNext())
- {
- ImageConsumer c = (ImageConsumer) i.next();
- c.imageComplete(ImageConsumer.IMAGEERROR);
- }
- }
- public void requestTopDownLeftRightResend(ImageConsumer ic)
- {
- startProduction(ic);
- }
- };
- }
-
- public Graphics getGraphics()
- {
- return null;
- }
-
- public Object getProperty(String name, ImageObserver observer)
- {
- return null;
- }
- public Image getScaledInstance(int width, int height, int flags)
- {
- return new GtkErrorImage();
- }
-
- public void flush()
- {
- }
- }
-
-
- /**
- * Helper to return either a BufferedImage -- the argument -- or a
- * GtkErrorImage if the argument is null.
- */
-
- private Image bufferedImageOrError(BufferedImage b)
+ private Image imageOrError(Image b)
{
if (b == null)
- return new GtkErrorImage();
+ return GtkImage.getErrorImage();
else
return b;
}
-
public Image createImage (String filename)
{
if (filename.length() == 0)
return new GtkImage ();
-
- if (useGraphics2D())
- return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (filename));
- else
- return new GtkImage (filename);
+
+ Image image;
+ try
+ {
+ if (useGraphics2D())
+ image = GdkPixbufDecoder.createBufferedImage(filename);
+ else
+ image = new GtkImage(filename);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ image = null;
+ }
+ return imageOrError(image);
}
public Image createImage (URL url)
{
- if (useGraphics2D())
- return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (url));
- else
- return new GtkImage (url);
+ Image image;
+ try
+ {
+ if (useGraphics2D())
+ image = GdkPixbufDecoder.createBufferedImage(url);
+ else
+ image = new GtkImage(url);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ image = null;
+ }
+ return imageOrError(image);
}
public Image createImage (ImageProducer producer)
{
- if (useGraphics2D())
- return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (producer));
- else
- return new GtkImage (producer);
+ Image image;
+ try
+ {
+ if (useGraphics2D())
+ image = GdkPixbufDecoder.createBufferedImage(producer);
+ else
+ image = new GtkImage(producer);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ image = null;
+ }
+ return imageOrError(image);
}
public Image createImage (byte[] imagedata, int imageoffset,
int imagelength)
{
- if (useGraphics2D())
- return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (imagedata,
- imageoffset,
- imagelength));
- else
+ Image image;
+ try
+ {
+ if (useGraphics2D())
+ image = GdkPixbufDecoder.createBufferedImage(imagedata,
+ imageoffset,
+ imagelength);
+ else
+ {
+ byte[] datacopy = new byte[imagelength];
+ System.arraycopy(imagedata, imageoffset, datacopy, 0, imagelength);
+ return new GtkImage(datacopy);
+ }
+ }
+ catch (IllegalArgumentException iae)
{
- byte[] datacopy = new byte[imagelength];
- System.arraycopy (imagedata, imageoffset, datacopy, 0, imagelength);
- return new GtkImage (datacopy);
+ image = null;
}
+ return imageOrError(image);
}
/**
@@ -608,7 +565,6 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
if (q == null)
{
q = new EventQueue();
- GtkGenericPeer.enableQueue (q);
}
}
return q;
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java
index 57fb87f37bf..6cc1390ea39 100644
--- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java
@@ -38,9 +38,12 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
+import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Frame;
+import java.awt.Graphics;
import java.awt.Window;
+import java.awt.event.PaintEvent;
import java.awt.event.WindowEvent;
import java.awt.peer.WindowPeer;
@@ -123,7 +126,23 @@ public class GtkWindowPeer extends GtkContainerPeer
native void nativeSetBounds (int x, int y, int width, int height);
native void nativeSetBoundsUnlocked (int x, int y, int width, int height);
+ native void nativeSetLocation (int x, int y);
+ native void nativeSetLocationUnlocked (int x, int y);
+ public void setLocation (int x, int y)
+ {
+ // prevent window_configure_cb -> awtComponent.setSize ->
+ // peer.setBounds -> nativeSetBounds self-deadlock on GDK lock.
+ if (Thread.currentThread() == GtkToolkit.mainThread)
+ return;
+ nativeSetLocation (x, y);
+ }
+
+ public void setLocationUnlocked (int x, int y)
+ {
+ nativeSetLocationUnlocked (x, y);
+ }
+
public void setBounds (int x, int y, int width, int height)
{
// prevent window_configure_cb -> awtComponent.setSize ->
@@ -192,12 +211,7 @@ public class GtkWindowPeer extends GtkContainerPeer
public void show ()
{
- // Prevent the window manager from automatically placing this
- // window when it is shown.
- setBounds (awtComponent.getX(),
- awtComponent.getY(),
- awtComponent.getWidth(),
- awtComponent.getHeight());
+ setLocation(awtComponent.getX(), awtComponent.getY());
setVisible (true);
}
@@ -235,4 +249,32 @@ public class GtkWindowPeer extends GtkContainerPeer
// TODO Auto-generated method stub
return false;
}
+
+ public void handleEvent(AWTEvent event)
+ {
+ int id = event.getID();
+ if (id == PaintEvent.UPDATE || id == PaintEvent.PAINT)
+ {
+ try
+ {
+ Graphics g = getGraphics();
+ if (! awtComponent.isShowing() || awtComponent.getWidth() < 1
+ || awtComponent.getHeight() < 1 || g == null)
+ return;
+
+ g.setClip(((PaintEvent) event).getUpdateRect());
+
+ // Do not want to clear anything before painting.
+ awtComponent.paint(g);
+
+ g.dispose();
+ return;
+ }
+ catch (InternalError e)
+ {
+ System.err.println(e);
+ }
+ }
+ super.handleEvent(event);
+ }
}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java
new file mode 100644
index 00000000000..2357fcbfb0d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java
@@ -0,0 +1,224 @@
+/* SwingButtonPeer.java -- A Swing based peer for AWT buttons
+ 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.java.awt.peer.swing;
+
+import java.awt.Button;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ButtonPeer;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+
+/**
+ * A Swing based peer for the AWT button.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingButtonPeer
+ extends SwingComponentPeer
+ implements ButtonPeer
+{
+
+ /**
+ * A specialized Swing button to be used as AWT button.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ class SwingButton
+ extends JButton
+ implements SwingComponent
+ {
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingButtonPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (SwingButtonPeer.this.awtComponent != null)
+ retVal = SwingButtonPeer.this.awtComponent.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingButtonPeer.this.createImage(w, h);
+ }
+
+ /**
+ * Overridden, so that the Swing button can create a Graphics without its
+ * own peer.
+ *
+ * @return a graphics instance for the button
+ */
+ public Graphics getGraphics()
+ {
+ return SwingButtonPeer.this.getGraphics();
+ }
+
+ /**
+ * Returns this button.
+ *
+ * @return this button
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code> after having retargetted it to this
+ * button.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code> after having retargetted it to
+ * this button.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to
+ * <code>processKeyEvent()</code> after having retargetted it to this
+ * button.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ ev.setSource(this);
+ processKeyEvent(ev);
+ }
+ }
+
+ /**
+ * Listens for ActionEvents on the Swing button and triggers corresponding
+ * ActionEvents on the AWT button.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ class SwingButtonListener implements ActionListener
+ {
+
+ /**
+ * Receives notification when an action was performend on the button.
+ *
+ * @param event the action event
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ Button b = (Button) SwingButtonPeer.this.awtComponent;
+ ActionListener[] l = b.getActionListeners();
+ if (l.length == 0)
+ return;
+ ActionEvent ev = new ActionEvent(b, ActionEvent.ACTION_PERFORMED,
+ b.getActionCommand());
+ for (int i = 0; i < l.length; ++i)
+ l[i].actionPerformed(ev);
+ }
+
+ }
+
+ /**
+ * Constructs a new SwingButtonPeer.
+ *
+ * @param theButton the AWT button for this peer
+ */
+ public SwingButtonPeer(Button theButton)
+ {
+ SwingButton button = new SwingButton();
+ button.setText(theButton.getLabel());
+ button.addActionListener(new SwingButtonListener());
+ init(theButton, button);
+ }
+
+ /**
+ * Sets the label of the button. This call is forwarded to the setText method
+ * of the managed Swing button.
+ *
+ * @param label the label to set
+ */
+ public void setLabel(String label)
+ {
+ ((SwingButton) swingComponent).setText(label);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingCanvasPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingCanvasPeer.java
new file mode 100644
index 00000000000..abef9ef12d1
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingCanvasPeer.java
@@ -0,0 +1,64 @@
+/* SwingCanvasPeer.java -- A canvas peer based on Swing
+ 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.java.awt.peer.swing;
+
+import java.awt.Canvas;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.LightweightPeer;
+
+/**
+ * A CanvasPeer to be used together with the Swing peers.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingCanvasPeer
+ extends SwingComponentPeer
+ implements LightweightPeer, CanvasPeer
+{
+
+ /**
+ * Creates a new <code>SwingCanvasPeer</code> for the specified Canvas.
+ *
+ * @param canvas the canvas.
+ */
+ public SwingCanvasPeer(Canvas canvas)
+ {
+ init(canvas, null);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java
new file mode 100644
index 00000000000..04ca7294f78
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java
@@ -0,0 +1,89 @@
+/* SwingComponent.java -- An interface that defines a Swing component for peers
+ 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.java.awt.peer.swing;
+
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+
+import javax.swing.JComponent;
+
+/**
+ * Defines some additional methods that the Swing components must implement
+ * in order to work with the Swing peers. This is usually achieved by
+ * subclassing a Swing component and forwarding the method calls to some
+ * protected JComponent method.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public interface SwingComponent
+{
+
+ /**
+ * Returns the actual swing compenent.
+ *
+ * @return the actual swing compenent
+ */
+ JComponent getJComponent();
+
+ /**
+ * Handles a mouse event. This is usually forwarded to
+ * {@link Component#processMouseMotionEvent(MouseEvent)} of the swing
+ * component.
+ *
+ * @param ev the mouse event
+ */
+ void handleMouseEvent(MouseEvent ev);
+
+ /**
+ * Handles a mouse motion event. This is usually forwarded to
+ * {@link Component#processMouseEvent(MouseEvent)} of the swing
+ * component.
+ *
+ * @param ev the mouse motion event
+ */
+ void handleMouseMotionEvent(MouseEvent ev);
+
+ /**
+ * Handles a key event. This is usually forwarded to
+ * {@link Component#processKeyEvent(KeyEvent)} of the swing
+ * component.
+ *
+ * @param ev the key event
+ */
+ void handleKeyEvent(KeyEvent ev);
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java
new file mode 100644
index 00000000000..5e34bc9dd21
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java
@@ -0,0 +1,994 @@
+/* SwingComponentPeer.java -- An abstract base class for Swing based peers
+ 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.java.awt.peer.swing;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.BufferCapabilities;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.BufferCapabilities.FlipContents;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.PaintEvent;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.VolatileImage;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.ContainerPeer;
+
+/**
+ * The base class for Swing based component peers. This provides the basic
+ * functionality needed for Swing based component peers. Many methods are
+ * implemented to forward to the Swing component. Others however forward
+ * to the component's parent and expect the toplevel component peer to provide
+ * a real implementation of it. These are for example the key methods
+ * {@link #getGraphics()} and {@link #createImage(int, int)}, as well as
+ * {@link #getLocationOnScreen()}.
+ *
+ * This class also provides the necesary hooks into the Swing painting and
+ * event handling system. In order to achieve this, it traps paint, mouse and
+ * key events in {@link #handleEvent(AWTEvent)} and calls some special methods
+ * ({@link #peerPaint(Graphics)}, {@link #handleKeyEvent(KeyEvent)},
+ * {@link #handleMouseEvent(MouseEvent)} and
+ * {@link #handleMouseMotionEvent(MouseEvent)}) that call the corresponding
+ * Swing methods.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingComponentPeer
+ implements ComponentPeer
+{
+
+ /**
+ * The AWT component for this peer.
+ */
+ protected Component awtComponent;
+
+ /**
+ * The Swing component for this peer.
+ */
+ protected SwingComponent swingComponent;
+
+ /**
+ * Creates a SwingComponentPeer instance. Subclasses are expected to call
+ * this constructor and thereafter call {@link #init(Component, JComponent)}
+ * in order to setup the AWT and Swing components properly.
+ */
+ protected SwingComponentPeer()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Initializes the AWT and Swing component for this peer. It is expected that
+ * subclasses call this from within their constructor.
+ *
+ * @param awtComp the AWT component for this peer
+ * @param swingComp the Swing component for this peer
+ */
+ protected void init(Component awtComp, SwingComponent swingComp)
+ {
+ awtComponent = awtComp;
+ swingComponent = swingComp;
+ }
+
+ /**
+ * Returns the construction status of the specified image. This is called
+ * by {@link Component#checkImage(Image, int, int, ImageObserver)}.
+ *
+ * @param img the image
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param ob the image observer to be notified of updates of the status
+ *
+ * @return a bitwise ORed set of ImageObserver flags
+ */
+ public int checkImage(Image img, int width, int height, ImageObserver ob)
+ {
+ return Toolkit.getDefaultToolkit().checkImage(img, width, height, ob);
+ }
+
+ /**
+ * Creates an image by starting the specified image producer. This is called
+ * by {@link Component#createImage(ImageProducer)}.
+ *
+ * @param prod the image producer to be used to create the image
+ *
+ * @return the created image
+ */
+ public Image createImage(ImageProducer prod)
+ {
+ Image image = Toolkit.getDefaultToolkit().createImage(prod);
+ return image;
+ }
+
+ /**
+ * Creates an empty image with the specified <code>width</code> and
+ * <code>height</code>.
+ *
+ * This is implemented to let the parent component create the image. This
+ * eventually goes up to the top-level component peer, which is then expected
+ * to deliver the image.
+ *
+ * @param width the width of the image to be created
+ * @param height the height of the image to be created
+ *
+ * @return the created image
+ */
+ public Image createImage(int width, int height)
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.createImage(width, height);
+ }
+
+ /**
+ * Disables the component. This is called by {@link Component#disable()}.
+ */
+ public void disable()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setEnabled(false);
+ }
+
+ /**
+ * Disposes the component peer. This should release all resources held by the
+ * peer. This is called when the component is no longer in use.
+ */
+ public void dispose()
+ {
+ awtComponent = null;
+ swingComponent = null;
+ }
+
+ /**
+ * Enables the component. This is called by {@link Component#enable()}.
+ */
+ public void enable()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setEnabled(true);
+ }
+
+ /**
+ * Returns the color model of the component. This is currently not used.
+ *
+ * @return the color model of the component
+ */
+ public ColorModel getColorModel()
+ {
+ // FIXME: When this peer method will be used, we need to provide an
+ // implementation of this, probably forwarding to the toplevel peer, like
+ // in the other methods.
+ return null;
+ }
+
+ /**
+ * Returns the font metrics for the specified font. This is called by
+ * {@link Component#getFontMetrics(Font)}.
+ *
+ * This is implemented to query the font metrics from the parent component.
+ * This will eventually call the top-level component peer, which is then
+ * expected to deliver a font metrics object.
+ *
+ * @param f the font for which to query the font metrics
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font f)
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.getFontMetrics(f);
+ }
+
+ /**
+ * Returns a {@link Graphics} object suitable for drawing on this component.
+ * This is called by {@link Component#getGraphics()}.
+ *
+ * This is implemented to query the graphics from the parent component and
+ * adjust the clip and translation to match this component.
+ * This will eventually call the top-level component peer, which is then
+ * expected to deliver a graphics object.
+ *
+ * @return a graphics object suitable for drawing on this component
+ */
+ public Graphics getGraphics()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ Graphics g = parentPeer.getGraphics();
+ g.translate(awtComponent.getX(), awtComponent.getY());
+ g.setClip(0, 0, awtComponent.getWidth(), awtComponent.getHeight());
+ return g;
+ }
+
+ /**
+ * Returns the location of this component in screen coordinates. This is
+ * called by {@link Component#getLocationOnScreen()}.
+ *
+ * This is implemented to query the parent component peer for its screen
+ * location and adds the offset of this component to it. This will eventually
+ * call the top-level component's peer, which is then expected to provide
+ * it's screen location.
+ *
+ * @return the location of this component in screen coordinates
+ */
+ public Point getLocationOnScreen()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ Point location = parentPeer.getLocationOnScreen();
+ location.x += awtComponent.getX();
+ location.y += awtComponent.getY();
+ return location;
+ }
+
+ /**
+ * Returns the minimum size for the component. This is called by
+ * {@link Component#getMinimumSize()}.
+ *
+ * This is implemented to return the Swing component's minimum size.
+ *
+ * @return the minimum size for the component
+ */
+ public Dimension getMinimumSize()
+ {
+ Dimension retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getMinimumSize();
+ else
+ retVal = new Dimension(0, 0);
+ return retVal;
+ }
+
+ /**
+ * Returns the preferred size for the component. This is called by
+ * {@link Component#getPreferredSize()}.
+ *
+ * This is implemented to return the Swing component's preferred size.
+ *
+ * @return the preferred size for the component
+ */
+ public Dimension getPreferredSize()
+ {
+ Dimension retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getPreferredSize();
+ else
+ retVal = new Dimension(0, 0);
+ return retVal;
+ }
+
+ /**
+ * Returns the toolkit that created this peer.
+ *
+ * @return the toolkit that created this peer
+ */
+ public Toolkit getToolkit()
+ {
+ return Toolkit.getDefaultToolkit();
+ }
+
+ /**
+ * Handles the given event. This is called from
+ * {@link Component#dispatchEvent(AWTEvent)} to give the peer a chance to
+ * react to events for the component.
+ *
+ * @param e the event
+ */
+ public void handleEvent(AWTEvent e)
+ {
+ switch (e.getID())
+ {
+ case PaintEvent.UPDATE:
+ case PaintEvent.PAINT:
+ Graphics g = getGraphics();
+ Rectangle clip = ((PaintEvent)e).getUpdateRect();
+ g.clipRect(clip.x, clip.y, clip.width, clip.height);
+ //if (this instanceof LightweightPeer)
+ // {
+ if (e.getID() == PaintEvent.UPDATE)
+ awtComponent.update(g);
+ else
+ awtComponent.paint(g);
+ // }
+ // We paint the 'heavyweights' at last, so that they appear on top of
+ // everything else.
+ peerPaint(g);
+
+ g.dispose();
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ case MouseEvent.MOUSE_CLICKED:
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ handleMouseEvent((MouseEvent) e);
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ handleMouseMotionEvent((MouseEvent) e);
+ break;
+ case KeyEvent.KEY_PRESSED:
+ case KeyEvent.KEY_RELEASED:
+ case KeyEvent.KEY_TYPED:
+ handleKeyEvent((KeyEvent) e);
+ break;
+ default:
+ // Other event types are not handled here.
+ break;
+ }
+ }
+
+ /**
+ * Makes the component invisible. This is called from
+ * {@link Component#hide()}.
+ *
+ * This is implemented to call setVisible(false) on the Swing component.
+ */
+ public void hide()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setVisible(false);
+ }
+
+ /**
+ * Returns <code>true</code> if the component can receive keyboard input
+ * focus. This is called from {@link Component#isFocusTraversable()}.
+ *
+ * This is implemented to return isFocusable() from the Swing component.
+ *
+ * @specnote Part of the earlier 1.1 API, replaced by isFocusable().
+ */
+ public boolean isFocusTraversable()
+ {
+ return swingComponent != null ?
+ swingComponent.getJComponent().isFocusable() : false;
+ }
+
+ /**
+ * Returns <code>true</code> if the component can receive keyboard input
+ * focus. This is called from {@link Component#isFocusable()}.
+ *
+ * This is implemented to return isFocusable() from the Swing component.
+ */
+ public boolean isFocusable()
+ {
+ return swingComponent != null ?
+ swingComponent.getJComponent().isFocusable() : false;
+ }
+
+ /**
+ * Returns the minimum size for the component. This is called by
+ * {@link Component#minimumSize()}.
+ *
+ * This is implemented to return the Swing component's minimum size.
+ *
+ * @return the minimum size for the component
+ */
+ public Dimension minimumSize()
+ {
+ Dimension retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getMinimumSize();
+ else
+ retVal = new Dimension(0, 0);
+ return retVal;
+ }
+
+ /**
+ * Returns the preferred size for the component. This is called by
+ * {@link Component#getPreferredSize()}.
+ *
+ * This is implemented to return the Swing component's preferred size.
+ *
+ * @return the preferred size for the component
+ */
+ public Dimension preferredSize()
+ {
+ Dimension retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getPreferredSize();
+ else
+ retVal = new Dimension(0, 0);
+ return retVal;
+ }
+
+ /**
+ * Prepares an image for rendering on this component. This is called by
+ * {@link Component#prepareImage(Image, int, int, ImageObserver)}.
+ *
+ * @param img the image to prepare
+ * @param width the desired width of the rendered image
+ * @param height the desired height of the rendered image
+ * @param ob the image observer to be notified of updates in the preparation
+ * process
+ *
+ * @return <code>true</code> if the image has been fully prepared,
+ * <code>false</code> otherwise (in which case the image observer
+ * receives updates)
+ */
+ public void paint(Graphics graphics)
+ {
+ // FIXME: I don't know what this method is supposed to do.
+ }
+
+ /**
+ * Prepares an image for rendering on this component. This is called by
+ * {@link Component#prepareImage(Image, int, int, ImageObserver)}.
+ *
+ * @param img the image to prepare
+ * @param width the desired width of the rendered image
+ * @param height the desired height of the rendered image
+ * @param ob the image observer to be notified of updates in the preparation
+ * process
+ *
+ * @return <code>true</code> if the image has been fully prepared,
+ * <code>false</code> otherwise (in which case the image observer
+ * receives updates)
+ */
+ public boolean prepareImage(Image img, int width, int height, ImageObserver ob)
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.prepareImage(img, width, height, ob);
+ }
+
+ public void print(Graphics graphics)
+ {
+ // FIXME: I don't know what this method is supposed to do.
+ }
+
+ /**
+ * Repaints the specified rectangle of this component. This is called from
+ * {@link Component#repaint(long, int, int, int, int)}.
+ *
+ * This is implemented to call repaint() on the Swing component.
+ *
+ * @param tm number of milliseconds to wait with repainting
+ * @param x the X coordinate of the upper left corner of the damaged rectangle
+ * @param y the Y coordinate of the upper left corner of the damaged rectangle
+ * @param width the width of the damaged rectangle
+ * @param height the height of the damaged rectangle
+ */
+ public void repaint(long tm, int x, int y, int width, int height)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().repaint(tm, x, y, width, height);
+ else
+ {
+ PaintEvent ev = new PaintEvent(awtComponent, PaintEvent.UPDATE,
+ new Rectangle(x, y, width, height));
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ev);
+ }
+ }
+
+ /**
+ * Requests that this component receives the focus. This is called from
+ * {@link Component#requestFocus()}.
+ *
+ * This calls requestFocus() on the Swing component.
+ *
+ * @specnote Part of the earlier 1.1 API, apparently replaced by argument
+ * form of the same method.
+ */
+ public void requestFocus()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().requestFocus();
+ }
+
+ /**
+ * Requests that this component receives the focus. This is called from
+ * {@link Component#requestFocus()}.
+ *
+ * This calls requestFocus() on the Swing component.
+ *
+ * @param source TODO
+ * @param bool1 TODO
+ * @param bool2 TODO
+ * @param x TODO
+ *
+ * @return TODO
+ */
+ public boolean requestFocus(Component source, boolean bool1, boolean bool2, long x)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().requestFocus();
+ return swingComponent != null;
+ }
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#reshape(int, int, int, int)}.
+ *
+ * This is implemented to call setBounds() on the Swing component.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setBounds(x, y, width, height);
+ }
+
+ /**
+ * Sets the background color of the component. This is called by
+ * {@link Component#setBackground(Color)}.
+ *
+ * This is implemented to call setBackground() on the Swing component.
+ *
+ * @param color the background color to set
+ */
+ public void setBackground(Color color)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setBackground(color);
+ }
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#setBounds(int, int, int, int)}.
+ *
+ * This is implemented to call setBounds() on the Swing component.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ public void setBounds(int x, int y, int width, int height)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setBounds(x, y, width, height);
+ }
+
+ /**
+ * Sets the cursor of the component. This is called by
+ * {@link Component#setCursor(Cursor)}.
+ *
+ * This is implemented to call setCursor() on the Swing component.
+ *
+ * @specnote Part of the earlier 1.1 API, apparently no longer needed.
+ */
+ public void setCursor(Cursor cursor)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setCursor(cursor);
+ }
+
+ /**
+ * Sets the enabled/disabled state of this component. This is called by
+ * {@link Component#setEnabled(boolean)}.
+ *
+ * This is implemented to call setEnabled() on the Swing component.
+ *
+ * @param enabled <code>true</code> to enable the component,
+ * <code>false</code> to disable it
+ */
+ public void setEnabled(boolean enabled)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setEnabled(enabled);
+ }
+
+ /**
+ * Sets the font of the component. This is called by
+ * {@link Component#setFont(Font)}.
+ *
+ * This is implemented to call setFont() on the Swing component.
+ *
+ * @param font the font to set
+ */
+ public void setFont(Font font)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setFont(font);
+ }
+
+ /**
+ * Sets the foreground color of the component. This is called by
+ * {@link Component#setForeground(Color)}.
+ *
+ * This is implemented to call setForeground() on the Swing component.
+ *
+ * @param color the foreground color to set
+ */
+ public void setForeground(Color color)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setForeground(color);
+ }
+
+ /**
+ * Sets the visibility state of the component. This is called by
+ * {@link Component#setVisible(boolean)}.
+ *
+ * This is implemented to call setVisible() on the Swing component.
+ *
+ * @param visible <code>true</code> to make the component visible,
+ * <code>false</code> to make it invisible
+ */
+ public void setVisible(boolean visible)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setVisible(visible);
+ }
+
+ /**
+ * Makes the component visible. This is called by {@link Component#show()}.
+ *
+ * This is implemented to call setVisible(true) on the Swing component.
+ */
+ public void show()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setVisible(true);
+ }
+
+ /**
+ * Get the graphics configuration of the component. The color model
+ * of the component can be derived from the configuration.
+ *
+ * This is implemented to return the GraphicsConfiguration of the parent
+ * component. This will eventually call the toplevel component peer, which
+ * is expected to provide a real implementation.
+ *
+ * @return the graphics configuration of the component
+ */
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.getGraphicsConfiguration();
+ }
+
+ /**
+ * Part of an older API, no longer needed.
+ */
+ public void setEventMask(long mask)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns <code>true</code> if this component has been obscured,
+ * <code>false</code> otherwise. This will only work if
+ * {@link #canDetermineObscurity()} also returns <code>true</code>.
+ *
+ * This is not yet implemented.
+ *
+ * @return <code>true</code> if this component has been obscured,
+ * <code>false</code> otherwise.
+ */
+ public boolean isObscured()
+ {
+ return false;
+ }
+
+ /**
+ * Returns <code>true</code> if this component peer can determine if the
+ * component has been obscured, <code>false</code> otherwise.
+ *
+ * This is not yet implemented.
+ *
+ * @return <code>true</code> if this component peer can determine if the
+ * component has been obscured, <code>false</code> otherwise
+ */
+ public boolean canDetermineObscurity()
+ {
+ return false;
+ }
+
+ /**
+ * Coalesces the specified paint event.
+ *
+ * @param e the paint event
+ */
+ public void coalescePaintEvent(PaintEvent e)
+ {
+ // Nothing to do here yet.
+ }
+
+ /**
+ * Updates the cursor. This is not yet implemented.
+ */
+ public void updateCursorImmediately()
+ {
+ // Nothing to do here yet.
+ }
+
+ /**
+ * Returns true, if this component can handle wheel scrolling,
+ * <code>false</code> otherwise.
+ *
+ * This is not yet implemented and returns <code>false</code>.
+ *
+ * @return true, if this component can handle wheel scrolling,
+ * <code>false</code> otherwise
+ */
+ public boolean handlesWheelScrolling()
+ {
+ return false;
+ }
+
+ /**
+ * A convenience method that creates a volatile image. The volatile
+ * image is created on the screen device on which this component is
+ * displayed, in the device's current graphics configuration.
+ *
+ * This is implemented to let the parent component peer create an image.
+ * This eventually ends up in the toplevel component peer, which is then
+ * responsible for creating the real image.
+ *
+ * @param width width of the image
+ * @param height height of the image
+ *
+ * @see VolatileImage
+ *
+ * @since 1.2
+ */
+ public VolatileImage createVolatileImage(int width, int height)
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.createVolatileImage(width, height);
+ }
+
+ /**
+ * Create a number of image buffers that implement a buffering
+ * strategy according to the given capabilities.
+ *
+ * This is implemented to forward to the parent component peer. Eventually
+ * this ends up in the top level component peer, which is then responsible
+ * for doing the real work.
+ *
+ * @param numBuffers the number of buffers
+ * @param caps the buffering capabilities
+ *
+ * @throws AWTException if the specified buffering strategy is not
+ * implemented
+ *
+ * @since 1.2
+ */
+ public void createBuffers(int numBuffers, BufferCapabilities caps) throws AWTException
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ parentPeer.createBuffers(numBuffers, caps);
+ }
+
+ /**
+ * Return the back buffer of this component.
+ *
+ * This is implemented to forward to the parent. Eventually this ends
+ * up in the toplevel component, which is then responsible for providing
+ * a back buffer.
+ *
+ * @return the back buffer of this component.
+ *
+ * @since 1.2
+ */
+ public Image getBackBuffer()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.getBackBuffer();
+ }
+
+ /**
+ * Perform a page flip, leaving the contents of the back buffer in
+ * the specified state.
+ *
+ * This is implemented to forward to the parent. Eventually this ends
+ * up in the toplevel component, which is then responsible for doing the real
+ * work.
+ *
+ * @param contents the state in which to leave the back buffer
+ *
+ * @since 1.2
+ */
+ public void flip(FlipContents contents)
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ parentPeer.flip(contents);
+ }
+
+ /**
+ * Destroy the resources created by createBuffers.
+ *
+ * This is implemented to forward to the parent component peer. Eventually
+ * this ends up in the top level component peer, which is then responsible
+ * for doing the real work.
+ *
+ * @since 1.2
+ */
+ public void destroyBuffers()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ parentPeer.destroyBuffers();
+ }
+
+ /**
+ * Get the bounds of this component peer.
+ *
+ * This is implemented to forward to the Swing component.
+ *
+ * @return component peer bounds
+ * @since 1.5
+ */
+ public Rectangle getBounds()
+ {
+ Rectangle retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getBounds();
+ else
+ retVal = new Rectangle();
+ return retVal;
+ }
+
+ /**
+ * Reparent this component under another container.
+ *
+ * @param parent
+ * @since 1.5
+ */
+ public void reparent(ContainerPeer parent)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Set the bounds of this component peer.
+ *
+ * This is implemented to forward to the swing component.
+ *
+ * @param x the new x co-ordinate
+ * @param y the new y co-ordinate
+ * @param width the new width
+ * @param height the new height
+ * @param z the new stacking level
+ * @since 1.5
+ */
+ public void setBounds(int x, int y, int width, int height, int z)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setBounds(x, y, width, height);
+ // FIXME: Somehow handle the Z order.
+ }
+
+ /**
+ * Check if this component supports being reparented.
+ *
+ * @return true if this component can be reparented,
+ * false otherwise.
+ * @since 1.5
+ */
+ public boolean isReparentSupported()
+ {
+ return true;
+ }
+
+
+ /**
+ * Layout this component peer.
+ *
+ * @since 1.5
+ */
+ public void layout()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().doLayout();
+ }
+
+ /**
+ * Triggers 'heavyweight' painting of the components. This usually calls
+ * paint() on the Swing component.
+ *
+ * @param g the graphics context to use for painting
+ */
+ protected void peerPaint(Graphics g)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().paint(g);
+ }
+
+ /**
+ * Handles mouse events on the component. This is usually forwarded to the
+ * SwingComponent's processMouseEvent() method.
+ *
+ * @param e the mouse event
+ */
+ protected void handleMouseEvent(MouseEvent e)
+ {
+ if (swingComponent != null)
+ swingComponent.handleMouseEvent(e);
+ }
+
+ /**
+ * Handles mouse motion events on the component. This is usually forwarded
+ * to the SwingComponent's processMouseMotionEvent() method.
+ *
+ * @param e the mouse motion event
+ */
+ protected void handleMouseMotionEvent(MouseEvent e)
+ {
+ if (swingComponent != null)
+ swingComponent.handleMouseMotionEvent(e);
+ }
+
+ /**
+ * Handles key events on the component. This is usually forwarded to the
+ * SwingComponent's processKeyEvent() method.
+ *
+ * @param e the key event
+ */
+ protected void handleKeyEvent(KeyEvent e)
+ {
+ if (swingComponent != null)
+ swingComponent.handleKeyEvent(e);
+ }
+
+ /**
+ * Returns the AWT component for this peer.
+ *
+ * @return the AWT component for this peer
+ */
+ public Component getComponent()
+ {
+ return awtComponent;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java
new file mode 100644
index 00000000000..37bea751f86
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java
@@ -0,0 +1,241 @@
+/* SwingContainerPeer.java -- A Swing based peer for AWT containers
+ 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.java.awt.peer.swing;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Shape;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.ContainerPeer;
+
+/**
+ * A peer for Container to be used with the Swing based AWT peers.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingContainerPeer
+ extends SwingComponentPeer
+ implements ContainerPeer
+{
+
+ /**
+ * Creates a new SwingContainerPeer.
+ *
+ * @param awtCont
+ */
+ public SwingContainerPeer(Container awtCont)
+ {
+ init(awtCont, null);
+ }
+
+ /**
+ * Returns the insets of the container.
+ *
+ * This is implemented to return the insets of the Swing container.
+ *
+ * @return the insets of the container
+ */
+ public Insets insets()
+ {
+ Insets retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getInsets();
+ else
+ retVal = new Insets(0, 0, 0, 0);
+ return retVal;
+ }
+
+ /**
+ * Returns the insets of the container.
+ *
+ * This is implemented to return the insets of the Swing container.
+ *
+ * @return the insets of the container
+ */
+ public Insets getInsets()
+ {
+ Insets retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getInsets();
+ else
+ retVal = new Insets(0, 0, 0, 0);
+ return retVal;
+ }
+
+ /**
+ * Called before the validation of this containers begins.
+ */
+ public void beginValidate()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Called after the validation of this containers ended.
+ */
+ public void endValidate()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Called before the layout of this containers begins.
+ */
+ public void beginLayout()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Called after the layout of this containers ended.
+ */
+ public void endLayout()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns <code>false</code> unconditionally. This method is not used at
+ * the moment.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isPaintPending()
+ {
+ return false;
+ }
+
+ /**
+ * Returns <code>false</code> unconditionally. This method is not used at
+ * the moment.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isRestackSupported()
+ {
+ return false;
+ }
+
+ /**
+ * This method is not used at the moment.
+ */
+ public void cancelPendingPaint(int x, int y, int width, int height)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * This method is not used at the moment.
+ */
+ public void restack()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Triggers painting of a component. This calls peerPaint on all the child
+ * components of this container.
+ *
+ * @param g the graphics context to paint to
+ */
+ protected void peerPaint(Graphics g)
+ {
+ Container c = (Container) awtComponent;
+ Component[] children = c.getComponents();
+ for (int i = children.length - 1; i >= 0; --i)
+ {
+ Component child = children[i];
+ ComponentPeer peer = child.getPeer();
+ boolean translated = false;
+ boolean clipped = false;
+ Shape oldClip = g.getClip();
+ try
+ {
+ g.translate(child.getX(), child.getY());
+ translated = true;
+ g.setClip(0, 0, child.getWidth(), child.getHeight());
+ clipped = true;
+ if (peer instanceof SwingComponentPeer)
+ ((SwingComponentPeer) peer).peerPaint(g);
+ }
+ finally
+ {
+ if (translated)
+ g.translate(- child.getX(), - child.getY());
+ if (clipped)
+ g.setClip(oldClip);
+ }
+ }
+ }
+
+ /**
+ * Handles mouse events by dispatching it to the correct component.
+ *
+ * @param ev the mouse event
+ */
+ protected void handleMouseEvent(MouseEvent ev)
+ {
+ Component comp = awtComponent.getComponentAt(ev.getPoint());
+ ComponentPeer peer = comp.getPeer();
+ if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
+ {
+ ev.translatePoint(comp.getX(), comp.getY());
+ ev.setSource(comp);
+ ((SwingComponentPeer) peer).handleMouseEvent(ev);
+ }
+ }
+
+ /**
+ * Handles mouse events by dispatching it to the correct component.
+ *
+ * @param ev the mouse event
+ */
+ protected void handleMouseMotionEvent(MouseEvent ev)
+ {
+ Component comp = awtComponent.getComponentAt(ev.getPoint());
+ ComponentPeer peer = comp.getPeer();
+ if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
+ {
+ ev.translatePoint(comp.getX(), comp.getY());
+ ((SwingComponentPeer) peer).handleMouseMotionEvent(ev);
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingFramePeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingFramePeer.java
new file mode 100644
index 00000000000..fea1b504a6a
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingFramePeer.java
@@ -0,0 +1,196 @@
+/* SwingFramePeer.java -- An abstract Swing based peer for AWT frames
+ 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.java.awt.peer.swing;
+
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.MenuBar;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.awt.peer.FramePeer;
+
+/**
+ * An abstract base class for FramePeer implementations based on Swing.
+ * This class provides the ability to display and handle AWT MenuBars that
+ * are based on Swing.
+ *
+ * As a minimum, a subclass must implement all the remaining abstract methods
+ * as well as the following methods:
+ * <ul>
+ * <li>{@link ComponentPeer#getLocationOnScreen()}</li>
+ * <li>{@link ComponentPeer#getGraphics()}</li>
+ * <li>{@link ComponentPeer#createImage(int, int)}</li>
+ * </ul>
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public abstract class SwingFramePeer
+ extends SwingWindowPeer
+ implements FramePeer
+{
+ /**
+ * The menu bar to display.
+ */
+ SwingMenuBarPeer menuBar = null;
+
+ /**
+ * Creates a new SwingFramePeer.
+ *
+ * @param frame the frame
+ */
+ public SwingFramePeer(Frame frame)
+ {
+ super(frame);
+ }
+
+ /**
+ * Sets the menu bar to display in this frame.
+ *
+ * @param mb the menu bar to set
+ */
+ public void setMenuBar(MenuBar mb)
+ {
+ menuBar = (SwingMenuBarPeer) mb.getPeer();
+ menuBar.setFramePeer(this);
+ menuBar.setWidth(awtComponent.getWidth());
+ }
+
+ /**
+ * Triggers 'heavyweight' painting of the frame. This will paint a menu bar
+ * if present as well as the child components of this frame.
+ *
+ * @param g the graphics context to use for painting
+ */
+ protected void peerPaint(Graphics g)
+ {
+ super.peerPaint(g);
+ if (menuBar != null)
+ menuBar.peerPaint(g);
+ }
+
+ /**
+ * Sets the size and location of this frame. This resizes the menubar to fit
+ * within the frame.
+ *
+ * @param x the X coordinate of the screen location
+ * @param y the Y coordinate of the screen location
+ * @param w the width of the frame
+ * @param h the height of the frame
+ */
+ public void setBounds(int x, int y, int w, int h)
+ {
+ super.setBounds(x, y, w, h);
+ if (menuBar != null)
+ menuBar.setWidth(w);
+ }
+
+ /**
+ * Calculates the insets of this frame peer. This fetches the insets
+ * from the superclass and adds the insets of the menubar if one is present.
+ *
+ * @return the insets of the frame
+ */
+ public Insets getInsets()
+ {
+ Insets insets = super.getInsets();
+ if (menuBar != null)
+ insets.top += menuBar.getHeight();
+ return insets;
+ }
+
+ /**
+ * Returns the location of the menu on the screen. This is needed internally
+ * by the {@link SwingMenuBarPeer} in order to determine its screen location.
+ *
+ * @return the location of the menu on the screen
+ */
+ public Point getMenuLocationOnScreen()
+ {
+ Insets i = super.getInsets();
+ return new Point(i.top, i.left);
+ }
+
+ /**
+ * Overridden to provide the ability to handle menus.
+ *
+ * @param ev the mouse event
+ */
+ protected void handleMouseEvent(MouseEvent ev)
+ {
+ Point p = ev.getPoint();
+ Insets i = super.getInsets();
+ if (menuBar != null)
+ {
+ int menuHeight = menuBar.getHeight();
+ if (p.y >= i.top && p.y <= i.top + menuHeight)
+ menuBar.handleMouseEvent(ev);
+ else
+ {
+ ev.translatePoint(0, -menuHeight);
+ super.handleMouseMotionEvent(ev);
+ }
+ }
+
+ super.handleMouseEvent(ev);
+ }
+
+ /**
+ * Overridden to provide the ability to handle menus.
+ *
+ * @param ev the mouse event
+ */
+ protected void handleMouseMotionEvent(MouseEvent ev)
+ {
+ Point p = ev.getPoint();
+ Insets i = super.getInsets();
+ if (menuBar != null)
+ {
+ int menuHeight = menuBar.getHeight();
+ if (p.y >= i.top && p.y <= i.top + menuHeight)
+ menuBar.handleMouseMotionEvent(ev);
+ else
+ {
+ ev.translatePoint(0, -menuHeight);
+ super.handleMouseMotionEvent(ev);
+ }
+ }
+
+ super.handleMouseMotionEvent(ev);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java
new file mode 100644
index 00000000000..dd86fff2d10
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java
@@ -0,0 +1,196 @@
+/* SwingLabelPeer.java -- A Swing based peer for AWT labels
+ 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.java.awt.peer.swing;
+
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.Point;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.LabelPeer;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+
+/**
+ * A Label peer based on {@link JLabel}.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingLabelPeer
+ extends SwingComponentPeer
+ implements LabelPeer
+{
+
+ /**
+ * A spezialized Swing label used to paint the label for the AWT Label.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingLabel
+ extends JLabel
+ implements SwingComponent
+ {
+
+ /**
+ * Returns this label.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to <code>processKeyEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ processKeyEvent(ev);
+ }
+
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingLabelPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (SwingLabelPeer.this.awtComponent != null)
+ retVal = SwingLabelPeer.this.awtComponent.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingLabelPeer.this.createImage(w, h);
+ }
+
+ }
+
+ /**
+ * Creates a new <code>SwingLabelPeer</code> for the specified AWT label.
+ *
+ * @param label the AWT label
+ */
+ public SwingLabelPeer(Label label)
+ {
+ super();
+ SwingLabel swingLabel = new SwingLabel();
+ swingLabel.setText(label.getText());
+ swingLabel.setHorizontalAlignment(label.getAlignment());
+ swingLabel.setOpaque(true);
+ init(label, swingLabel);
+ }
+
+ /**
+ * Sets the text of the label. This is implemented to set the text on the
+ * Swing label.
+ *
+ * @param text the text to be set
+ */
+ public void setText(String text)
+ {
+ ((JLabel) swingComponent.getJComponent()).setText(text);
+ }
+
+ /**
+ * Sets the horizontal alignment of the label. This is implemented to
+ * set the alignment on the Swing label.
+ *
+ * @param alignment the horizontal alignment
+ *
+ * @see Label#LEFT
+ * @see Label#RIGHT
+ * @see Label#CENTER
+ */
+ public void setAlignment(int alignment)
+ {
+ ((JLabel) swingComponent.getJComponent()).setHorizontalAlignment(alignment);
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuBarPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuBarPeer.java
new file mode 100644
index 00000000000..bd9dcd77aaa
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuBarPeer.java
@@ -0,0 +1,295 @@
+/* SwingMenuBarPeer.java -- A Swing based peer for AWT menu bars
+ 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.java.awt.peer.swing;
+
+import java.awt.Container;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.awt.peer.MenuBarPeer;
+
+import javax.swing.JMenuBar;
+
+/**
+ * A Swing based peer for the AWT menu bar. This is a little bit different from
+ * the other peers, since the AWT MenuBar is not derived from the AWT
+ * component.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingMenuBarPeer
+ implements MenuBarPeer
+{
+
+ /**
+ * The AWT menu bar.
+ */
+ MenuBar awtMenuBar;
+
+ /**
+ * The Swing menu bar.
+ */
+ SwingMenuBar menuBar;
+
+ /**
+ * The peer of the frame that contains this menu bar.
+ */
+ SwingFramePeer framePeer;
+
+ /**
+ * A specialized JMenuBar that can be used as 'backend' for AWT MenuBars.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingMenuBar
+ extends JMenuBar
+ {
+ /**
+ * Overridden in order to provide a parent frame for this menu bar. The
+ * menu bar still is not inside the component hierarchy, we are faking
+ * here.
+ */
+ public Container getParent()
+ {
+ Container result = null;
+ if (framePeer != null)
+ result = (Container) framePeer.awtComponent;
+ return result;
+ }
+
+ /**
+ * Unconditionally returns <code>true</code>, since we assume that when the
+ * menubar has a peer, it must be showing.
+ *
+ * @return <code>true</code>
+ */
+ public boolean isShowing()
+ {
+ // FIXME: This might be wrong. Maybe find a better way to do that.
+ return true;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Determines the menubar's screen location by asking the SwingFramePeer
+ * for it.
+ *
+ * @return the screen location of the menu bar
+ */
+ public Point getLocationOnScreen()
+ {
+ return framePeer.getMenuLocationOnScreen();
+ }
+ }
+
+ /**
+ * Creates a new <code>SwingMenuBarPeer</code> instance.
+ *
+ * @param awtMenuBar the AWT menu bar
+ */
+ public SwingMenuBarPeer(MenuBar awtMenuBar)
+ {
+ this.awtMenuBar = awtMenuBar;
+ menuBar = new SwingMenuBar();
+ menuBar.setDoubleBuffered(false);
+ // Add all the menus that are already in the MenuBar.
+ for (int i = 0; i < awtMenuBar.getMenuCount(); i++)
+ {
+ Menu menu = awtMenuBar.getMenu(i);
+ menu.addNotify();
+ addMenu(awtMenuBar.getMenu(i));
+ }
+ }
+
+ /**
+ * Sets the <code>SwingFramePeer</code> of the frame that holds this menu.
+ *
+ * @param peer the <code>SwingFramePeer</code> to set
+ */
+ public void setFramePeer(SwingFramePeer peer)
+ {
+ framePeer = peer;
+ }
+
+ /**
+ * Adds a menu to the menu bar.
+ *
+ * @param m the menu to add
+ */
+ public void addMenu(Menu m)
+ {
+ SwingMenuPeer menuPeer = (SwingMenuPeer) m.getPeer();
+ menuBar.add(menuPeer.menu);
+ }
+
+ /**
+ * Adds a help menu to the menu bar.
+ *
+ * @param m the menu to add
+ */
+ public void addHelpMenu(Menu menu)
+ {
+ // FIXME: We should manage the help menu differently, so that it always
+ // appears at the rightmost position.
+ SwingMenuPeer menuPeer = (SwingMenuPeer) menu.getPeer();
+ menuBar.add(menuPeer.menu);
+ }
+
+ /**
+ * Removes the menu with the specified index.
+ *
+ * @param index the index of the menu to remove
+ */
+ public void delMenu(int index)
+ {
+ menuBar.remove(index);
+ }
+
+ /**
+ * Disposes this peer. This releases any reference to the AWT and Swing
+ * components.
+ */
+ public void dispose()
+ {
+ menuBar = null;
+ awtMenuBar = null;
+ }
+
+ /**
+ * Sets a font for the menu bar.
+ *
+ * @param font the font to set
+ */
+ public void setFont(Font font)
+ {
+ menuBar.setFont(font);
+ }
+
+ /**
+ * Sets the width of the menu bar. This is called from the top level
+ * component peers to adjust the width of the menubar when their sizes
+ * change.
+ *
+ * @param w the width to set
+ */
+ public void setWidth(int w)
+ {
+ menuBar.setSize(w, menuBar.getPreferredSize().height);
+ menuBar.doLayout();
+ }
+
+ /**
+ * Paints the menu bar.
+ *
+ * @param g the graphics context to use for painting
+ */
+ public void peerPaint(Graphics g)
+ {
+ menuBar.paint(g);
+ }
+
+ /**
+ * Determines the height of the menubar.
+ *
+ * @return the height of the menu bar
+ */
+ public int getHeight()
+ {
+ return menuBar.getPreferredSize().height;
+ }
+
+ /**
+ * Handles mouse events.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ Point point = ev.getPoint();
+ for (int i = 0; i < awtMenuBar.getMenuCount(); i++)
+ {
+ Menu menu = awtMenuBar.getMenu(i);
+ SwingMenuPeer peer = (SwingMenuPeer) menu.getPeer();
+ int x1 = peer.getX();
+ int x2 = x1 + peer.getWidth();
+ if (point.x >= x1 && point.x <= x2)
+ {
+ ev.translatePoint(peer.getX(), peer.getY());
+ peer.handleMouseEvent(ev);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Handles mouse motion events.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ Point point = ev.getPoint();
+ for (int i = 0; i < awtMenuBar.getMenuCount(); i++)
+ {
+ Menu menu = awtMenuBar.getMenu(i);
+ SwingMenuPeer peer = (SwingMenuPeer) menu.getPeer();
+ int x1 = peer.getX();
+ int x2 = x1 + peer.getWidth();
+ if (point.x >= x1 && point.x <= x2)
+ {
+ ev.translatePoint(peer.getX(), peer.getY());
+ peer.handleMouseMotionEvent(ev);
+ break;
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuItemPeer.java
new file mode 100644
index 00000000000..8b9d47ec015
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuItemPeer.java
@@ -0,0 +1,157 @@
+/* SwingMenuItemPeer.java -- A Swing based peer for AWT menu items
+ 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.java.awt.peer.swing;
+
+import java.awt.Font;
+import java.awt.MenuItem;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.MenuItemPeer;
+
+import javax.swing.JMenuItem;
+
+/**
+ * A Swing based peer for the AWT MenuItem.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingMenuItemPeer
+ implements MenuItemPeer
+{
+ /**
+ * The AWT menu item.
+ */
+ MenuItem awtMenuItem;
+
+ /**
+ * The Swing menu item.
+ */
+ JMenuItem menuItem;
+
+ /**
+ * Receives ActionEvents from the Swing menu item and forwards them
+ * to the ActionListeners of the AWT MenuItem.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingMenuItemListener implements ActionListener
+ {
+
+ /**
+ * Receives notification when the action has been performed.
+ *
+ * @param event the action event
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ event.setSource(awtMenuItem);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
+ }
+
+ }
+
+ /**
+ * Creates a new instance of <code>SwingMenuItemPeer</code>.
+ *
+ * @param awtMenuItem the AWT menu item
+ */
+ public SwingMenuItemPeer(MenuItem awtMenuItem)
+ {
+ this.awtMenuItem = awtMenuItem;
+ menuItem = new JMenuItem(awtMenuItem.getLabel());
+ menuItem.addActionListener(new SwingMenuItemListener());
+ }
+
+ /**
+ * Disables the menu item.
+ */
+ public void disable()
+ {
+ menuItem.setEnabled(false);
+ }
+
+ /**
+ * Enables the menu item.
+ */
+ public void enable()
+ {
+ menuItem.setEnabled(true);
+ }
+
+ /**
+ * Sets the enabled state to <code>enabled</code>.
+ *
+ * @param enabled if the menu item should be enabled or not
+ */
+ public void setEnabled(boolean enabled)
+ {
+ menuItem.setEnabled(enabled);
+ }
+
+ /**
+ * Sets the label for the menu item.
+ *
+ * @param text the label to set
+ */
+ public void setLabel(String text)
+ {
+ menuItem.setText(text);
+ }
+
+ /**
+ * Disposes the menu item. This releases any reference to the Swing and AWT
+ * menu item.
+ */
+ public void dispose()
+ {
+ menuItem = null;
+ awtMenuItem = null;
+ }
+
+ /**
+ * Sets the font for this menu item.
+ *
+ * @param font the font to set
+ */
+ public void setFont(Font font)
+ {
+ menuItem.setFont(font);
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuPeer.java
new file mode 100644
index 00000000000..ecb54a52479
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuPeer.java
@@ -0,0 +1,284 @@
+/* SwingMenuPeer.java -- A Swing based peer for AWT menus
+ 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.java.awt.peer.swing;
+
+import java.awt.Font;
+import java.awt.Menu;
+import java.awt.MenuItem;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.awt.peer.MenuPeer;
+
+import javax.swing.JMenu;
+
+/**
+ * A Swing based peer for the AWT menu.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingMenuPeer
+ implements MenuPeer
+{
+
+ /**
+ * The AWT menu.
+ */
+ Menu awtMenu;
+
+ /**
+ * The Swing menu.
+ */
+ SwingMenu menu;
+
+ /**
+ * A specialized JMenu that can be used as 'backend' for an AWT menu.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingMenu
+ extends JMenu
+ {
+
+ /**
+ * Unconditionally returns <code>true</code>, since we assume that when the
+ * menu has a peer, it must be showing.
+ *
+ * @return <code>true</code>
+ */
+ public boolean isShowing()
+ {
+ // FIXME: This might be wrong. Maybe find a better way to do that.
+ return true;
+ }
+
+ /**
+ * Overridden so that we can provide a location even without a real peer
+ * attached.
+ *
+ * @return the screen location of this menu
+ */
+ public Point getLocationOnScreen()
+ {
+ Point parentLoc = getParent().getLocationOnScreen();
+ parentLoc.x += getX();
+ parentLoc.y += getY();
+ return parentLoc;
+ }
+
+ /**
+ * Handles mouse events by forwarding them to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse events by forwarding them to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseMotionEvent(ev);
+ }
+ }
+
+ /**
+ * Creates a new <code>SwingMenuPeer</code> instance.
+ *
+ * @param awtMenu the AWT menu
+ */
+ public SwingMenuPeer(Menu awtMenu)
+ {
+ this.awtMenu = awtMenu;
+ menu = new SwingMenu();
+ menu.setDoubleBuffered(false);
+ menu.setText(awtMenu.getLabel());
+ for (int i = 0; i < awtMenu.getItemCount(); i++)
+ {
+ MenuItem item = awtMenu.getItem(i);
+ item.addNotify();
+ SwingMenuItemPeer peer = (SwingMenuItemPeer) item.getPeer();
+ menu.add(peer.menuItem);
+ }
+ }
+
+ /**
+ * Adds a menu item to this menu.
+ *
+ * @param item the menu item to add
+ */
+ public void addItem(MenuItem item)
+ {
+ SwingMenuItemPeer menuItemPeer = (SwingMenuItemPeer) item.getPeer();
+ menu.add(menuItemPeer.menuItem);
+ }
+
+ /**
+ * Adds a separator to the menu.
+ */
+ public void addSeparator()
+ {
+ menu.addSeparator();
+ }
+
+ /**
+ * Removes a menu item from the menu.
+ *
+ * @param index the index of the menu item to remove
+ */
+ public void delItem(int index)
+ {
+ menu.remove(index);
+ }
+
+ /**
+ * Disables the menu.
+ */
+ public void disable()
+ {
+ menu.setEnabled(false);
+ }
+
+ /**
+ * Enables the menu.
+ */
+ public void enable()
+ {
+ menu.setEnabled(true);
+ }
+
+ /**
+ * Sets the enabled state of the menu to <code>enabled</code>.
+ *
+ * @param enabled if the menu should be enabled or not
+ */
+ public void setEnabled(boolean enabled)
+ {
+ menu.setEnabled(enabled);
+ }
+
+ /**
+ * Sets the label of the menu.
+ *
+ * @param text the label to set
+ */
+ public void setLabel(String text)
+ {
+ menu.setText(text);
+ }
+
+ /**
+ * Releases any reference to the AWT and Swing menu instances.
+ */
+ public void dispose()
+ {
+ menu = null;
+ awtMenu = null;
+ }
+
+ /**
+ * Sets the font for the menu.
+ *
+ * @param font the font to set
+ */
+ public void setFont(Font font)
+ {
+ menu.setFont(font);
+ }
+
+ /**
+ * Handles mouse events by forwarding them to the Swing menu.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ menu.handleMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding them to the Swing menu.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ menu.handleMouseMotionEvent(ev);
+ }
+
+ /**
+ * Returns the X coordinate of the upper left corner of the menu. This is
+ * used internally by the SwingMenuBarPeer.
+ *
+ * @return the X coordinate of the upper left corner of the menu
+ */
+ int getX()
+ {
+ return menu.getX();
+ }
+
+ /**
+ * Returns the width of the menu. This is used internally by the
+ * SwingMenuBarPeer.
+ *
+ * @return the X coordinate of the upper left corner of the menu
+ */
+ int getWidth()
+ {
+ return menu.getWidth();
+ }
+
+ /**
+ * Returns the Y coordinate of the upper left corner of the menu. This is
+ * used internally by the SwingMenuBarPeer.
+ *
+ * @return the X coordinate of the upper left corner of the menu
+ */
+ public int getY()
+ {
+ return menu.getY();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java
new file mode 100644
index 00000000000..0a0f20fe826
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java
@@ -0,0 +1,67 @@
+/* SwingPanelPeer.java -- A PanelPeer based on Swing
+ 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.java.awt.peer.swing;
+
+import java.awt.Panel;
+import java.awt.peer.LightweightPeer;
+import java.awt.peer.PanelPeer;
+
+/**
+ * A panel peer based on Swing.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+// TODO: Maybe base implementation on JPanel. However, this doesn't seem
+// necessary, but might be good for more consistend Look.
+public class SwingPanelPeer
+ extends SwingContainerPeer
+ implements PanelPeer, LightweightPeer
+{
+
+ /**
+ * Creates a new instance of <code>SwingPanelPeer</code> for the specified
+ * AWT panel.
+ *
+ * @param panel the AWT panel
+ */
+ public SwingPanelPeer(Panel panel)
+ {
+ super(panel);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java
new file mode 100644
index 00000000000..a4c6d82d2cd
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java
@@ -0,0 +1,367 @@
+/* SwingTextFieldPeer.java -- A Swing based peer for AWT textfields
+ 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.java.awt.peer.swing;
+
+import java.awt.Dimension;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.TextField;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.im.InputMethodRequests;
+import java.awt.peer.TextFieldPeer;
+
+import javax.swing.JComponent;
+import javax.swing.JTextField;
+
+/**
+ * A TextFieldPeer based on Swing JTextField.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingTextFieldPeer
+ extends SwingComponentPeer
+ implements TextFieldPeer
+{
+
+ /**
+ * A specialized Swing textfield for use in the peer.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingTextField
+ extends JTextField
+ implements SwingComponent
+ {
+
+ /**
+ * Overridden to provide normal behaviour even without a real peer
+ * attached.
+ *
+ * @return the location of the textfield on screen
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingTextFieldPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (SwingTextFieldPeer.this.awtComponent != null)
+ retVal = SwingTextFieldPeer.this.awtComponent.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingTextFieldPeer.this.createImage(w, h);
+ }
+
+ /**
+ * Returns this textfield.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to the swing textfield.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to the swing textfield.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to the swing textfield.
+ *
+ * @param ev the key event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ ev.setSource(this);
+ processKeyEvent(ev);
+ }
+
+ }
+
+ /**
+ * Creates a new <code>SwingTextFieldPeer</code> instance for the specified
+ * AWT textfield.
+ *
+ * @param textField the AWT textfield
+ */
+ public SwingTextFieldPeer(TextField textField)
+ {
+ SwingTextField swingTextField = new SwingTextField();
+ swingTextField.setText(textField.getText());
+ init(textField, swingTextField);
+ }
+
+ /**
+ * Returns the minimum size of the textfield.
+ *
+ * @param len not used here
+ *
+ * @return the minimum size of the textfield
+ */
+ public Dimension minimumSize(int len)
+ {
+ return swingComponent.getJComponent().getMinimumSize();
+ }
+
+ /**
+ * Returns the preferred size of the textfield.
+ *
+ * @param len not used here
+ *
+ * @return the preferred size of the textfield
+ */
+ public Dimension preferredSize(int len)
+ {
+ return swingComponent.getJComponent().getPreferredSize();
+ }
+
+ /**
+ * Returns the minimum size of the textfield.
+ *
+ * @param len not used here
+ *
+ * @return the minimum size of the textfield
+ */
+ public Dimension getMinimumSize(int len)
+ {
+ return swingComponent.getJComponent().getMinimumSize();
+ }
+
+ /**
+ * Returns the preferred size of the textfield.
+ *
+ * @param len not used here
+ *
+ * @return the preferred size of the textfield
+ */
+ public Dimension getPreferredSize(int len)
+ {
+ return swingComponent.getJComponent().getPreferredSize();
+ }
+
+ /**
+ * Sets the echo character.
+ *
+ * @param echoChar the echo character to be set
+ */
+ public void setEchoChar(char echoChar)
+ {
+ // TODO: Must be implemented.
+ }
+
+ /**
+ * Sets the echo character.
+ *
+ * @param echoChar the echo character to be set
+ */
+ public void setEchoCharacter(char echoChar)
+ {
+ // TODO: Must be implemented.
+ }
+
+ /**
+ * Returns the end index of the current selection.
+ *
+ * @return the end index of the current selection
+ */
+ public int getSelectionEnd()
+ {
+ // TODO: Must be implemented.
+ return 0;
+ }
+
+ /**
+ * Returns the start index of the current selection.
+ *
+ * @return the start index of the current selection
+ */
+ public int getSelectionStart()
+ {
+ // TODO: Must be implemented.
+ return 0;
+ }
+
+ /**
+ * Returns the current content of the textfield.
+ *
+ * @return the current content of the textfield
+ */
+ public String getText()
+ {
+ return ((JTextField) swingComponent.getJComponent()).getText();
+ }
+
+ /**
+ * Sets the content of the textfield.
+ *
+ * @param text the text to set
+ */
+ public void setText(String text)
+ {
+ ((JTextField) swingComponent.getJComponent()).setText(text);
+ }
+
+ /**
+ * Sets the current selection.
+ *
+ * @param startPos the start index of the selection
+ * @param endPos the start index of the selection
+ */
+ public void select(int start_pos, int endPos)
+ {
+ // TODO: Must be implemented.
+ }
+
+ /**
+ * Sets the editable flag of the text field.
+ *
+ * @param editable <code>true</code> to make the textfield editable,
+ * <code>false</code> to make it uneditable
+ */
+ public void setEditable(boolean editable)
+ {
+ ((JTextField) swingComponent.getJComponent()).setEditable(editable);
+ }
+
+ /**
+ * Returns the current caret position.
+ *
+ * @return the current caret position
+ */
+ public int getCaretPosition()
+ {
+ return ((JTextField) swingComponent.getJComponent()).getCaret().getDot();
+ }
+
+ /**
+ * Sets the current caret position.
+ *
+ * @param pos the caret position to set
+ */
+ public void setCaretPosition(int pos)
+ {
+ ((JTextField) swingComponent.getJComponent()).getCaret().setDot(pos);
+ }
+
+ /**
+ * Returns the index of the character at the specified location.
+ *
+ * @param x the X coordinate of the point to query
+ * @param y the Y coordinate of the point to query
+ *
+ * @return the index of the character at the specified location
+ */
+ public int getIndexAtPoint(int x, int y)
+ {
+ // TODO: Must be implemented.
+ return 0;
+ }
+
+ /**
+ * Returns the bounds of the character at the specified index.
+ *
+ * @param pos the index of the character
+ *
+ * @return the bounds of the character at the specified index
+ */
+ public Rectangle getCharacterBounds(int pos)
+ {
+ // TODO: Must be implemented.
+ return null;
+ }
+
+ /**
+ * Not used.
+ */
+ public long filterEvents(long filter)
+ {
+ // TODO: Must be implemented.
+ return 0;
+ }
+
+ /**
+ * Not used.
+ */
+ public InputMethodRequests getInputMethodRequests()
+ {
+ // TODO: Must be implemented.
+ return null;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java
new file mode 100644
index 00000000000..166e1f47b6f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java
@@ -0,0 +1,165 @@
+/* SwingToolkit.java -- A base toolkit for Swing peers
+ 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.java.awt.peer.swing;
+
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Label;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.TextField;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.TextFieldPeer;
+
+import gnu.java.awt.ClasspathToolkit;
+
+/**
+ * A base implementation for {@link java.awt.Toolkit} that provides the
+ * Swing based widgets. Concrete implementations still must provide the
+ * remaining abstract methods.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public abstract class SwingToolkit extends ClasspathToolkit
+{
+
+ /**
+ * Creates a SwingButtonPeer.
+ *
+ * @param button the AWT button
+ *
+ * @return the Swing button peer
+ */
+ protected ButtonPeer createButton(Button button)
+ {
+ return new SwingButtonPeer(button);
+ }
+
+ /**
+ * Creates a SwingCanvasPeer.
+ *
+ * @param canvas the AWT canvas
+ *
+ * @return the Swing canvas peer
+ */
+ protected CanvasPeer createCanvas(Canvas canvas)
+ {
+ return new SwingCanvasPeer(canvas);
+ }
+
+ /**
+ * Creates a SwingLabelPeer.
+ *
+ * @param label the AWT label
+ *
+ * @return the Swing label peer
+ */
+ protected LabelPeer createLabel(Label label)
+ {
+ return new SwingLabelPeer(label);
+ }
+
+ /**
+ * Creates a SwingMenuPeer.
+ *
+ * @param menu the AWT menu
+ *
+ * @return the Swing menu peer
+ */
+ protected MenuPeer createMenu(Menu menu)
+ {
+ return new SwingMenuPeer(menu);
+ }
+
+ /**
+ * Creates a SwingMenuBarPeer.
+ *
+ * @param menuBar the AWT menubar
+ *
+ * @return the Swing menu bar peer
+ */
+ protected MenuBarPeer createMenuBar(MenuBar menuBar)
+ {
+ return new SwingMenuBarPeer(menuBar);
+ }
+
+ /**
+ * Creates a SwingMenuItemPeer.
+ *
+ * @param menuItem the AWT menu item
+ *
+ * @return the Swing menu item peer
+ */
+ protected MenuItemPeer createMenuItem(MenuItem menuItem)
+ {
+ return new SwingMenuItemPeer(menuItem);
+ }
+
+ /**
+ * Creates a SwingPanelPeer.
+ *
+ * @param panel the AWT panel
+ *
+ * @return the Swing panel peer
+ */
+ protected PanelPeer createPanel(Panel panel)
+ {
+ return new SwingPanelPeer(panel);
+ }
+
+ /**
+ * Creates a SwingTextFieldPeer.
+ *
+ * @param textField the AWT text field
+ *
+ * @return the Swing text field peer
+ */
+ protected TextFieldPeer createTextField(TextField textField)
+ {
+ return new SwingTextFieldPeer(textField);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java
new file mode 100644
index 00000000000..2f89795ca4f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java
@@ -0,0 +1,72 @@
+/* SwingWindowPeer.java -- An abstract base for Swing based window peers
+ 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.java.awt.peer.swing;
+
+import java.awt.Window;
+import java.awt.peer.WindowPeer;
+
+/**
+ * An abstract base class for Swing based WindowPeer implementation. Concrete
+ * implementations of WindowPeers should subclass this class in order to get
+ * the correct behaviour.
+ *
+ * As a minimum, a subclass must implement all the remaining abstract methods
+ * as well as the following methods:
+ * <ul>
+ * <li>{@link ComponentPeer#getLocationOnScreen()}</li>
+ * <li>{@link ComponentPeer#getGraphics()}</li>
+ * <li>{@link ComponentPeer#createImage(int, int)}</li>
+ * </ul>
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public abstract class SwingWindowPeer
+ extends SwingContainerPeer
+ implements WindowPeer
+{
+
+ /**
+ * Creates a new instance of WindowPeer.
+ *
+ * @param window the AWT window
+ */
+ public SwingWindowPeer(Window window)
+ {
+ super(window);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/package.html b/libjava/classpath/gnu/java/awt/peer/swing/package.html
new file mode 100644
index 00000000000..506eda883e4
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/package.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in gnu.java.awt.peer.swing package.
+ 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. -->
+
+<html>
+ <head>
+ <title>Swing based AWT peers</title>
+ </head>
+ <body>
+ <h1>Swing based AWT peers.</h1>
+ <p>This package defines an abstract set of AWT peers that is based on Swing
+ widgets. This can be used as an implementation base for peer implementors
+ who don't have access to native widgets or who want to build a quick
+ prototype of a peer set without implementing all of the AWT widgets.
+ </p>
+ <p>An actual implementation would have to provide the following:
+ <ul>
+ <li>A concrete implementation of {@link java.awt.Toolkit}, possibly based
+ on {@link SwingToolkit}. This implementation must provide all the missing
+ methods of the <code>SwingToolkit</code>.</li>
+ <li>Concrete implementations of {@link java.awt.peer.DialogPeer},
+ {@link java.awt.peer.FramePeer} and {@link java.awt.peer.WindowPeer},
+ ideally based on their <code>SwingXXXPeer</code> counterparts.
+ Some methods must be specially
+ overridden in those peers to provide useful functionality, like
+ <code>getLocationOnScreen()</code>. See the API documentation for more
+ details</li>
+ <li>An implementation of {@link java.awt.Image}. These must be provided by
+ the toplevel component peers.</li>
+ <li>An implementation of {@link java.awt.Graphics}. This must also be
+ provided by the toplevel peers.</li>
+ <li>An implementation of {@link java.awt.Font}. This must be
+ provided by the toolkit.</li>
+ </ul>
+ </p>
+ </body>
+</html>
diff --git a/libjava/classpath/gnu/java/beans/decoder/DefaultExceptionListener.java b/libjava/classpath/gnu/java/beans/DefaultExceptionListener.java
index 71e7158e7d2..42b31fae808 100644
--- a/libjava/classpath/gnu/java/beans/decoder/DefaultExceptionListener.java
+++ b/libjava/classpath/gnu/java/beans/DefaultExceptionListener.java
@@ -1,5 +1,5 @@
/* gnu.java.beans.DefaultExceptionListener
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,23 +35,32 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.java.beans.decoder;
+package gnu.java.beans;
import java.beans.ExceptionListener;
-/** The DefaultExceptionListener is the default implementation of the ExceptionListener
- * interface. An instance of this class is used whenever the user provided no
- * ExceptionListener instance on its own.
+/** The DefaultExceptionListener is the default implementation of the
+ * {@link ExceptionListener} interface. An instance of
+ * this class is used whenever the user provided no
+ * <code>ExceptionListener</code> instance on its own.
*
- * <p>The implementation just writes the exception's message to <code>System.err</code>.</p>
+ * <p>The implementation just writes the exception's message
+ * to <code>System.err</code> and is used by the {@link java.beans.Encoder}
+ * and the {@link java.beans.XMLDecoder}.
+ * </p>
*
- * @author Robert Schuster
+ * @author Robert Schuster (robertschuster@fsfe.org)
*/
public class DefaultExceptionListener implements ExceptionListener
{
+ public final static DefaultExceptionListener INSTANCE
+ = new DefaultExceptionListener();
+
public void exceptionThrown(Exception e)
{
- System.err.println("non-critical exception: " + e + " - message: "
+ System.err.println("exception thrown: "
+ + e + " - message: "
+ e.getMessage());
}
+
}
diff --git a/libjava/classpath/gnu/java/lang/CharData.java b/libjava/classpath/gnu/java/lang/CharData.java
index b12078d9f98..a84d94da21f 100644
--- a/libjava/classpath/gnu/java/lang/CharData.java
+++ b/libjava/classpath/gnu/java/lang/CharData.java
@@ -41,22 +41,26 @@ package gnu.java.lang;
/**
* This contains the info about the unicode characters, that
* java.lang.Character needs. It is generated automatically from
- * <code>doc/unicode/UnicodeData-3.0.0.txt</code> and
- * <code>doc/unicode/SpecialCasing-2.txt</code>, by some
- * perl scripts. These Unicode definition file can be found on the
+ * <code>../doc/unicode/UnicodeData-4.0.0.txt</code> and
+ * <code>../doc/unicode/SpecialCasing-4.0.0.txt</code>, by some
+ * perl scripts. These Unicode definition files can be found on the
* <a href="http://www.unicode.org">http://www.unicode.org</a> website.
- * JDK 1.4 uses Unicode version 3.0.0.
+ * JDK 1.5 uses Unicode version 4.0.0.
*
* The data is stored as string constants, but Character will convert these
- * Strings to their respective <code>char[]</code> components. The field
+ * Strings to their respective <code>char[]</code> components. The fields
+ * are stored in arrays of 17 elements each, one element per Unicode plane.
* <code>BLOCKS</code> stores the offset of a block of 2<sup>SHIFT</sup>
* characters within <code>DATA</code>. The DATA field, in turn, stores
* information about each character in the low order bits, and an offset
* into the attribute tables <code>UPPER</code>, <code>LOWER</code>,
* <code>NUM_VALUE</code>, and <code>DIRECTION</code>. Notice that the
* attribute tables are much smaller than 0xffff entries; as many characters
- * in Unicode share common attributes. The DIRECTION table also contains
- * a field for detecting characters with multi-character uppercase expansions.
+ * in Unicode share common attributes. Numbers that are too large to fit
+ * into NUM_VALUE as 16 bit chars are stored in LARGENUMS and a number N is
+ * stored in NUM_VALUE such that (-N - 3) is the offset into LARGENUMS for
+ * the particular character. The DIRECTION table also contains a field for
+ * detecting characters with multi-character uppercase expansions.
* Next, there is a listing for <code>TITLE</code> exceptions (most characters
* just have the same title case as upper case). Finally, there are two
* tables for multi-character capitalization, <code>UPPER_SPECIAL</code>
@@ -73,208 +77,622 @@ public interface CharData
/**
* The Unicode definition file that was parsed to build this database.
*/
- String SOURCE = "doc/unicode/UnicodeData-3.0.0.txt";
+ String SOURCE = "../doc/unicode/UnicodeData-4.0.0.txt";
/**
* The character shift amount to look up the block offset. In other words,
- * <code>(char) (BLOCKS.value[ch >> SHIFT] + ch)</code> is the index where
- * <code>ch</code> is described in <code>DATA</code>.
+ * <code>(char) (BLOCKS.value[ch >> SHIFT[p]] + ch)</code> is the index
+ * where <code>ch</code> is described in <code>DATA</code> if <code>ch</code>
+ * is in Unicode plane <code>p</code>. Note that <code>p</code> is simply
+ * the integer division of ch and 0x10000.
*/
- int SHIFT = 5;
+ int[] SHIFT
+ = new int[] {4, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8};
/**
* The mapping of character blocks to their location in <code>DATA</code>.
* Each entry has been adjusted so that the 16-bit sum with the desired
* character gives the actual index into <code>DATA</code>.
*/
- String BLOCKS
- = "\u01c2\u01c2\u01c1\u012c\u012b\u01a0\u01f8\u02dc\u025f\u02ee\u0215"
- + "\u0346\u02dc\u0326\u02bc\u0216\u015f\u02d4\u0376\u0376\u0376\u0369"
- + "\ufe8f\u0344\uff85\uff65\ufdb5\ufda1\033\u02c4\034G\ufea8"
- + "\uff8c\u0235\ufeff\032\ufebf&\ufb20\ufe28\u0113\u0104\ufb61"
- + "\ufb5a\u010b\u0109\u00fe\uff08\u0229\u025e\u01c7\u01fc\u01dc\ufc46"
- + "\u0229\ufe27\ufb55\u0169\ufbc8\u00fc\u0103\ufb68\ufb48\ufb28\ufb08"
- + "\ufae8\ufac8\ufaa8\ufa88\ufa68\ufa48eP\u00ab\u0139\ufe0e"
- + "c\u0155\u01a8\uf669\u0129\u0128\uf91f\ufe56\u0108\u0107\ufac0"
- + "\ufc8e\ufead\u00c6\ufca7\ufb95\uf47d\u009f\ufb17\ufe20\ufd28\ufb2f"
- + ";\uf3b9\ufe57\ufcce\uffbb\uf339\ufa98\uff8b\uff3b\ufa54\uf7e3"
- + "\uff2b\ufad7\ufb69\ufc3a\ufee5\uf4c8\ufcb0\ufa88\ufdbf\uf448\ufe45"
- + "\ufcc7\ufe4f\uf7f1\uf715\uf2e8\ufd9f\uf348\uf96a\ufc02\ufd97\uf2c8"
- + "\uf2a8\uf4b9\uf4b3\uef6b\uf86a\uf84a\ufc58\uf80a\uf7ea\ufc0f\uf7aa"
- + "\uee9c\ufb90\uf74a\uf7fa\uf70a\uf7ca\uf792\uf471\uf4d2\uf732\uf64a"
- + "\uf401\uf64d\uefa8\uf5ca\uf5aa\ueca1\uf569\uf54a\uf52a\uf50a\uf4ea"
- + "\uf4ca\uf4aa\uf48a\uf46a\uf44a\uf42a\uf40a\uf3ea\uf3ca\uf3aa\uf38a"
- + "\uf36a\uf34a\uf32a\uf289\uf777\uf2ca\uf2aa\uf737\uec28\uec08\uebe8"
- + "\uebc8\uf1ea\uf4a2\uf545\uedc6\uf2d7\uf14a\ue8ed\ue81e\uf0ea\uf597"
- + "\uea68\uea48\uea28\uea08\ue9e8\ue9c8\ue9a8\ue988\ue968\ue948\ue928"
- + "\ue908\ue8e8\ue8c8\ue8a8\ue888\ue868\ue848\ue828\ue808\ue7e8\ue7c8"
- + "\ue7a8\ue788\ue768\ue748\ue728\ue708\ue6e8\ue6c8\ue6a8\ue688\ue668"
- + "\ue648\ue628\ue608\ue5e8\ue5c8\ue5a8\ue588\ue568\ue548\ue55f\ue53f"
- + "\ue51f\ue4ff\uefd7\ue4bf\ue49f\ue485\uef87\uef57\uef57\uef57\uef57"
- + "\uef47\ue1ad\uef46\uef46\uef46\ue1e0\ue3dd\uef06\ue9d9\uebeb\ue244"
- + "\ueed4\uef65\ue1f5\uef45\ueee9\uef7c\uee74\uef70\uef7d\uef78\uee91"
- + "\uefd3\uee7d\uee25\uee27\uef65\uefdd\uee96\uefd3\uefe1\uef69\udf88"
- + "\udf68\udf48\ued2b\ued3d\ued19\uef1c\uef08\ued47\ued3d\ued33\uec2b"
- + "\uec0b\uebeb\uebcb\uebce\uea7c\ueb69\ueb6c\ue9b6\ueb0b\ueaeb\ue9e9"
- + "\udca8\udc88\udc68\udc48\ue910\uea23\ueb58\ueb4f\ueb45\ueae5\udb68"
- + "\udb48\ue92b\ue90b\ue8eb\ue8cb\ue8ab\ue88b\ue86b\ue84b\uda28\uda08"
- + "\ud9e8\ud9c8\ud9a8\ud988\ud968\ud948\ud928\ud908\ud8e8\ud8c8\ud8a8"
- + "\ud888\ud868\ud848\ud828\ud808\ud7e8\ud7c8\ud7a8\ud788\ud768\ud748"
- + "\ud728\ud708\ud6e8\ud6c8\ud6a8\ud688\ud668\ud648\ud628\ud608\ud5e8"
- + "\ud5c8\ud5a8\ud588\ud568\ud548\ud528\ud508\ud4e8\ud4c8\ue2b1\ue28b"
- + "\ue26b\ue270\ue22b\ue20b\ue1eb\ue1cb\ue1ab\ue18b\ue18e\udd8f\ue3a8"
- + "\udfd3\ud929\ud90a\ue348\ud8c9\ud8aa\udcd7\udcb2\ud681\ud82a\ud80a"
- + "\ue268\ucede\ud168\ud148\ue116\ue0e9\ue1cb\ue0b7\ue0b7\ue15e\udf17"
- + "\ue034\ue013\udff3\udfd3\ude6c\udf93\udf73\udf55\udf34\ud56a\ud54a"
- + "\ud52a\ud50a\ud4ea\ud4ca\ud4aa\ud48a\ud46a\ud44a\ud42a\ud40a\ud3ea"
- + "\ud3ca\ud3aa\ud38a\ud36a\ud34a\ud32a\ud30a\ud2ea\ud2ca\ud2aa\ud28a"
- + "\ud26a\ud24a\ud22a\ud20a\ud1ea\ud1ca\ud1aa\ud18a\ud16a\ud14a\ud12a"
- + "\ud10a\ud0ea\ud0ca\ud0aa\ud08a\ud06a\ud04a\ud02a\ud00a\ucfea\ucfca"
- + "\ucfaa\ucf8a\ucf6a\ucf4a\ucf2a\ucf0a\uceea\uceca\uceaa\uce8a\uce6a"
- + "\uce4a\uce2a\uce0a\ucdea\ucdca\ucdaa\ucd8a\ucd6a\ucd4a\ucd2a\ucd0a"
- + "\uccea\uccca\uccaa\ucc8a\ucc6a\ucc4a\ucc2a\ucc0a\ucbea\ucbca\ucbaa"
- + "\ucb8a\ucb6a\ucb4a\ucb2a\ucb0a\ucaea\ucaca\ucaaa\uca8a\uca6a\uca4a"
- + "\uca2a\uca0a\uc9ea\uc9ca\uc9aa\uc98a\uc96a\uc94a\uc92a\uc90a\uc8ea"
- + "\uc8ca\uc8aa\uc88a\uc86a\uc84a\uc82a\uc80a\uc7ea\uc7ca\uc7aa\uc78a"
- + "\uc76a\uc74a\uc72a\uc70a\uc6ea\uc6ca\uc6aa\uc68a\uc66a\uc64a\uc62a"
- + "\uc60a\uc5ea\uc5ca\uc5aa\uc58a\uc56a\uc54a\uc52a\uc50a\uc4ea\uc4ca"
- + "\uc4aa\uc48a\uc46a\uc44a\uc42a\uc40a\uc3ea\uc3ca\uc3aa\uc38a\uc36a"
- + "\uc34a\uc32a\uc30a\uc2ea\uc2ca\uc2aa\uc28a\uc26a\uc24a\uc22a\uc20a"
- + "\uc1ea\uc1ca\uc1aa\uc18a\uc16a\uc14a\uc12a\uc10a\uc0ea\uc0ca\uc0aa"
- + "\uc08a\uc06a\uc04a\uc02a\uc00a\ubfea\ubfca\ubfaa\ubf8a\ubf6a\ubf4a"
- + "\ubf2a\ubf0a\ubeea\ubeca\ubeaa\ube8a\ube6a\ube4a\ube2a\ube0a\ubdea"
- + "\ubdca\ubdaa\ubd8a\ubd6a\ubd4a\ubd2a\ubd0a\ubcea\ubcca\ubcaa\ubc8a"
- + "\ubc6a\ubc4a\ubc2a\ubc0a\ubbea\ub2e0\ub568\ub548\ubb6a\ubb4a\ubb2a"
- + "\ubb0a\ubaea\ubaca\ubaaa\uba8a\uba6a\uba4a\uba2a\uba0a\ub9ea\ub9ca"
- + "\ub9aa\ub98a\ub96a\ub94a\ub92a\ub90a\ub8ea\ub8ca\ub8aa\ub88a\ub86a"
- + "\ub84a\ub82a\ub80a\ub7ea\ub7ca\ub7aa\ub78a\ub76a\ub74a\ub72a\ub70a"
- + "\ub6ea\ub6ca\ub6aa\ub68a\ub66a\ub64a\ub62a\ub60a\ub5ea\ub5ca\ub5aa"
- + "\ub58a\ub56a\ub54a\ub52a\ub50a\ub4ea\ub4ca\ub4aa\ub48a\ub46a\ub44a"
- + "\ub42a\ub40a\ub3ea\ub3ca\ub3aa\ub38a\ub36a\ub34a\ub32a\ub30a\ub2ea"
- + "\ub2ca\ub2aa\ub28a\ub26a\ub24a\ub22a\ub20a\ub1ea\ub1ca\ub1aa\ub18a"
- + "\ub16a\ub14a\ub12a\ub10a\ub0ea\ub0ca\ub0aa\ub08a\ub06a\ub04a\ub02a"
- + "\ub00a\uafea\uafca\uafaa\uaf8a\uaf6a\uaf4a\uaf2a\uaf0a\uaeea\uaeca"
- + "\uaeaa\uae8a\uae6a\uae4a\uae2a\uae0a\uadea\uadca\uadaa\uad8a\uad6a"
- + "\uad4a\uad2a\uad0a\uacea\uacca\uacaa\uac8a\uac6a\uac4a\uac2a\uac0a"
- + "\uabea\uabca\uabaa\uab8a\uab6a\uab4a\uab2a\uab0a\uaaea\uaaca\uaaaa"
- + "\uaa8a\uaa6a\uaa4a\uaa2a\uaa0a\ua9ea\ua9ca\ua9aa\ua98a\ua96a\ua94a"
- + "\ua92a\ua90a\ua8ea\ua8ca\ua8aa\ua88a\ua86a\ua84a\ua82a\ua80a\ua7ea"
- + "\ua7ca\ua7aa\ua78a\ua76a\ua74a\ua72a\ua70a\ua6ea\ua6ca\ua6aa\ua68a"
- + "\ua66a\ua64a\ua62a\ua60a\ua5ea\ua5ca\ua5aa\ua58a\ua56a\ua54a\ua52a"
- + "\ua50a\ua4ea\ua4ca\ua4aa\ua48a\ua46a\ua44a\ua42a\ua40a\ua3ea\ua3ca"
- + "\ua3aa\ua38a\ua36a\ua34a\ua32a\ua30a\ua2ea\ua2ca\ua2aa\ua28a\ua26a"
- + "\ua24a\ua22a\ua20a\ua1ea\ua1ca\ua1aa\ua18a\ua16a\ua14a\ua12a\ua10a"
- + "\ua0ea\ua0ca\ua0aa\ua08a\ua06a\ua04a\ua02a\ua00a\u9fea\u9fca\u9faa"
- + "\u9f8a\u9f6a\u9f4a\u9f2a\u9f0a\u9eea\u9eca\u9eaa\u9e8a\u9e6a\u9e4a"
- + "\u9e2a\u9e0a\u9dea\u9dca\u9daa\u9d8a\u9d6a\u9d4a\u9d2a\u9d0a\u9cea"
- + "\u9cca\u9caa\u9c8a\u9c6a\u9c4a\u9c2a\u9c0a\u9bea\u9bca\u9baa\u9b8a"
- + "\u9b6a\u9b4a\u9b2a\u9b0a\u9aea\u9aca\u9aaa\u9a8a\u9a6a\u9a4a\u9a2a"
- + "\u9a0a\u99ea\u99ca\u99aa\u998a\u996a\u994a\u992a\u990a\u98ea\u98ca"
- + "\u98aa\u988a\u986a\u984a\u982a\u980a\u97ea\u97ca\u97aa\u978a\u976a"
- + "\u974a\u972a\u970a\u96ea\u96ca\u96aa\u968a\u966a\u964a\u962a\u960a"
- + "\u95ea\u95ca\u95aa\u958a\u956a\u954a\u952a\u950a\u94ea\u94ca\u94aa"
- + "\u948a\u946a\u944a\u942a\u940a\u93ea\u93ca\u93aa\u938a\u936a\u934a"
- + "\u932a\u930a\u92ea\u92ca\u92aa\u928a\u926a\u924a\u922a\u920a\u91ea"
- + "\u91ca\u91aa\u918a\u916a\u914a\u912a\u910a\u90ea\u90ca\u90aa\u908a"
- + "\u906a\u904a\u902a\u900a\u8fea\u8fca\u8faa\u8f8a\u8f6a\u8f4a\u8f2a"
- + "\u8f0a\u8eea\u8eca\u8eaa\u8e8a\u8e6a\u8e4a\u8e2a\u8e0a\u8dea\u8dca"
- + "\u8daa\u8d8a\u8d6a\u8d4a\u8d2a\u8d0a\u8cea\u8cca\u8caa\u8c8a\u8c6a"
- + "\u8c4a\u8c2a\u8c0a\u8bea\u8bca\u8baa\u8b8a\u8b6a\u8b4a\u8b2a\u8b0a"
- + "\u8aea\u8aca\u8aaa\u8a8a\u8a6a\u8a4a\u8a2a\u8a0a\u89ea\u89ca\u89aa"
- + "\u898a\u896a\u894a\u892a\u890a\u88ea\u88ca\u88aa\u888a\u886a\u884a"
- + "\u882a\u880a\u87ea\u87ca\u87aa\u878a\u876a\u874a\u872a\u870a\u86ea"
- + "\u86ca\u86aa\u868a\u866a\u864a\u862a\u860a\u85ea\u85ca\u85aa\u858a"
- + "\u856a\u854a\u852a\u850a\u84ea\u84ca\u84aa\u848a\u846a\u844a\u842a"
- + "\u840a\u83ea\u83ca\u83aa\u838a\u836a\u834a\u832a\u830a\u82ea\u82ca"
- + "\u82aa\u828a\u826a\u824a\u822a\u820a\u81ea\u81ca\u81aa\u818a\u816a"
- + "\u814a\u812a\u810a\u80ea\u80ca\u80aa\u808a\u806a\u804a\u802a\u800a"
- + "\u7fea\u7fca\u7faa\u7f8a\u7f6a\u7f4a\u7f2a\u7f0a\u7eea\u7eca\u7eaa"
- + "\u7e8a\u7e6a\u7e4a\u7e2a\u7e0a\u7dea\u7dca\u7daa\u7d8a\u7d6a\u7d4a"
- + "\u7d2a\u7d0a\u7cea\u7cca\u7caa\u7c8a\u7c6a\u7c4a\u7c2a\u7c0a\u7bea"
- + "\u7bca\u7baa\u7b8a\u7b6a\u7b4a\u7b2a\u7b0a\u7aea\u7aca\u7aaa\u7a8a"
- + "\u7a6a\u7a4a\u7a2a\u7a0a\u79ea\u79ca\u79aa\u798a\u796a\u794a\u792a"
- + "\u790a\u78ea\u78ca\u78aa\u788a\u786a\u784a\u782a\u780a\u77ea\u77ca"
- + "\u77aa\u778a\u776a\u774a\u772a\u770a\u76ea\u76ca\u76aa\u768a\u766a"
- + "\u764a\u762a\u760a\u75ea\u75ca\u75aa\u758a\u756a\u754a\u752a\u750a"
- + "\u74ea\u74ca\u74aa\u748a\u746a\u744a\u742a\u740a\u73ea\u73ca\u73aa"
- + "\u738a\u736a\u734a\u732a\u730a\u72ea\u72ca\u72aa\u728a\u726a\u724a"
- + "\u722a\u720a\u71ea\u71ca\u71aa\u718a\u716a\u714a\u712a\u710a\u70ea"
- + "\u70ca\u70aa\u708a\u706a\u704a\u702a\u700a\u6fea\u6fca\u6faa\u6f8a"
- + "\u6f6a\u6f4a\u6f2a\u6f0a\u6eea\u6eca\u6eaa\u6e8a\u6e6a\u6e4a\u6e2a"
- + "\u6e0a\u6dea\u6dca\u6daa\u6d8a\u6d6a\u6d4a\u6d2a\u6d0a\u6cea\u6cca"
- + "\u6caa\u6c8a\u6c6a\u6c4a\u6c2a\u6c0a\u6bea\u6bca\u6baa\u6b8a\u6b6a"
- + "\u6b4a\u6b2a\u6b0a\u6aea\u6aca\u6aaa\u6a8a\u6a6a\u6a4a\u6a2a\u6a0a"
- + "\u69ea\u60f0\u6368\u6348\u696a\u694a\u692a\u690a\u68ea\u68ca\u68aa"
- + "\u688a\u686a\u684a\u682a\u680a\u67ea\u67ca\u67aa\u678a\u676a\u674a"
- + "\u672a\u670a\u66ea\u66ca\u66aa\u668a\u666a\u664a\u662a\u660a\u65ea"
- + "\u65ca\u65aa\u658a\u656a\u654a\u652a\u650a\u6b26\u6de1\u6e9c\u5e48"
- + "\u5e28\u5e08\u5de8\u5dc8\u5da8\u5d88\u5d68\u5d48\u5d28\u5d08\u5ce8"
- + "\u5cc8\u5ca8\u5c88\u5c68\u5c48\u5c28\u5c08\u5be8\u5bc8\u5ba8\u5b88"
- + "\u5b68\u5b48\u5b28\u5b08\u5ae8\u5ac8\u5aa8\u5a88\u5a68\u5a48\u5a28"
- + "\u5a08\u59e8\u59c8\u59a8\u5988\u5968\u5948\u5928\u5908\u58e8\u58c8"
- + "\u58a8\u5888\u5868\u5848\u5828\u5808\u57e8\u57c8\u57a8\u5788\u5768"
- + "\u5748\u5d6a\u5d4a\u5d2a\u5d0a\u5cea\u5cca\u5caa\u5c8a\u5c6a\u5c4a"
- + "\u5c2a\u5c0a\u5bea\u5bca\u5baa\u5b8a\u5b6a\u5b4a\u5b2a\u5b0a\u5aea"
- + "\u5aca\u5aaa\u5a8a\u5a6a\u5a4a\u5a2a\u5a0a\u59ea\u59ca\u59aa\u598a"
- + "\u596a\u594a\u592a\u590a\u58ea\u58ca\u58aa\u588a\u586a\u584a\u582a"
- + "\u580a\u57ea\u57ca\u57aa\u578a\u576a\u574a\u572a\u570a\u56ea\u56ca"
- + "\u56aa\u568a\u566a\u564a\u562a\u560a\u55ea\u55ca\u55aa\u558a\u556a"
- + "\u554a\u552a\u550a\u54ea\u54ca\u54aa\u548a\u546a\u544a\u542a\u540a"
- + "\u53ea\u53ca\u53aa\u538a\u536a\u534a\u532a\u530a\u52ea\u52ca\u52aa"
- + "\u528a\u526a\u524a\u522a\u520a\u51ea\u51ca\u51aa\u518a\u516a\u514a"
- + "\u512a\u510a\u50ea\u50ca\u50aa\u508a\u506a\u504a\u502a\u500a\u4fea"
- + "\u4fca\u4faa\u4f8a\u4f6a\u4f4a\u4f2a\u4f0a\u4eea\u4eca\u4eaa\u4e8a"
- + "\u4e6a\u4e4a\u4e2a\u4e0a\u4dea\u4dca\u4daa\u4d8a\u4d6a\u4d4a\u4d2a"
- + "\u4d0a\u4cea\u4cca\u4caa\u4c8a\u4c6a\u4c4a\u4c2a\u4c0a\u4bea\u4bca"
- + "\u4baa\u4b8a\u4b6a\u4b4a\u4b2a\u4b0a\u4aea\u4aca\u4aaa\u4a8a\u4a6a"
- + "\u4a4a\u4a2a\u4a0a\u49ea\u49ca\u49aa\u498a\u496a\u494a\u492a\u490a"
- + "\u48ea\u48ca\u48aa\u488a\u486a\u484a\u482a\u480a\u47ea\u47ca\u47aa"
- + "\u478a\u476a\u474a\u472a\u470a\u46ea\u46ca\u46aa\u468a\u466a\u464a"
- + "\u462a\u460a\u45ea\u45ca\u45aa\u458a\u456a\u454a\u452a\u450a\u44ea"
- + "\u44ca\u44aa\u448a\u446a\u444a\u442a\u440a\u43ea\u43ca\u43aa\u438a"
- + "\u436a\u434a\u432a\u430a\u42ea\u42ca\u42aa\u428a\u426a\u424a\u422a"
- + "\u420a\u41ea\u41ca\u41aa\u418a\u416a\u414a\u412a\u410a\u40ea\u40ca"
- + "\u40aa\u408a\u406a\u404a\u402a\u400a\u3fea\u3fca\u3faa\u3f8a\u3f6a"
- + "\u3f4a\u3f2a\u3f0a\u3eea\u3eca\u3eaa\u3e8a\u3e6a\u3e4a\u3e2a\u3e0a"
- + "\u3dea\u3dca\u3daa\u3d8a\u3d6a\u3d4a\u3d2a\u3d0a\u3cea\u3cca\u3caa"
- + "\u3c8a\u3c6a\u3c4a\u3c2a\u3c0a\u3bea\u3bca\u3baa\u3b8a\u3b6a\u3b4a"
- + "\u3b2a\u3b0a\u3aea\u3aca\u3aaa\u3a8a\u3a6a\u3a4a\u3a2a\u3a0a\u39ea"
- + "\u39ca\u39aa\u398a\u396a\u394a\u392a\u390a\u38ea\u38ca\u38aa\u388a"
- + "\u386a\u384a\u382a\u380a\u37ea\u37ca\u37aa\u378a\u376a\u374a\u372a"
- + "\u370a\u36ea\u36ca\u36aa\u368a\u366a\u364a\u362a\u360a\u35ea\u35ca"
- + "\u35aa\u358a\u356a\u354a\u352a\u350a\u34ea\u34ca\u34aa\u348a\u346a"
- + "\u344a\u342a\u340a\u33ea\u33ca\u33aa\u338a\u336a\u334a\u332a\u330a"
- + "\u32ea\u32ca\u32aa\u328a\u326a\u324a\u322a\u320a\u31ea\u28f2\u2b68"
- + "\u2b48\u3c2b\u3c0b\u3beb\u3bcb\u3bab\u3b8b\u3b6b\u3b4b\u3b2b\u3b0b"
- + "\u3aeb\u3acb\u3aab\u3a8b\u3a6b\u3a4b\u3a2b\u3a0b\u39eb\u39cb\u39ab"
- + "\u398b\u396b\u394b\u392b\u390b\u38eb\u38cb\u38ab\u388b\u386b\u384b"
- + "\u382b\u380b\u37eb\u37cb\u37ab\u378b\u376b\u374b\u372b\u370b\u36eb"
- + "\u36cb\u36ab\u368b\u366b\u364b\u362b\u360b\u35eb\u35cb\u35ab\u358b"
- + "\u356b\u354b\u352b\u350b\u34eb\u34cb\u34ab\u348b\u346b\u344b\u344b"
- + "\u342b\u340b\u33eb\u33cb\u33ab\u338b\u336b\u334b\u332b\u330b\u32eb"
- + "\u32cb\u32ab\u328b\u326b\u324b\u322b\u320b\u31eb\u31cb\u31ab\u318b"
- + "\u316b\u314b\u312b\u310b\u30eb\u30cb\u30ab\u308b\u306b\u304b\u302b"
- + "\u300b\u2feb\u2fcb\u2fab\u2f8b\u2f6b\u2f4b\u2f2b\u2f0b\u2eeb\u2ecb"
- + "\u2eab\u2e8b\u2e6b\u2e4b\u2e2b\u2e0b\u2deb\u2dcb\u2dab\u2d8b\u2d6b"
- + "\u2d4b\u2d2b\u2d0b\u2ceb\u2ccb\u2cab\u2c8b\u2c6b\u2c4b\u2c2b\u2c0b"
- + "\u2beb\u2bcb\u2bab\u2b8b\u2b6b\u2b4b\u2b2b\u2b0b\u2aeb\u2acb\u2aab"
- + "\u2a8b\u2a6b\u2a4b\u2a2b\u2a0b\u29eb\u29cb\u29ab\u298b\u296b\u294b"
- + "\u292b\u290b\u28eb\u28cb\u28ab\u288b\u286b\u284b\u282b\u280b\u27eb"
- + "\u27cb\u27ab\u278b\u276b\u274b\u272b\u270b\u26eb\u26cb\u26ab\u268b"
- + "\u266b\u264b\u262b\u260b\u25eb\u25cb\u25ab\u258b\u256b\u254b\u252b"
- + "\u250b\u24eb\u24cb\u24ab\u248b\u246b\u244b\u242b\u240b\u23eb\u23cb"
- + "\u23ab\u238b\u236b\u234b\u232b\u230b\u22eb\u22cb\u22ab\u228b\u226b"
- + "\u224b\u222b\u220b\u21eb\u21cb\u21ab\u218b\u216b\u214b\u212b\u210b"
- + "\u20eb\u20cb\u20ab\u208b\u206b\u204b\u202b\u200b\u1feb\u1fcb\u1fab"
- + "\u1f8b\u1f6b\u1f4b\u1f2b\u1f0b\u1eeb\u1ecb\u1eab\u1e8b\u1e6b\u1e4b"
- + "\u1e2b\u1e0b\u1deb\u1dcb\u1dab\u1d8b\u1d6b\u1d4b\u1d2b\u1d0b\u1ceb"
- + "\u1ccb\u1cab\u1c8b\u1c6b\u1c4b\u1c2b\u1c0b\u1beb\u1bcb\u1bab\u1b8b"
- + "\u1b6b\u106a\u104a\u102a\u100a\u0fea\u0fca\u0faa\u0f8a\u0f6a\u0668"
- + "\u08e8\u08c8\u08a8\u0888\u0868\u0848\u07d7\u194b\u07b6\u0d1c\u0cfc"
- + "\u0cb2\u0ca9\u0c9c\u0c7c\u0c5c\u0c3c\u0c1c\u0bfc\u0bdc\u0bbc\u0b9c"
- + "\u0b7c\u0b5e\u0b2c\u0b1c\u0ab8\u0adc\u0a9c\u02c2\u0528\u166b\u1667"
- + "\u03ff\u09fc\u09dc\u09bc\u0659\u0bb8\u15a7\u0fc6\u01c0\u01b1\u09cb"
- + "\u082c\u1285";
+ String[] BLOCKS = new String[]{
+ "\017\0275\00744Z\uff90\uff9d\uff93\013"
+ + "\uffb5\013\004\034\025\027\007\ufff7\u00ad\u010d\uffc7"
+ + "\uffb7\uff7b\u0111\u0111\u00b7\u0101\uffdc\uff4a\uff37\ufef3\uff17"
+ + "\uff07\ufef5\uff79\u00dc2\u0141\005\uffe7\u013d\u0130\u0137"
+ + "\u0163\u0163\u0112\u0145\u0166\u0156\u0146\u0136\uff81\u0191\u0106"
+ + "\ufe84\u01ca\ufd3a\u01ba\ufd4b\u01aa\ufe74\ufd37\u014e\u01b3\ufcbb"
+ + "\ufcab\ufccc\ufcbc\u0173\ufcb7\ufca7\ufca8\ufc87\ufc77\ufc67\u0113"
+ + "\ufc47\ufc37\ufc42\ufc17\ufe0c\ufdfc\ufcd3\ufcc4\ufcbd\ufe0a\ufdfb"
+ + "\ufdf4\ufed5\ufec3\ufd17\ufd15\u008a\u007f\u00b5\ufdb1\u00dc\ufd6e"
+ + "\u00f9\u00cb\uffe3k\u00f9\ufd0f\ufcff\ufcef\ufcdf\ufccf\011"
+ + "\u00abi\ufffbX\ufc6f\ufd36\uffd6\ufbcc\ufbbc\ufbac\ufc0f"
+ + "\ufbff\uff70\ufff9\ufb5c\ufb4c\ufb3c\ufb2c\ufb1c\ufb0c\ufafc\ufaec"
+ + "\ufadc\ufacc\ufabc\ufaac\ufa9c\ufa8c\ufa7c\ufa6c\ufa5c\ufa4c\ufa3c"
+ + "\ufa2c\ufee1\ufb03\ufaf3\ufef3\ufcd4\uff0b\uff13\uf9ab\ufb8a\uf7fa"
+ + "\ufa69\ufbe5\ufb6e\uf90e\ufea9\ufeaf\ufb79\uf77a\uf9e9\uf8c7\ufdfc"
+ + "\uf760\ufb82\ufe3f\uf6e4\uf980\uf969\uf70e\ufbc6\uf764\ufda9\ufddd"
+ + "\ufa0a\uf67a\uf8e9\ufb48\uf68d\uf5ec\ufd91\uf6c3\uf7c4\uf75b\uf7af"
+ + "\uf75b\uf93b\ufade\ufb5b\ufd17\uf704\uf801\uf7e9\ufba4\ufcd7\uf72f"
+ + "\ufc91\uf6ac\ufb4b\uf781\uf769\ufc77\ufb71\uf99a\ufc11\uf62c\ufacb"
+ + "\uf701\uf6e9\ufa8f\ufbf7\uf95e\ufb91\uf5ac\ufbd4\uf3eb\uf673\uf7da"
+ + "\ufb87\uf832\uf53c\uf527\uf612\uf603\uf5f3\ufa8f\ufa9d\ufa29\uf4bc"
+ + "\uf4ac\uf2c7\uf6f4\uf678\ufab9\ufab9\uf9bf\uf43c\uf42c\ufa89\uf30a"
+ + "\uf6c8\uf6c4\uf4ca\uf4c3\uf89b\uf57d\uf967\uf4cd\uf4c6\uf4b9\uf264"
+ + "\uf34c\uf33c\uf32c\uf413\uf403\uf502\uf969\uf8b7\uf959\uf2bc\uf2ac"
+ + "\uf29c\uf28c\uf927\uf917\uf911\uf343\uf333\uf773\uf313\uf303\uf2f3"
+ + "\uf2e3\uf2d3\uf6ac\uf2b3\uf2a3\uf293\uf283\uf663\uf263\uf253\uf243"
+ + "\uf233\uf7f1\uf20b\uf203\uf1f3\uf1e3\uef2b\uef1b\uf1b3\uf1a3\ueeeb"
+ + "\uf183\uf163\ueec3\ueeb3\uf13b\uf123\uf123\uf103\uee63\uf0f3\uf0e3"
+ + "\uf0cb\uf4ab\uf2c3\uf3d9\uef9c\uef8c\uf073\uf063\uf053\uf043\uf033"
+ + "\uf5f6\uf012\uf003\ueff3\uefe3\uefd3\uefc3\uefb3\uefa3\uef93\uef83"
+ + "\uef73\uef63\uef53\uef43\uef33\uef23\uef13\uef03\ueef3\ueee3\ueed3"
+ + "\ueec3\ueeb3\ueea3\uee93\uee83\uee73\uee63\uee53\uee43\uee33\uee23"
+ + "\uee13\uee03\uedf3\uede3\uedd3\uedc3\ueb2d\uf374\uf176\uf156\ued73"
+ + "\ued63\ued53\ued43\uf279\uf307\ued05\uf2f7\uecf3\uf2e7\uecd3\uf2d7"
+ + "\ueca5\uf2c7\uec93\uec83\uec73\uf297\uee4c\uf292\ueb56\uf291\uf291"
+ + "\ueb26\uebf3\uebe3\uefda\uebc3\uebb3\uf173\ueb93\ueb83\uf201\uea6c"
+ + "\uea5c\uea4c\uea3c\uea2c\ueb13\ueee9\uf132\uec73\ue9f0\ueac3\uee98"
+ + "\uf076\ue99c\ue98c\ue97c\ue96c\ue95c\ue94c\uf0e4\uf0d4\ue91c\ue90c"
+ + "\ue8fc\ue8ec\ue8dc\ue8cc\ue8bc\ue8ac\ue89c\ue88c\ue87c\ue86c\ue85c"
+ + "\ue84c\ue83c\ue82c\ue81c\ue80c\ue7fc\ue7ec\ue7dc\ue7cc\ue7bc\ue7ac"
+ + "\ue79c\ue78c\ue77c\ue76c\ue75c\ue74c\ue73c\ue72c\ue71c\ue70c\ue6fc"
+ + "\ue6ec\ue6dc\ue6cc\ue6bc\ue6ac\ue69c\ue68c\ue67c\ue66c\ue65c\ue64c"
+ + "\ue63c\ue62c\ue6d0\ue6c0\ue6b4\ue6b0\ue6a0\ue690\uee5e\ue5ac\ue59c"
+ + "\ue58c\ue57c\ue56c\ue55c\ue54c\ue53c\ue52c\ue317\ue307\ue2f7\ue2e7"
+ + "\ue2d7\ue2c7\ue2b7\ue2a7\ue297\ue358\ue277\ue267\ue257\ue247\ue237"
+ + "\ue6e8\uecce\uecce\uecae\uec9e\uec9e\uec9e\uec6e\uec8e\uec8e\uec7e"
+ + "\uec6e\uec6e\ue483\uec5e\uec5e\ue165\uec4e\uec4e\ue07b\uec4d\ue053"
+ + "\udff6\ue71b\uec1d\uec1d\ue28c\uec0d\uec0b\ue25c\uebfb\ue607\ue22c"
+ + "\ue2bf\ue9a1\uea8e\ue889\uec17\ue56b\uec07\uec07\uec07\uea12\uebf7"
+ + "\ue914\ue906\ue8ef\ue8e4\ue8e0\ue967\ueb1b\ueb16\ue8d2\ueacf\uea9a"
+ + "\ue8b9\uea9c\ue8d2\ue8f5\uea66\uea63\uea30\ue87c\uea2e\uea1c\ueaa6"
+ + "\ue7b4\uea90\uea8b\uea81\uea71\uea61\ue10d\ue744\ue114\ue734\ue100"
+ + "\ue704\uea29\udf3c\udf2c\ue6c4\ue6b4\ue9d3\udeec\ue9af\udecc\ue9b1"
+ + "\ue99d\ue989\ue989\ue921\ue9aa\ue9a0\ue9a0\ue996\ue582\ue5c4\ue5b4"
+ + "\ue5a4\ue594\ue584\ue574\ue564\ue554\ue544\ue534\ue524\ue7ee\ue502"
+ + "\ue4f4\ue4e4\ue4dc\ue4c4\udea9\ue4a4\ue494\ue484\ue474\ue465\ue77c"
+ + "\ue444\ue768\ue758\udc6c\udc5c\udc4c\udc3c\udc2c\udd98\ue3b4\udd99"
+ + "\ue394\udd4a\ue744\udd61\udd5b\udd51\ue654\ue324\ue63b\udb5c\ue50b"
+ + "\ue6c4\ue2e4\ue2c4\ue2b4\ue2a4\ue294\ue284\ue274\ue264\ue254\ue244"
+ + "\ue234\ue224\ue214\ue204\ue1f4\ue1e4\ue1d4\ue1d4\ue1c4\ue1b4\ue1a4"
+ + "\ue194\ue184\ue174\ue164\ue16e\ue166\ue36c\ue1de\ue1af\ue37b\ue14f"
+ + "\ue0f0\ue0da\ue331\ue13d\ue149\ue094\ue147\ue2bd\ue0d9\ue28c\ue27c"
+ + "\ue081\ue25c\ue24c\ue03d\ue217\ue04c\ue2ec\ud80c\ud7fc\ud7ec\ud7dc"
+ + "\ud7cc\ud7bc\ud7ac\ud79c\ud78c\ud77c\ud76c\ud75c\ud74c\ud73c\ud72c"
+ + "\ud71c\ud70c\ud6fc\ud6ec\ud6dc\ud6cc\ud6bc\ud6ac\ud69c\ud68c\ud67c"
+ + "\ud66c\ud65c\ud64c\ud63c\ud62c\ud61c\ud60c\ud5fc\ud5ec\ud5dc\ud5cc"
+ + "\ud5bc\ud5ac\ud59c\ud58c\ud57c\ud56c\ud55c\ud54c\ud53c\ud52c\ud51c"
+ + "\ud50c\ud4fc\ud4ec\ud4dc\ud4cc\ud4bc\ud4ac\udc44\ud627\udc24\udc14"
+ + "\udc04\udbf4\udbe4\udf06\udbc4\udbb4\udba4\udb94\udb84\udb74\udb64"
+ + "\udb54\udb44\udb34\udb24\udb14\udb04\ude24\ud33c\uddfe\udeb4\udeb2"
+ + "\ud433\ude56\ud3d2\ud3c3\ud3b3\ud3a3\ud393\ud7bc\ud362\ud363\ud353"
+ + "\ud343\ud333\ud71b\ud706\ud303\ud6d9\ud2e2\ud2d3\ud2c3\ud2b3\ud2a3"
+ + "\ud283\ud2e7\ud273\ud833\ud15c\ud14c\ud13c\ud223\udbc1\udbb4\udc30"
+ + "\udb91\udc00\udc82\udb61\udb55\udbd0\udb31\udb21\udb24\udb65\udaf1"
+ + "\udae1\udb45\udac1\udab1\udaa1\uda91\uda81\uda71\uda61\udaba\uda41"
+ + "\uda31\uda21\uda11\uda01\ud9f3\ud9e1\ud9d2\ud013\ud003\ucff3\ucfe3"
+ + "\ucfd3\ucfc3\ucfb3\ucfa3\ucf93\ucf83\ucf73\ucf63\ucf53\ucf43\ucf33"
+ + "\ucf23\ucf13\ucf03\ucef3\ucee3\uced3\ucec3\uceb3\ucea3\uce93\uce83"
+ + "\uce73\uce63\uce53\uce43\uce33\uce23\uce13\uce03\ucdf3\ucde3\ucdd3"
+ + "\ucdc3\ucdb3\ucda3\ucd93\ucd83\ucd73\ucd63\ucd53\ucd43\ucd33\ucd23"
+ + "\ucd13\ucd03\uccf3\ucce3\uccd3\uccc3\uccb3\ucca3\ucc93\ucc83\ucc73"
+ + "\ucc63\ucc53\ucc43\ucc33\ucc23\ucc13\ucc03\ucbf3\ucbe3\ucbd3\ucbc3"
+ + "\ucbb3\ucba3\ucb93\ucb83\ucb73\ucb63\ucb53\ucb43\ucb33\ucb23\ucb13"
+ + "\ucb03\ucaf3\ucae3\ucad3\ucac3\ucab3\ucaa3\uca93\uca83\uca73\uca63"
+ + "\uca53\uca43\uca33\uca23\uca13\uca03\uc9f3\uc9e3\uc9d3\uc9c3\uc9b3"
+ + "\uc9a3\uc993\uc983\uc973\uc963\uc953\uc943\uc933\uc923\uc913\uc903"
+ + "\uc8f3\uc8e3\uc8d3\uc8c3\uc8b3\uc8a3\uc893\uc883\uc873\uc863\uc853"
+ + "\uc843\uc833\uc823\uc813\uc803\uc7f3\uc7e3\uc7d3\uc7c3\uc7b3\uc7a3"
+ + "\uc793\uc783\uc773\uc763\uc753\uc743\uc733\uc723\uc713\uc703\uc6f3"
+ + "\uc6e3\uc6d3\uc6c3\uc6b3\uc6a3\uc693\uc683\uc673\uc663\uc653\uc643"
+ + "\uc633\uc623\uc613\uc603\uc5f3\uc5e3\uc5d3\uc5c3\uc5b3\uc5a3\uc593"
+ + "\uc583\uc573\uc563\uc553\uc543\uc533\uc523\uc513\uc503\uc4f3\uc4e3"
+ + "\uc4d3\uc4c3\uc4b3\uc4a3\uc493\uc483\uc473\uc463\uc453\uc443\uc433"
+ + "\uc423\uc413\uc403\uc3f3\uc3e3\uc3d3\uc3c3\uc3b3\uc3a3\uc393\uc383"
+ + "\uc373\uc363\uc353\uc343\uc333\uc323\uc313\uc303\uc2f3\uc2e3\uc2d3"
+ + "\uc2c3\uc2b3\uc2a3\uc293\uc283\uc273\uc263\uc253\uc243\uc233\uc223"
+ + "\uc213\uc203\uc1f3\uc1e3\uc1d3\uc1c3\uc1b3\uc1a3\uc193\uc183\uc173"
+ + "\uc163\uc153\uc143\uc133\uc123\uc113\uc103\uc0f3\uc0e3\uc0d3\uc0c3"
+ + "\uc0b3\uc0a3\uc093\uc083\uc073\uc063\uc053\uc043\uc033\uc023\uc013"
+ + "\uc003\ubff3\ubfe3\ubfd3\ubfc3\ubfb3\ubfa3\ubf93\ubf83\ubf73\ubf63"
+ + "\ubf53\ubf43\ubf33\ubf23\ubf13\ubf03\ubef3\ubee3\ubed3\ubec3\ubeb3"
+ + "\ubea3\ube93\ube83\ube73\ube63\ube53\ube43\ube33\ube23\ube13\ube03"
+ + "\ubdf3\ubde3\ubdd3\ubdc3\ubdb3\ubda3\ubd93\ubd83\ubd73\ubd63\ubd53"
+ + "\ubd43\ubd33\ubd23\ubd13\ubd03\ubcf3\ubce3\ubcd3\ubcc3\ubcb3\ubca3"
+ + "\ubc93\ubc83\ubc73\ubc63\ubc53\ubc43\ubc33\ubc23\ubc13\ubc03\ubbf3"
+ + "\ubbe3\ubbd3\ubbc3\ubbb3\ubba3\ubb93\ubb83\ubb73\ubb63\ubb53\ubb43"
+ + "\ubb33\ubb23\ubb13\ubb03\ubaf3\ubae3\ubad3\ubac3\ubab3\ubaa3\uba93"
+ + "\uba83\uba73\uba63\uba53\uba43\uba33\uba23\uba13\uba03\ub9f3\ub9e3"
+ + "\ub9d3\ub9c3\ub9b3\ub9a3\ub993\ub983\ub973\ub963\ub953\ub943\ub933"
+ + "\ub923\ub913\ub903\ub8f3\ub8e3\ub8d3\ub8c3\ub8b3\ub8a3\ub893\ub883"
+ + "\ub873\ub863\ub853\ub843\ub833\ub823\ub813\ub803\ub7f3\ub7e3\ub7d3"
+ + "\ub7c3\ub7b3\ub7a3\ub793\ub783\ub773\ub763\ub753\ub743\ub733\ub723"
+ + "\ub713\ub703\ub6f3\ub6e3\ub6d3\ub6c3\ub6b3\ub6a3\ub693\ub683\ub673"
+ + "\ubc35\ubd04\ubcf4\ubce4\ubcd4\ub613\ub603\ub5f3\ub5e3\ub5d3\ub5c3"
+ + "\ub5b3\ub5a3\ub593\ub583\ub573\ub563\ub553\ub543\ub533\ub523\ub513"
+ + "\ub503\ub4f3\ub4e3\ub4d3\ub4c3\ub4b3\ub4a3\ub493\ub483\ub473\ub463"
+ + "\ub453\ub443\ub433\ub423\ub413\ub403\ub3f3\ub3e3\ub3d3\ub3c3\ub3b3"
+ + "\ub3a3\ub393\ub383\ub373\ub363\ub353\ub343\ub333\ub323\ub313\ub303"
+ + "\ub2f3\ub2e3\ub2d3\ub2c3\ub2b3\ub2a3\ub293\ub283\ub273\ub263\ub253"
+ + "\ub243\ub233\ub223\ub213\ub203\ub1f3\ub1e3\ub1d3\ub1c3\ub1b3\ub1a3"
+ + "\ub193\ub183\ub173\ub163\ub153\ub143\ub133\ub123\ub113\ub103\ub0f3"
+ + "\ub0e3\ub0d3\ub0c3\ub0b3\ub0a3\ub093\ub083\ub073\ub063\ub053\ub043"
+ + "\ub033\ub023\ub013\ub003\uaff3\uafe3\uafd3\uafc3\uafb3\uafa3\uaf93"
+ + "\uaf83\uaf73\uaf63\uaf53\uaf43\uaf33\uaf23\uaf13\uaf03\uaef3\uaee3"
+ + "\uaed3\uaec3\uaeb3\uaea3\uae93\uae83\uae73\uae63\uae53\uae43\uae33"
+ + "\uae23\uae13\uae03\uadf3\uade3\uadd3\uadc3\uadb3\uada3\uad93\uad83"
+ + "\uad73\uad63\uad53\uad43\uad33\uad23\uad13\uad03\uacf3\uace3\uacd3"
+ + "\uacc3\uacb3\uaca3\uac93\uac83\uac73\uac63\uac53\uac43\uac33\uac23"
+ + "\uac13\uac03\uabf3\uabe3\uabd3\uabc3\uabb3\uaba3\uab93\uab83\uab73"
+ + "\uab63\uab53\uab43\uab33\uab23\uab13\uab03\uaaf3\uaae3\uaad3\uaac3"
+ + "\uaab3\uaaa3\uaa93\uaa83\uaa73\uaa63\uaa53\uaa43\uaa33\uaa23\uaa13"
+ + "\uaa03\ua9f3\ua9e3\ua9d3\ua9c3\ua9b3\ua9a3\ua993\ua983\ua973\ua963"
+ + "\ua953\ua943\ua933\ua923\ua913\ua903\ua8f3\ua8e3\ua8d3\ua8c3\ua8b3"
+ + "\ua8a3\ua893\ua883\ua873\ua863\ua853\ua843\ua833\ua823\ua813\ua803"
+ + "\ua7f3\ua7e3\ua7d3\ua7c3\ua7b3\ua7a3\ua793\ua783\ua773\ua763\ua753"
+ + "\ua743\ua733\ua723\ua713\ua703\ua6f3\ua6e3\ua6d3\ua6c3\ua6b3\ua6a3"
+ + "\ua693\ua683\ua673\ua663\ua653\ua643\ua633\ua623\ua613\ua603\ua5f3"
+ + "\ua5e3\ua5d3\ua5c3\ua5b3\ua5a3\ua593\ua583\ua573\ua563\ua553\ua543"
+ + "\ua533\ua523\ua513\ua503\ua4f3\ua4e3\ua4d3\ua4c3\ua4b3\ua4a3\ua493"
+ + "\ua483\ua473\ua463\ua453\ua443\ua433\ua423\ua413\ua403\ua3f3\ua3e3"
+ + "\ua3d3\ua3c3\ua3b3\ua3a3\ua393\ua383\ua373\ua363\ua353\ua343\ua333"
+ + "\ua323\ua313\ua303\ua2f3\ua2e3\ua2d3\ua2c3\ua2b3\ua2a3\ua293\ua283"
+ + "\ua273\ua263\ua253\ua243\ua233\ua223\ua213\ua203\ua1f3\ua1e3\ua1d3"
+ + "\ua1c3\ua1b3\ua1a3\ua193\ua183\ua173\ua163\ua153\ua143\ua133\ua123"
+ + "\ua113\ua103\ua0f3\ua0e3\ua0d3\ua0c3\ua0b3\ua0a3\ua093\ua083\ua073"
+ + "\ua063\ua053\ua043\ua033\ua023\ua013\ua003\u9ff3\u9fe3\u9fd3\u9fc3"
+ + "\u9fb3\u9fa3\u9f93\u9f83\u9f73\u9f63\u9f53\u9f43\u9f33\u9f23\u9f13"
+ + "\u9f03\u9ef3\u9ee3\u9ed3\u9ec3\u9eb3\u9ea3\u9e93\u9e83\u9e73\u9e63"
+ + "\u9e53\u9e43\u9e33\u9e23\u9e13\u9e03\u9df3\u9de3\u9dd3\u9dc3\u9db3"
+ + "\u9da3\u9d93\u9d83\u9d73\u9d63\u9d53\u9d43\u9d33\u9d23\u9d13\u9d03"
+ + "\u9cf3\u9ce3\u9cd3\u9cc3\u9cb3\u9ca3\u9c93\u9c83\u9c73\u9c63\u9c53"
+ + "\u9c43\u9c33\u9c23\u9c13\u9c03\u9bf3\u9be3\u9bd3\u9bc3\u9bb3\u9ba3"
+ + "\u9b93\u9b83\u9b73\u9b63\u9b53\u9b43\u9b33\u9b23\u9b13\u9b03\u9af3"
+ + "\u9ae3\u9ad3\u9ac3\u9ab3\u9aa3\u9a93\u9a83\u9a73\u9a63\u9a53\u9a43"
+ + "\u9a33\u9a23\u9a13\u9a03\u99f3\u99e3\u99d3\u99c3\u99b3\u99a3\u9993"
+ + "\u9983\u9973\u9963\u9953\u9943\u9933\u9923\u9913\u9903\u98f3\u98e3"
+ + "\u98d3\u98c3\u98b3\u98a3\u9893\u9883\u9873\u9863\u9853\u9843\u9833"
+ + "\u9823\u9813\u9803\u97f3\u97e3\u97d3\u97c3\u97b3\u97a3\u9793\u9783"
+ + "\u9773\u9763\u9753\u9743\u9733\u9723\u9713\u9703\u96f3\u96e3\u96d3"
+ + "\u96c3\u96b3\u96a3\u9693\u9683\u9673\u9663\u9653\u9643\u9633\u9623"
+ + "\u9613\u9603\u95f3\u95e3\u95d3\u95c3\u95b3\u95a3\u9593\u9583\u9573"
+ + "\u9563\u9553\u9543\u9533\u9523\u9513\u9503\u94f3\u94e3\u94d3\u94c3"
+ + "\u94b3\u94a3\u9493\u9483\u9473\u9463\u9453\u9443\u9433\u9423\u9413"
+ + "\u9403\u93f3\u93e3\u93d3\u93c3\u93b3\u93a3\u9393\u9383\u9373\u9363"
+ + "\u9353\u9343\u9333\u9323\u9313\u9303\u92f3\u92e3\u92d3\u92c3\u92b3"
+ + "\u92a3\u9293\u9283\u9273\u9263\u9253\u9243\u9233\u9223\u9213\u9203"
+ + "\u91f3\u91e3\u91d3\u91c3\u91b3\u91a3\u9193\u9183\u9173\u9163\u9153"
+ + "\u9143\u9133\u9123\u9113\u9103\u90f3\u90e3\u90d3\u90c3\u90b3\u90a3"
+ + "\u9093\u9083\u9073\u9063\u9053\u9043\u9033\u9023\u9013\u9003\u8ff3"
+ + "\u8fe3\u8fd3\u8fc3\u8fb3\u8fa3\u8f93\u8f83\u8f73\u8f63\u8f53\u8f43"
+ + "\u8f33\u8f23\u8f13\u8f03\u8ef3\u8ee3\u8ed3\u8ec3\u8eb3\u8ea3\u8e93"
+ + "\u8e83\u8e73\u8e63\u8e53\u8e43\u8e33\u8e23\u8e13\u8e03\u8df3\u8de3"
+ + "\u8dd3\u8dc3\u8db3\u8da3\u8d93\u8d83\u8d73\u8d63\u8d53\u8d43\u8d33"
+ + "\u8d23\u8d13\u8d03\u8cf3\u8ce3\u8cd3\u8cc3\u8cb3\u8ca3\u8c93\u8c83"
+ + "\u8c73\u8c63\u8c53\u8c43\u8c33\u8c23\u8c13\u8c03\u8bf3\u8be3\u8bd3"
+ + "\u8bc3\u8bb3\u8ba3\u8b93\u8b83\u8b73\u8b63\u8b53\u8b43\u8b33\u8b23"
+ + "\u8b13\u8b03\u8af3\u8ae3\u8ad3\u8ac3\u8ab3\u8aa3\u8a93\u8a83\u8a73"
+ + "\u8a63\u8a53\u8a43\u8a33\u8a23\u8a13\u8a03\u89f3\u89e3\u89d3\u89c3"
+ + "\u89b3\u89a3\u8993\u8983\u8973\u8963\u8953\u8943\u8933\u8923\u8913"
+ + "\u8903\u88f3\u88e3\u88d3\u88c3\u88b3\u88a3\u8893\u8883\u8873\u8863"
+ + "\u8853\u8843\u8833\u8823\u8813\u8803\u87f3\u87e3\u87d3\u87c3\u87b3"
+ + "\u87a3\u8793\u8783\u8773\u8763\u8753\u8743\u8733\u8723\u8713\u8703"
+ + "\u86f3\u86e3\u86d3\u86c3\u86b3\u86a3\u8693\u8683\u8673\u8663\u8653"
+ + "\u8643\u8633\u8623\u8613\u8603\u85f3\u85e3\u85d3\u85c3\u85b3\u85a3"
+ + "\u8593\u8583\u8573\u8563\u8553\u8543\u8533\u8523\u8513\u8503\u84f3"
+ + "\u84e3\u84d3\u84c3\u84b3\u84a3\u8493\u8483\u8473\u8463\u8453\u8443"
+ + "\u8433\u8423\u8413\u8403\u83f3\u83e3\u83d3\u83c3\u83b3\u83a3\u8393"
+ + "\u8383\u8373\u8363\u8353\u8343\u8333\u8323\u8313\u8303\u82f3\u82e3"
+ + "\u82d3\u82c3\u82b3\u82a3\u8293\u8283\u8273\u8263\u8253\u8243\u8233"
+ + "\u8223\u8213\u8203\u81f3\u81e3\u81d3\u81c3\u81b3\u81a3\u8193\u8183"
+ + "\u8173\u8163\u8153\u8143\u8133\u8123\u8113\u8103\u80f3\u80e3\u80d3"
+ + "\u80c3\u80b3\u80a3\u8093\u8083\u8073\u8063\u8053\u8043\u8033\u8023"
+ + "\u8013\u8003\u7ff3\u7fe3\u7fd3\u7fc3\u7fb3\u7fa3\u7f93\u7f83\u7f73"
+ + "\u7f63\u7f53\u7f43\u7f33\u7f23\u7f13\u7f03\u7ef3\u7ee3\u7ed3\u7ec3"
+ + "\u7eb3\u7ea3\u7e93\u7e83\u7e73\u7e63\u7e53\u7e43\u7e33\u7e23\u7e13"
+ + "\u7e03\u7df3\u7de3\u7dd3\u7dc3\u7db3\u7da3\u7d93\u7d83\u7d73\u7d63"
+ + "\u7d53\u7d43\u7d33\u7d23\u7d13\u7d03\u7cf3\u7ce3\u7cd3\u7cc3\u7cb3"
+ + "\u7ca3\u7c93\u7c83\u7c73\u7c63\u7c53\u7c43\u7c33\u7c23\u7c13\u7c03"
+ + "\u7bf3\u7be3\u7bd3\u7bc3\u7bb3\u7ba3\u7b93\u7b83\u7b73\u7b63\u7b53"
+ + "\u7b43\u7b33\u7b23\u7b13\u7b03\u7af3\u7ae3\u7ad3\u7ac3\u7ab3\u7aa3"
+ + "\u7a93\u7a83\u7a73\u7a63\u7a53\u7a43\u7a33\u7a23\u7a13\u7a03\u79f3"
+ + "\u79e3\u79d3\u79c3\u79b3\u79a3\u7993\u7983\u7973\u7963\u7953\u7943"
+ + "\u7933\u7923\u7913\u7903\u78f3\u78e3\u78d3\u78c3\u78b3\u78a3\u7893"
+ + "\u7883\u7873\u7863\u7853\u7843\u7833\u7823\u7813\u7803\u77f3\u77e3"
+ + "\u77d3\u77c3\u77b3\u77a3\u7793\u7783\u7773\u7763\u7753\u7743\u7733"
+ + "\u7723\u7713\u7703\u76f3\u76e3\u76d3\u76c3\u76b3\u76a3\u7693\u7683"
+ + "\u7673\u7663\u7653\u7643\u7633\u7623\u7613\u7603\u75f3\u75e3\u75d3"
+ + "\u75c3\u75b3\u75a3\u7593\u7583\u7573\u7563\u7553\u7543\u7533\u7523"
+ + "\u7513\u7503\u74f3\u74e3\u74d3\u74c3\u74b3\u74a3\u7493\u7483\u7473"
+ + "\u7463\u7453\u7443\u7433\u7423\u7413\u7403\u73f3\u73e3\u73d3\u73c3"
+ + "\u73b3\u73a3\u7393\u7383\u7373\u7363\u7353\u7343\u7333\u7323\u7313"
+ + "\u7303\u72f3\u72e3\u72d3\u72c3\u72b3\u72a3\u7293\u7283\u7273\u7263"
+ + "\u7253\u7243\u7233\u7223\u7213\u7203\u71f3\u71e3\u71d3\u71c3\u71b3"
+ + "\u71a3\u7193\u7183\u7173\u7163\u7153\u7143\u7133\u7123\u7113\u7103"
+ + "\u70f3\u70e3\u70d3\u70c3\u70b3\u70a3\u7093\u7083\u7073\u7063\u7053"
+ + "\u7043\u7033\u7023\u7013\u7003\u6ff3\u6fe3\u6fd3\u6fc3\u6fb3\u6fa3"
+ + "\u6f93\u6f83\u6f73\u6f63\u6f53\u6f43\u6f33\u6f23\u6f13\u6f03\u6ef3"
+ + "\u6ee3\u6ed3\u6ec3\u6eb3\u6ea3\u6e93\u6e83\u6e73\u6e63\u6e53\u6e43"
+ + "\u6e33\u6e23\u6e13\u6e03\u6df3\u6de3\u6dd3\u6dc3\u6db3\u6da3\u6d93"
+ + "\u6d83\u6d73\u6d63\u6d53\u6d43\u6d33\u6d23\u6d13\u6d03\u6cf3\u6ce3"
+ + "\u6cd3\u6cc3\u6cb3\u6ca3\u6c93\u6c83\u6c73\u6c63\u6c53\u6c43\u6c33"
+ + "\u6c23\u6c13\u6c03\u6bf3\u6be3\u6bd3\u6bc3\u6bb3\u6ba3\u6b93\u6b83"
+ + "\u6b73\u6b63\u6b53\u6b43\u6b33\u6b23\u6b13\u6b03\u6af3\u6ae3\u6ad3"
+ + "\u6ac3\u6ab3\u6aa3\u6a93\u6a83\u6a73\u6a63\u6a53\u6a43\u6a33\u6a23"
+ + "\u6a13\u6a03\u69f3\u69e3\u69d3\u69c3\u69b3\u69a3\u6993\u6983\u6973"
+ + "\u6963\u6953\u6943\u6933\u6923\u6913\u6903\u68f3\u68e3\u68d3\u68c3"
+ + "\u68b3\u68a3\u6893\u6883\u6873\u6863\u6853\u6843\u6833\u6823\u6813"
+ + "\u6803\u67f3\u67e3\u67d3\u67c3\u67b3\u67a3\u6793\u6783\u6773\u6763"
+ + "\u6753\u6743\u6733\u6723\u6713\u6703\u66f3\u66e3\u66d3\u66c3\u66b3"
+ + "\u66a3\u6693\u6683\u6673\u6663\u6653\u6643\u6633\u6623\u6613\u6603"
+ + "\u65f3\u65e3\u65d3\u65c3\u65b3\u65a3\u6593\u6583\u6573\u6563\u6553"
+ + "\u6543\u6533\u6523\u6513\u6503\u64f3\u64e3\u64d3\u64c3\u64b3\u64a3"
+ + "\u6493\u6483\u6a45\u636c\u635c\u634c\u633c\u632c\u6413\u6403\u63f3"
+ + "\u63e3\u63d3\u63c3\u63b3\u63a3\u6393\u6383\u6373\u6363\u6353\u6343"
+ + "\u6333\u6323\u6313\u6303\u62f3\u62e3\u62d3\u62c3\u62b3\u62a3\u6293"
+ + "\u6283\u6273\u6263\u6253\u6243\u6233\u6223\u6213\u6203\u61f3\u61e3"
+ + "\u61d3\u61c3\u61b3\u61a3\u6193\u6183\u6173\u6163\u6153\u6143\u6133"
+ + "\u6123\u6113\u6103\u60f3\u60e3\u60d3\u60c3\u60b3\u60a3\u6093\u6083"
+ + "\u6073\u6063\u6053\u6043\u6033\u6023\u6013\u6003\u5ff3\u5fe3\u5fd3"
+ + "\u5fc3\u5fb3\u5fa3\u6379\u6634\u6624\u6614\u6933\u5e4c\u5e3c\u5e2c"
+ + "\u5e1c\u5e0c\u5dfc\u5dec\u5ddc\u5dcc\u5dbc\u5dac\u5d9c\u5d8c\u5d7c"
+ + "\u5d6c\u5d5c\u5d4c\u5d3c\u5d2c\u5d1c\u5d0c\u5cfc\u5cec\u5cdc\u5ccc"
+ + "\u5cbc\u5cac\u5c9c\u5c8c\u5c7c\u5c6c\u5c5c\u5c4c\u5c3c\u5c2c\u5c1c"
+ + "\u5c0c\u5bfc\u5bec\u5bdc\u5bcc\u5bbc\u5bac\u5b9c\u5b8c\u5b7c\u5b6c"
+ + "\u5b5c\u5b4c\u5b3c\u5b2c\u5b1c\u5b0c\u5afc\u5aec\u5adc\u5acc\u5abc"
+ + "\u5aac\u5a9c\u5a8c\u5a7c\u5a6c\u5a5c\u5a4c\u5a3c\u5a2c\u5a1c\u5a0c"
+ + "\u59fc\u59ec\u59dc\u59cc\u59bc\u59ac\u599c\u598c\u597c\u596c\u595c"
+ + "\u594c\u593c\u592c\u591c\u590c\u58fc\u58ec\u58dc\u58cc\u58bc\u58ac"
+ + "\u589c\u588c\u587c\u586c\u585c\u584c\u583c\u582c\u581c\u580c\u57fc"
+ + "\u57ec\u57dc\u57cc\u57bc\u57ac\u579c\u578c\u577c\u576c\u575c\u574c"
+ + "\u573c\u572c\u5813\u5803\u57f3\u57e3\u57d3\u57c3\u57b3\u57a3\u5793"
+ + "\u5783\u5773\u5763\u5753\u5743\u5733\u5723\u5713\u5703\u56f3\u56e3"
+ + "\u56d3\u56c3\u56b3\u56a3\u5693\u5683\u5673\u5663\u5653\u5643\u5633"
+ + "\u5623\u5613\u5603\u55f3\u55e3\u55d3\u55c3\u55b3\u55a3\u5593\u5583"
+ + "\u5573\u5563\u5553\u5543\u5533\u5523\u5513\u5503\u54f3\u54e3\u54d3"
+ + "\u54c3\u54b3\u54a3\u5493\u5483\u5473\u5463\u5453\u5443\u5433\u5423"
+ + "\u5413\u5403\u53f3\u53e3\u53d3\u53c3\u53b3\u53a3\u5393\u5383\u5373"
+ + "\u5363\u5353\u5343\u5333\u5323\u5313\u5303\u52f3\u52e3\u52d3\u52c3"
+ + "\u52b3\u52a3\u5293\u5283\u5273\u5263\u5253\u5243\u5233\u5223\u5213"
+ + "\u5203\u51f3\u51e3\u51d3\u51c3\u51b3\u51a3\u5193\u5183\u5173\u5163"
+ + "\u5153\u5143\u5133\u5123\u5113\u5103\u50f3\u50e3\u50d3\u50c3\u50b3"
+ + "\u50a3\u5093\u5083\u5073\u5063\u5053\u5043\u5033\u5023\u5013\u5003"
+ + "\u4ff3\u4fe3\u4fd3\u4fc3\u4fb3\u4fa3\u4f93\u4f83\u4f73\u4f63\u4f53"
+ + "\u4f43\u4f33\u4f23\u4f13\u4f03\u4ef3\u4ee3\u4ed3\u4ec3\u4eb3\u4ea3"
+ + "\u4e93\u4e83\u4e73\u4e63\u4e53\u4e43\u4e33\u4e23\u4e13\u4e03\u4df3"
+ + "\u4de3\u4dd3\u4dc3\u4db3\u4da3\u4d93\u4d83\u4d73\u4d63\u4d53\u4d43"
+ + "\u4d33\u4d23\u4d13\u4d03\u4cf3\u4ce3\u4cd3\u4cc3\u4cb3\u4ca3\u4c93"
+ + "\u4c83\u4c73\u4c63\u4c53\u4c43\u4c33\u4c23\u4c13\u4c03\u4bf3\u4be3"
+ + "\u4bd3\u4bc3\u4bb3\u4ba3\u4b93\u4b83\u4b73\u4b63\u4b53\u4b43\u4b33"
+ + "\u4b23\u4b13\u4b03\u4af3\u4ae3\u4ad3\u4ac3\u4ab3\u4aa3\u4a93\u4a83"
+ + "\u4a73\u4a63\u4a53\u4a43\u4a33\u4a23\u4a13\u4a03\u49f3\u49e3\u49d3"
+ + "\u49c3\u49b3\u49a3\u4993\u4983\u4973\u4963\u4953\u4943\u4933\u4923"
+ + "\u4913\u4903\u48f3\u48e3\u48d3\u48c3\u48b3\u48a3\u4893\u4883\u4873"
+ + "\u4863\u4853\u4843\u4833\u4823\u4813\u4803\u47f3\u47e3\u47d3\u47c3"
+ + "\u47b3\u47a3\u4793\u4783\u4773\u4763\u4753\u4743\u4733\u4723\u4713"
+ + "\u4703\u46f3\u46e3\u46d3\u46c3\u46b3\u46a3\u4693\u4683\u4673\u4663"
+ + "\u4653\u4643\u4633\u4623\u4613\u4603\u45f3\u45e3\u45d3\u45c3\u45b3"
+ + "\u45a3\u4593\u4583\u4573\u4563\u4553\u4543\u4533\u4523\u4513\u4503"
+ + "\u44f3\u44e3\u44d3\u44c3\u44b3\u44a3\u4493\u4483\u4473\u4463\u4453"
+ + "\u4443\u4433\u4423\u4413\u4403\u43f3\u43e3\u43d3\u43c3\u43b3\u43a3"
+ + "\u4393\u4383\u4373\u4363\u4353\u4343\u4333\u4323\u4313\u4303\u42f3"
+ + "\u42e3\u42d3\u42c3\u42b3\u42a3\u4293\u4283\u4273\u4263\u4253\u4243"
+ + "\u4233\u4223\u4213\u4203\u41f3\u41e3\u41d3\u41c3\u41b3\u41a3\u4193"
+ + "\u4183\u4173\u4163\u4153\u4143\u4133\u4123\u4113\u4103\u40f3\u40e3"
+ + "\u40d3\u40c3\u40b3\u40a3\u4093\u4083\u4073\u4063\u4053\u4043\u4033"
+ + "\u4023\u4013\u4003\u3ff3\u3fe3\u3fd3\u3fc3\u3fb3\u3fa3\u3f93\u3f83"
+ + "\u3f73\u3f63\u3f53\u3f43\u3f33\u3f23\u3f13\u3f03\u3ef3\u3ee3\u3ed3"
+ + "\u3ec3\u3eb3\u3ea3\u3e93\u3e83\u3e73\u3e63\u3e53\u3e43\u3e33\u3e23"
+ + "\u3e13\u3e03\u3df3\u3de3\u3dd3\u3dc3\u3db3\u3da3\u3d93\u3d83\u3d73"
+ + "\u3d63\u3d53\u3d43\u3d33\u3d23\u3d13\u3d03\u3cf3\u3ce3\u3cd3\u3cc3"
+ + "\u3cb3\u3ca3\u3c93\u3c83\u3c73\u3c63\u3c53\u3c43\u3c33\u3c23\u3c13"
+ + "\u3c03\u3bf3\u3be3\u3bd3\u3bc3\u3bb3\u3ba3\u3b93\u3b83\u3b73\u3b63"
+ + "\u3b53\u3b43\u3b33\u3b23\u3b13\u3b03\u3af3\u3ae3\u3ad3\u3ac3\u3ab3"
+ + "\u3aa3\u3a93\u3a83\u3a73\u3a63\u3a53\u3a43\u3a33\u3a23\u3a13\u3a03"
+ + "\u39f3\u39e3\u39d3\u39c3\u39b3\u39a3\u3993\u3983\u3973\u3963\u3953"
+ + "\u3943\u3933\u3923\u3913\u3903\u38f3\u38e3\u38d3\u38c3\u38b3\u38a3"
+ + "\u3893\u3883\u3873\u3863\u3853\u3843\u3833\u3823\u3813\u3803\u37f3"
+ + "\u37e3\u37d3\u37c3\u37b3\u37a3\u3793\u3783\u3773\u3763\u3753\u3743"
+ + "\u3733\u3723\u3713\u3703\u36f3\u36e3\u36d3\u36c3\u36b3\u36a3\u3693"
+ + "\u3683\u3673\u3663\u3653\u3643\u3633\u3623\u3613\u3603\u35f3\u35e3"
+ + "\u35d3\u35c3\u35b3\u35a3\u3593\u3583\u3573\u3563\u3553\u3543\u3533"
+ + "\u3523\u3513\u3503\u34f3\u34e3\u34d3\u34c3\u34b3\u34a3\u3493\u3483"
+ + "\u3473\u3463\u3453\u3443\u3433\u3423\u3413\u3403\u33f3\u33e3\u33d3"
+ + "\u33c3\u33b3\u33a3\u3393\u3383\u3373\u3363\u3353\u3343\u3333\u3323"
+ + "\u3313\u3303\u32f3\u32e3\u32d3\u32c3\u32b3\u32a3\u3293\u3283\u3273"
+ + "\u3263\u3253\u3243\u3233\u3223\u3213\u3203\u31f3\u31e3\u31d3\u31c3"
+ + "\u31b3\u31a3\u3193\u3183\u3173\u3163\u3153\u3143\u3133\u3123\u3113"
+ + "\u3103\u30f3\u30e3\u30d3\u30c3\u30b3\u30a3\u3093\u3083\u3073\u3063"
+ + "\u3053\u3043\u3033\u3023\u3013\u3003\u2ff3\u2fe3\u2fd3\u2fc3\u2fb3"
+ + "\u2fa3\u2f93\u2f83\u2f73\u2f63\u2f53\u2f43\u2f33\u2f23\u2f13\u2f03"
+ + "\u2ef3\u2ee3\u2ed3\u2ec3\u2eb3\u2ea3\u2e93\u2e83\u2e73\u2e63\u2e53"
+ + "\u2e43\u2e33\u2e23\u2e13\u2e03\u2df3\u2de3\u2dd3\u2dc3\u2db3\u2da3"
+ + "\u2d93\u2d83\u2d73\u2d63\u2d53\u2d43\u2d33\u2d23\u2d13\u2d03\u2cf3"
+ + "\u2ce3\u2cd3\u2cc3\u2cb3\u2ca3\u2c93\u2c83\u3247\u2b6c\u2b5c\u2b4c"
+ + "\u2b3c\u2b2c\u36e2\u36d2\u36c2\u36b2\u36a2\u3692\u3682\u3672\u3662"
+ + "\u3652\u3642\u3632\u3622\u3612\u3602\u35f2\u35e2\u35d2\u35c2\u35b2"
+ + "\u35a2\u3592\u3582\u3572\u3562\u3552\u3542\u3532\u3522\u3512\u3502"
+ + "\u34f2\u34e2\u34d2\u34c2\u34b2\u34a2\u3492\u3482\u3472\u3462\u3452"
+ + "\u3442\u3432\u3422\u3412\u3402\u33f2\u33e2\u33d2\u33c2\u33b2\u33a2"
+ + "\u3392\u3382\u3372\u3362\u3352\u3342\u3332\u3322\u3312\u3302\u32f2"
+ + "\u32e2\u32d2\u32c2\u32b2\u32a2\u3292\u3282\u3272\u3262\u3252\u3242"
+ + "\u3232\u3222\u3212\u3202\u31f2\u31e2\u31d2\u31c2\u31b2\u31a2\u3192"
+ + "\u3182\u3172\u3162\u3152\u3142\u3132\u3122\u3112\u3102\u30f2\u30e2"
+ + "\u30d2\u30c2\u30b2\u30a2\u3092\u3082\u3072\u3062\u3052\u3042\u3032"
+ + "\u3022\u3012\u3002\u2ff2\u2fe2\u2fd2\u2fc2\u2fb2\u2fa2\u2f92\u2f82"
+ + "\u2f72\u2f62\u2f52\u2f42\u2f32\u2f22\u2f12\u2f02\u2ef2\u2ef2\u2ee2"
+ + "\u2ed2\u2ec2\u2eb2\u2ea2\u2e92\u2e82\u2e72\u2e62\u2e52\u2e42\u2e32"
+ + "\u2e22\u2e12\u2e02\u2df2\u2de2\u2dd2\u2dc2\u2db2\u2da2\u2d92\u2d82"
+ + "\u2d72\u2d62\u2d52\u2d42\u2d32\u2d22\u2d12\u2d02\u2cf2\u2ce2\u2cd2"
+ + "\u2cc2\u2cb2\u2ca2\u2c92\u2c82\u2c72\u2c62\u2c52\u2c42\u2c32\u2c22"
+ + "\u2c12\u2c02\u2bf2\u2be2\u2bd2\u2bc2\u2bb2\u2ba2\u2b92\u2b82\u2b72"
+ + "\u2b62\u2b52\u2b42\u2b32\u2b22\u2b12\u2b02\u2af2\u2ae2\u2ad2\u2ac2"
+ + "\u2ab2\u2aa2\u2a92\u2a82\u2a72\u2a62\u2a52\u2a42\u2a32\u2a22\u2a12"
+ + "\u2a02\u29f2\u29e2\u29d2\u29c2\u29b2\u29a2\u2992\u2982\u2972\u2962"
+ + "\u2952\u2942\u2932\u2922\u2912\u2902\u28f2\u28e2\u28d2\u28c2\u28b2"
+ + "\u28a2\u2892\u2882\u2872\u2862\u2852\u2842\u2832\u2822\u2812\u2802"
+ + "\u27f2\u27e2\u27d2\u27c2\u27b2\u27a2\u2792\u2782\u2772\u2762\u2752"
+ + "\u2742\u2732\u2722\u2712\u2702\u26f2\u26e2\u26d2\u26c2\u26b2\u26a2"
+ + "\u2692\u2682\u2672\u2662\u2652\u2642\u2632\u2622\u2612\u2602\u25f2"
+ + "\u25e2\u25d2\u25c2\u25b2\u25a2\u2592\u2582\u2572\u2562\u2552\u2542"
+ + "\u2532\u2522\u2512\u2502\u24f2\u24e2\u24d2\u24c2\u24b2\u24a2\u2492"
+ + "\u2482\u2472\u2462\u2452\u2442\u2432\u2422\u2412\u2402\u23f2\u23e2"
+ + "\u23d2\u23c2\u23b2\u23a2\u2392\u2382\u2372\u2362\u2352\u2342\u2332"
+ + "\u2322\u2312\u2302\u22f2\u22e2\u22d2\u22c2\u22b2\u22a2\u2292\u2282"
+ + "\u2272\u2262\u2252\u2242\u2232\u2222\u2212\u2202\u21f2\u21e2\u21d2"
+ + "\u21c2\u21b2\u21a2\u2192\u2182\u2172\u2162\u2152\u2142\u2132\u2122"
+ + "\u2112\u2102\u20f2\u20e2\u20d2\u20c2\u20b2\u20a2\u2092\u2082\u2072"
+ + "\u2062\u2052\u2042\u2032\u2022\u2012\u2002\u1ff2\u1fe2\u1fd2\u1fc2"
+ + "\u1fb2\u1fa2\u1f92\u1f82\u1f72\u1f62\u1f52\u1f42\u1f32\u1f22\u1f12"
+ + "\u1f02\u1ef2\u1ee2\u1ed2\u1ec2\u1eb2\u1ea2\u1e92\u1e82\u1e72\u1e62"
+ + "\u1e52\u1e42\u1e32\u1e22\u1e12\u1e02\u1df2\u1de2\u1dd2\u1dc2\u1db2"
+ + "\u1da2\u1d92\u1d82\u1d72\u1d62\u1d52\u1d42\u1d32\u1d22\u1d12\u1d02"
+ + "\u1cf2\u1ce2\u1cd2\u1cc2\u1cb2\u1ca2\u1c92\u1c82\u1c72\u1c62\u1c52"
+ + "\u1c42\u1c32\u1c22\u1c12\u1c02\u1bf2\u1be2\u1bd2\u1bc2\u1bb2\u1ba2"
+ + "\u1b92\u1b82\u1b72\u1b62\u1b52\u1b42\u1b32\u1b22\u1b12\u1b02\u1af2"
+ + "\u1ae2\u1ad2\u1ac2\u1ab2\u1aa2\u1a92\u1a82\u1a72\u1a62\u1a52\u1a42"
+ + "\u1a32\u1a22\u1a12\u1a02\u19f2\u19e2\u19d2\u19c2\u19b2\u19a2\u1992"
+ + "\u1982\u1972\u1962\u1952\u1942\u1932\u1922\u1912\u1902\u18f2\u18e2"
+ + "\u18d2\u18c2\u18b2\u18a2\u1892\u1882\u1872\u1862\u1852\u1842\u1832"
+ + "\u1822\u1812\u1802\u17f2\u17e2\u17d2\u17c2\u17b2\u17a2\u1792\u1782"
+ + "\u1772\u1762\u1752\u1742\u1732\u1722\u1712\u1702\u16f2\u16e2\u16d2"
+ + "\u16c2\u16b2\u16a2\u1692\u1682\u1672\u1662\u1652\u1642\u1632\u1622"
+ + "\u1612\u1602\u0b13\u0b03\u0af3\u0ae3\u0ad3\u0ac3\u0ab3\u0aa3\u0a93"
+ + "\u0a83\u0a73\u0a63\u0a53\u0a43\u0a33\u0a23\u0a13\u0a03\u0dd8\u09e3"
+ + "\u09d3\u09c3\u0d9b\u08ac\u089c\u088c\u087c\u086c\u085c\u084c\u083c"
+ + "\u082c\u1402\u0b35\u13f2\u13ec\u0b14\u083f\u082f\u081f\u080f\u07ff"
+ + "\u07ef\u0b82\u075c\u07bc\u07af\u079f\u078f\u077f\u076f\u075f\u074f"
+ + "\u073f\u072f\u071f\u070f\u06ff\u06ef\u06df\u06cf\u06bf\u06af\u069f"
+ + "\u068f\u067f\u066f\u0661\u05dc\u063f\u062f\u061f\u060f\u05fd\u05ef"
+ + "\u05df\u096c\u054c\u053c\u09a9\u0666\u050c\u0818\u10fc\u10f8\u0e1e"
+ + "\u10e8\u08b3\u050f\u04ff\u04ef\u04df\u04cf\u04bf\u04af\u087c\u0795"
+ + "\u0127\u0154\u0154\u017a\u1008\u0859\u08ad\u0493\u0485\u0473\u0453"
+ + "\u01c3\u038b\u0f88\u0333",
+
+ "\000\uffff?\004\004\u00fd\u00bd}=\ufffd\uffbd"
+ + "\uff7d\uff7d\ufef2\uff2d\ufe7d\ufc7f\ufc6f\ufe6d\ufd7d\ufd3d\ufcfd"
+ + "\ufcbd\ufc7d\ufc3d\ufbfd\ufbbd\ufb7d\ufb3d\ufafd\ufabd\ufa7d\ufb2d"
+ + "\uf9fd\uf9bd\uf97d\uf93d\uf8fd\uf8bd\uf87d\uf83d\uf7fd\uf7bd\uf77d"
+ + "\uf73d\uf6fd\uf6bd\uf67d\uf63d\uf5fd\uf5bd\uf57d\uf53d\uf4fd\uf4bd"
+ + "\uf47d\uf43d\uf3fd\uf3bd\uf37d\uf33d\uf2fd\uf2bd\uf27d\uf23d\uf1fd"
+ + "\uf1bd\uf17d\uf13d\uf0fd\uf0bd\uf07d\uf03d\ueffd\uefbd\uef7d\uef3d"
+ + "\ueefd\ueebd\uee7d\uee3d\uedfd\uedbd\ued7d\ued3d\uecfd\uecbd\uec7d"
+ + "\uec3d\uebfd\uebbd\ueb7d\ueb3d\ueafd\ueabd\uea7d\uea3d\ue9fd\ue9bd"
+ + "\ue97d\ue93d\ue8fd\ue8bd\ue87d\ue83d\ue7fd\ue7bd\ue77d\ue73d\ue6fd"
+ + "\ue6bd\ue67d\ue63d\ue5fd\ue5bd\ue57d\ue53d\ue4fd\ue4bd\ue47d\ue43d"
+ + "\ue3fd\ue3bd\ue37d\ue33d\ue2fd\ue2bd\ue27d\ue23d\ue1fd\ue1bd\ue17d"
+ + "\ue13d\ue0fd\ue0bd\ue07d\ue03d\udffd\udfbd\udf7d\udf3d\udefd\udebd"
+ + "\ude7d\ude3d\uddfd\uddbd\udd7d\udd3d\udcfd\udcbd\udc7d\udc3d\udbfd"
+ + "\udbbd\udb7d\udb3d\udafd\udabd\uda7d\uda3d\ud9fd\ud9bd\ud97d\ud93d"
+ + "\ud8fd\ud8bd\ud87d\ud83d\ud7fd\ud7bd\ud77d\ud73d\ud6fd\ud6bd\ud67d"
+ + "\ud63d\ud5fd\ud5bd\ud57d\ud53d\ud4fd\ud4bd\ud47d\ud43d\ud3fd\ud3bd"
+ + "\ud37d\ud33d\ud2fd\ud2bd\ud27d\ud23d\ud1fd\ud1bd\ud17d\ud13d\ud0fd"
+ + "\ud0bd\ud07d\ud03d\ucffd\ucfbd\ucf7d\ucf3d\ucefd\ucebd\uce7d\uce3d"
+ + "\ucdfd\ucdbd\ucd7d\ucd3d\uccfd\uccbd\ucc7d\ucc3d\ucbfd\ucbbd\ucb7d"
+ + "\ucb3d\ucafd\ucabd\uca7d\uca3d\uc9fd\uc9bd\uc97d\uc93d\uc8fd\uc8bd"
+ + "\uc87d\uc83d\uc7fd\uc7bd\uc77d\uc73d\uc6fd\uc6bd\uc67d\uc63d\uc5fd"
+ + "\uc5bd\uc57d\uc53d\uc4fd\uc4bd\uc47d\uc43d\uc3fd\uc3bd\uc37d\uc33d"
+ + "\uc2fd\uc2bd\uc27d\uc23d\uc1fd\uc1bd\uc17d\uc13d\uc0fd\uc0bd\uc07d"
+ + "\uc03d\ubffd\ubfbd\ubf7d\ubf3d\ubefd\ubebd\ube7d\ube3d\ubdfd\ubdbd"
+ + "\ubd7d\ubd3d\ubcfd\ubcbd\ubc7d\ubc3d\ubbfd\ubbbd\ubb7d\ubb3d\ubafd"
+ + "\ubabd\uba7d\uba3d\ub9fd\ub9bd\ub97d\ub93d\ub8fd\ub8bd\ub87d\ub83d"
+ + "\ub7fd\ub7bd\ub77d\ub73d\ub6fd\ub6bd\ub67d\ub63d\ub5fd\ub5bd\ub57d"
+ + "\ub53d\ub4fd\ub4bd\ub47d\ub43d\ub3fd\ub3bd\ub37d\ub33d\ub2fd\ub2bd"
+ + "\ub27d\ub23d\ub1fd\ub1bd\ub17d\ub13d\ub0fd\ub0bd\ub07d\ub03d\uaffd"
+ + "\uafbd\uaf7d\uaf3d\uaefd\uaebd\uae7d\uae3d\uadfd\uadbd\uad7d\uad3d"
+ + "\uacfd\uacbd\uac7d\uac3d\uabfd\uabbd\uab7d\uab3d\uaafd\uaabd\uaa7d"
+ + "\uaa3d\ua9fd\ua9bd\ua97d\ua93d\ua8fd\ua8bd\ua87d\ua83d\ua7fd\ua7bd"
+ + "\ua77d\ua73d\ua6fd\ua6bd\ua67d\ua63d\ua5fd\ua5bd\ua57d\ua53d\ua4fd"
+ + "\ua4bd\ua47d\ua43d\ua3fd\ua3bd\ua37d\ua33d\ua2fd\ua2bd\ua27d\ua23d"
+ + "\ua1fd\ua1bd\ua17d\ua13d\ua0fd\ua0bd\ua07d\ua03d\u9ffd\u9fbd\u9f7d"
+ + "\u9f3d\u9efd\u9ebd\u9e7d\u9e3d\u9dfd\u9dbd\u9d7d\u9d3d\u9cfd\u9cbd"
+ + "\u9c7d\u9c3d\u9bfd\u9bbd\u9b7d\u9b3d\u9afd\u9abd\u9a7d\u9a3d\u99fd"
+ + "\u99bd\u997d\u993d\u98fd\u98bd\u987d\u983d\u97fd\u97bd\u977d\u973d"
+ + "\u96fd\u96bd\u967d\u963d\u95fd\u95bd\u957d\u953d\u94fd\u94bd\u947d"
+ + "\u943d\u93fd\u93bd\u937d\u933d\u92fd\u92bd\u927d\u923d\u91fd\u91bd"
+ + "\u917d\u913d\u90fd\u90bd\u907d\u903d\u8ffd\u8fbd\u8f7d\u8f3d\u8efd"
+ + "\u8ebd\u8e7d\u8e3d\u8dfd\u8dbd\u8d7d\u8d3d\u8cfd\u8cbd\u8c7d\u8c3d"
+ + "\u8bfd\u8bbd\u8b7d\u8b3d\u8afd\u8abd\u8a7d\u8a3d\u89fd\u89bd\u897d"
+ + "\u893d\u88fd\u88bd\u887d\u883d\u87fd\u87bd\u877d\u873d\u86fd\u86bd"
+ + "\u867d\u863d\u85fd\u85bd\u857d\u853d\u84fd\u84bd\u847d\u843d\u83fd"
+ + "\u83bd\u837d\u833d\u82fd\u82bd\u827d\u823d\u81fd\u81bd\u817d\u813d"
+ + "\u80fd\u80bd\u807d\u803d\u7ffd\u7fbd\u7f7d\u7f3d\u7efd\u7ebd\u7e7d"
+ + "\u7e3d\u7dfd\u7dbd\u7d7d\u7d3d\u7cfd\u7cbd\u7c7d\u7c3d\u7bfd\u7bbd"
+ + "\u7b7d\u7b3d\u7afd\u7abd\u7a7d\u7a3d\u79fd\u79bd\u797d\u793d\u78fd"
+ + "\u78bd\u787d\u783d\u77fd\u77bd\u777d\u773d\u76fd\u76bd\u767d\u763d"
+ + "\u75fd\u75bd\u757d\u753d\u74fd\u74bd\u747d\u743d\u73fd\u73bd\u737d"
+ + "\u733d\u72fd\u72bd\u727d\u723d\u71fd\u71bd\u717d\u713d\u70fd\u70bd"
+ + "\u707d\u703d\u6ffd\u6fbd\u6f7d\u6f3d\u6efd\u6ebd\u6e7d\u6e3d\u6dfd"
+ + "\u6dbd\u6d7d\u6d3d\u6cfd\u6cbd\u6c7d\u6c3d\u6bfd\u6bbd\u6b7d\u6b3d"
+ + "\u6afd\u6abd\u6a7d\u6a3d\u69fd\u69bd\u697d\u693d\u68fd\u68bd\u687d"
+ + "\u683d\u67fd\u67bd\u677d\u673d\u66fd\u66bd\u667d\u663d\u65fd\u65bd"
+ + "\u657d\u653d\u64fd\u64bd\u647d\u643d\u63fd\u63bd\u637d\u633d\u62fd"
+ + "\u62bd\u627d\u623d\u61fd\u61bd\u617d\u613d\u60fd\u60bd\u607d\u603d"
+ + "\u5ffd\u5fbd\u5f7d\u5f3d\u5efd\u5ebd\u5e7d\u5e3d\u5dfd\u5dbd\u5d7d"
+ + "\u5d3d\u5cfd\u5cbd\u5c7d\u5c3d\u5bfd\u5bbd\u5b7d\u5b3d\u5afd\u5abd"
+ + "\u5a7d\u5a3d\u59fd\u59bd\u597d\u593d\u58fd\u58bd\u587d\u583d\u57fd"
+ + "\u57bd\u577d\u573d\u56fd\u56bd\u567d\u563d\u55fd\u55bd\u557d\u553d"
+ + "\u54fd\u54bd\u547d\u543d\u53fd\u53bd\u537d\u533d\u52fd\u52bd\u527d"
+ + "\u523d\u51fd\u51bd\u517d\u513d\u50fd\u50bd\u507d\u503d\u4ffd\u4fbd"
+ + "\u4f7d\u4f3d\u4efd\u4ebd\u4e7d\u4e3d\u4dfd\u4dbd\u4d7d\u4d3d\u4cfd"
+ + "\u4cbd\u4c7d\u4c3d\u4bfd\u4bbd\u4b7d\u4b3d\u4afd\u4abd\u4a7d\u4a3d"
+ + "\u49fd\u49bd\u497d\u493d\u48fd\u48bd\u487d\u483d\u47fd\u47bd\u477d"
+ + "\u473d\u46fd\u46bd\u467d\u463d\u45fd\u45bd\u457d\u453d\u44fd\u44bd"
+ + "\u447d\u443d\u43fd\u43bd\u437d\u433d\u42fd\u42bd\u427d\u423d\u41fd"
+ + "\u41bd\u417d\u413d\u40fd\u40bd\u407d\u403d\u3ffd\u3fbd\u3f7d\u3f3d"
+ + "\u3efd\u3ebd\u3e7d\u3e3d\u3dfd\u3dbd\u3d7d\u3d3d\u3cfd\u3cbd\u3c7d"
+ + "\u3c3d\u3bfd\u3bbd\u3b7d\u3b3d\u3afd\u3abd\u3a7d\u3a3d\u39fd\u39bd"
+ + "\u397d\u393d\u38fd\u38bd\u387d\u383d\u37fd\u37bd\u377d\u373d\u36fd"
+ + "\u36bd\u367d\u363d\u35fd\u35bd\u357d\u353d\u34fd\u34bd\u347d\u343d"
+ + "\u33fd\u33bd\u337d\u333d\u32fd\u32bd\u327d\u31d0\u3190\u3150\u311a"
+ + "\u30a6\u2ffb\u2ff8\u3032\u303d\u2ffd\u2fbd\u2f7d\u306d\u3056\u2ebd"
+ + "\u2e7d\u3034\u306a\u30a3\u2f64\u3060\u2fa5\u2ec8\u2e94\u2e2c\u2df8"
+ + "\u2df8\u2d16\u2cdc\u2ca2\u2c68\u2de0\u2a3d\u29fd\u29bd\u297d\u293d"
+ + "\u28fd\u28bd\u287d\u283d\u27fd\u27bd\u277d\u273d\u26fd\u26bd\u267d"
+ + "\u263d\u25fd\u25bd\u257d\u253d\u24fd\u24bd\u247d\u243d\u23fd\u23bd"
+ + "\u237d\u233d\u22fd\u22bd\u227d\u223d\u21fd\u21bd\u217d\u213d\u20fd"
+ + "\u20bd\u207d\u203d\u1ffd\u1fbd\u1f7d\u1f3d\u1efd\u1ebd\u1e7d\u1e3d"
+ + "\u1dfd\u1dbd\u1d7d\u1d3d\u1cfd\u1cbd\u1c7d\u1c3d\u1bfd\u1bbd\u1b7d"
+ + "\u1b3d\u1afd\u1abd\u1a7d\u1a3d\u19fd\u19bd\u197d\u193d\u18fd\u18bd"
+ + "\u187d\u183d\u17fd\u17bd\u177d\u173d\u16fd\u16bd\u167d\u163d\u15fd"
+ + "\u15bd\u157d\u153d\u14fd\u14bd\u147d\u143d\u13fd\u13bd\u137d\u133d"
+ + "\u12fd\u12bd\u127d\u123d\u11fd\u11bd\u117d\u113d\u10fd\u10bd\u107d"
+ + "\u103d\u0ffd\u0fbd\u0f7d\u0f3d\u0efd\u0ebd\u0e7d\u0e3d\u0dfd\u0dbd"
+ + "\u0d7d\u0d3d\u0cfd\u0cbd\u0c7d\u0c3d\u0bfd\u0bbd\u0b7d\u0b3d\u0afd"
+ + "\u0abd\u0a7d\u0a3d\u09fd\u09bd\u097d\u093d\u08fd\u08bd\u087d\u083d"
+ + "\u07fd\u07bd\u077d\u073d\u06fd\u06bd\u067d\u063d\u05fd\u05bd\u057d"
+ + "\u053d\u04fd\u04bd\u047d\u043d\u03fd\u03bd\u037d\u033d\u02fd\u02bd"
+ + "\u027d",
+
+ "\000\uff80\uff00\ufe80\ufe00\ufd80\ufd00\ufc80\ufc00\ufb80\ufb00"
+ + "\ufa80\ufa00\uf980\uf900\uf880\uf800\uf780\uf700\uf680\uf600\uf580"
+ + "\uf500\uf480\uf400\uf380\uf300\uf280\uf200\uf180\uf100\uf080\uf000"
+ + "\uef80\uef00\uee80\uee00\ued80\ued00\uec80\uec00\ueb80\ueb00\uea80"
+ + "\uea00\ue980\ue900\ue880\ue800\ue780\ue700\ue680\ue600\ue580\ue500"
+ + "\ue480\ue400\ue380\ue300\ue280\ue200\ue180\ue100\ue080\ue000\udf80"
+ + "\udf00\ude80\ude00\udd80\udd00\udc80\udc00\udb80\udb00\uda80\uda00"
+ + "\ud980\ud900\ud880\ud800\ud780\ud700\ud680\ud600\ud580\ud500\ud480"
+ + "\ud400\ud380\ud300\ud280\ud200\ud180\ud100\ud080\ud000\ucf80\ucf00"
+ + "\uce80\uce00\ucd80\ucd00\ucc80\ucc00\ucb80\ucb00\uca80\uca00\uc980"
+ + "\uc900\uc880\uc800\uc780\uc700\uc680\uc600\uc580\uc500\uc480\uc400"
+ + "\uc380\uc300\uc280\uc200\uc180\uc100\uc080\uc000\ubf80\ubf00\ube80"
+ + "\ube00\ubd80\ubd00\ubc80\ubc00\ubb80\ubb00\uba80\uba00\ub980\ub900"
+ + "\ub880\ub800\ub780\ub700\ub680\ub600\ub580\ub500\ub480\ub400\ub380"
+ + "\ub300\ub280\ub200\ub180\ub100\ub080\ub000\uaf80\uaf00\uae80\uae00"
+ + "\uad80\uad00\uac80\uac00\uab80\uab00\uaa80\uaa00\ua980\ua900\ua880"
+ + "\ua800\ua780\ua700\ua680\ua600\ua580\ua500\ua480\ua400\ua380\ua300"
+ + "\ua280\ua200\ua180\ua100\ua080\ua000\u9f80\u9f00\u9e80\u9e00\u9d80"
+ + "\u9d00\u9c80\u9c00\u9b80\u9b00\u9a80\u9a00\u9980\u9900\u9880\u9800"
+ + "\u9780\u9700\u9680\u9600\u9580\u9500\u9480\u9400\u9380\u9300\u9280"
+ + "\u9200\u9180\u9100\u9080\u9000\u8f80\u8f00\u8e80\u8e00\u8d80\u8d00"
+ + "\u8c80\u8c00\u8b80\u8b00\u8a80\u8a00\u8980\u8900\u8880\u8800\u8780"
+ + "\u8700\u8680\u8600\u8580\u8500\u8480\u8400\u8380\u8300\u8280\u8200"
+ + "\u8180\u8100\u8080\u8000\u7f80\u7f00\u7e80\u7e00\u7d80\u7d00\u7c80"
+ + "\u7c00\u7b80\u7b00\u7a80\u7a00\u7980\u7900\u7880\u7800\u7780\u7700"
+ + "\u7680\u7600\u7580\u7500\u7480\u7400\u7380\u7300\u7280\u7200\u7180"
+ + "\u7100\u7080\u7000\u6f80\u6f00\u6e80\u6e00\u6d80\u6d00\u6c80\u6c00"
+ + "\u6b80\u6b00\u6a80\u6a00\u6980\u6900\u6880\u6800\u6780\u6700\u6680"
+ + "\u6600\u6580\u6500\u6480\u6400\u6380\u6300\u6280\u6200\u6180\u6100"
+ + "\u6080\u6000\u5f80\u5f00\u5e80\u5e00\u5d80\u5d00\u5c80\u5c00\u5b80"
+ + "\u5b00\u5a80\u5a00\u59a9\u5980\u5900\u5880\u5800\u5780\u5700\u5680"
+ + "\u5600\u5580\u5500\u5480\u5400\u5380\u5300\u5280\u5200\u5180\u5100"
+ + "\u5080\u5000\u4f80\u4f00\u4e80\u4e00\u4d80\u4d00\u4c80\u4c00\u4b80"
+ + "\u4b00\u4a80\u4a00\u4980\u4900\u4880\u4800\u4780\u4700\u4680\u4600"
+ + "\u4580\u4500\u4480\u4400\u4380\u4300\u4280\u4200\u4180\u4100\u4080"
+ + "\u4000\u3f80\u3f00\u3e80\u3e00\u3d80\u3d00\u3c80\u3c00\u3b80\u3b00"
+ + "\u3a80\u3a00\u3980\u3900\u3880\u3800\u3780\u3700\u3680\u3600\u3580"
+ + "\u3500\u3480\u3400\u3380\u3300\u3280\u3200\u3180\u3100\u3080\u3000"
+ + "\u2f80\u2f00\u2e80\u2e00\u2d80\u2d00\u2c80\u2c00\u2b80\u2b00\u2a80"
+ + "\u2a00\u2980\u2900\u2880\u2800\u2780\u2700\u2680\u2600\u2580\u2500"
+ + "\u2480\u2400\u2380\u2300\u2280\u2200\u2180\u2100\u2080\u2000\u1f80"
+ + "\u1f00\u1e80\u1e00\u1d80\u1d00\u1c80\u1c00\u1b80\u1b00\u1a80\u1a00"
+ + "\u1980\u1900\u1880\u1800\u1780\u1700\u1680\u1600\u1580\u1500\u1480"
+ + "\u1400\u1380\u1300\u1280\u1200\u1180\u1100\u1080\u1000\u0f80\u0f00"
+ + "\u0e80\u0e00\u0d80\u0d00\u0c80\u0c00\u0b80\u0b00\u0a80\u0a00\u0980"
+ + "\u0900\u0800\u0780\u0700\u0680\u0662\u0600\u0580\u0500\u0480\u0400"
+ + "\u0380\u0300\u0280\u0200\u0180\u0100",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "\u00ff\000\uff00\ufe90\ufe80\ufe00\ufd80\ufd00\ufc80\ufc00\ufb80"
+ + "\ufb00\ufa80\ufa00\uf980\uf900\uf880\uf800\uf780\uf700\uf680\uf600"
+ + "\uf580\uf500\uf480\uf400\uf380\uf300\uf280\uf200\uf180\uf100\uf080"
+ + "\uf000\uef80\uef00\uee80\uee00\ued80\ued00\uec80\uec00\ueb80\ueb00"
+ + "\uea80\uea00\ue980\ue900\ue880\ue800\ue780\ue700\ue680\ue600\ue580"
+ + "\ue500\ue480\ue400\ue380\ue300\ue280\ue200\ue180\ue100\ue080\ue000"
+ + "\udf80\udf00\ude80\ude00\udd80\udd00\udc80\udc00\udb80\udb00\uda80"
+ + "\uda00\ud980\ud900\ud880\ud800\ud780\ud700\ud680\ud600\ud580\ud500"
+ + "\ud480\ud400\ud380\ud300\ud280\ud200\ud180\ud100\ud080\ud000\ucf80"
+ + "\ucf00\uce80\uce00\ucd80\ucd00\ucc80\ucc00\ucb80\ucb00\uca80\uca00"
+ + "\uc980\uc900\uc880\uc800\uc780\uc700\uc680\uc600\uc580\uc500\uc480"
+ + "\uc400\uc380\uc300\uc280\uc200\uc180\uc100\uc080\uc000\ubf80\ubf00"
+ + "\ube80\ube00\ubd80\ubd00\ubc80\ubc00\ubb80\ubb00\uba80\uba00\ub980"
+ + "\ub900\ub880\ub800\ub780\ub700\ub680\ub600\ub580\ub500\ub480\ub400"
+ + "\ub380\ub300\ub280\ub200\ub180\ub100\ub080\ub000\uaf80\uaf00\uae80"
+ + "\uae00\uad80\uad00\uac80\uac00\uab80\uab00\uaa80\uaa00\ua980\ua900"
+ + "\ua880\ua800\ua780\ua700\ua680\ua600\ua580\ua500\ua480\ua400\ua380"
+ + "\ua300\ua280\ua200\ua180\ua100\ua080\ua000\u9f80\u9f00\u9e80\u9e00"
+ + "\u9d80\u9d00\u9c80\u9c00\u9b80\u9b00\u9a80\u9a00\u9980\u9900\u9880"
+ + "\u9800\u9780\u9700\u9680\u9600\u9580\u9500\u9480\u9400\u9380\u9300"
+ + "\u9280\u9200\u9180\u9100\u9080\u9000\u8f80\u8f00\u8e80\u8e00\u8d80"
+ + "\u8d00\u8c80\u8c00\u8b80\u8b00\u8a80\u8a00\u8980\u8900\u8880\u8800"
+ + "\u8780\u8700\u8680\u8600\u8580\u8500\u8480\u8400\u8380\u8300\u8280"
+ + "\u8200\u8180\u8100\u8080\u8000\u7f80\u7f00\u7e80\u7e00\u7d80\u7d00"
+ + "\u7c80\u7c00\u7b80\u7b00\u7a80\u7a00\u7980\u7900\u7880\u7800\u7780"
+ + "\u7700\u7680\u7600\u7580\u7500\u7480\u7400\u7380\u7300\u7280\u7200"
+ + "\u7180\u7100\u7080\u7000\u6f80\u6f00\u6e80\u6e00\u6d80\u6d00\u6c80"
+ + "\u6c00\u6b80\u6b00\u6a80\u6a00\u6980\u6900\u6880\u6800\u6780\u6700"
+ + "\u6680\u6600\u6580\u6500\u6480\u6400\u6380\u6300\u6280\u6200\u6180"
+ + "\u6100\u6080\u6000\u5f80\u5f00\u5e80\u5e00\u5d80\u5d00\u5c80\u5c00"
+ + "\u5b80\u5b00\u5a80\u5a00\u5980\u5900\u5880\u5800\u5780\u5700\u5680"
+ + "\u5600\u5580\u5500\u5480\u5400\u5380\u5300\u5280\u5200\u5180\u5100"
+ + "\u5080\u5000\u4f80\u4f00\u4e80\u4e00\u4d80\u4d00\u4c80\u4c00\u4b80"
+ + "\u4b00\u4a80\u4a00\u4980\u4900\u4880\u4800\u4780\u4700\u4680\u4600"
+ + "\u4580\u4500\u4480\u4400\u4380\u4300\u4280\u4200\u4180\u4100\u4080"
+ + "\u4000\u3f80\u3f00\u3e80\u3e00\u3d80\u3d00\u3c80\u3c00\u3b80\u3b00"
+ + "\u3a80\u3a00\u3980\u3900\u3880\u3800\u3780\u3700\u3680\u3600\u3580"
+ + "\u3500\u3480\u3400\u3380\u3300\u3280\u3200\u3180\u3100\u3080\u3000"
+ + "\u2f80\u2f00\u2e80\u2e00\u2d80\u2d00\u2c80\u2c00\u2b80\u2b00\u2a80"
+ + "\u2a00\u2980\u2900\u2880\u2800\u2780\u2700\u2680\u2600\u2580\u2500"
+ + "\u2480\u2400\u2380\u2300\u2280\u2200\u2180\u2100\u2080\u2000\u1f80"
+ + "\u1f00\u1e80\u1e00\u1d80\u1d00\u1c80\u1c00\u1b80\u1b00\u1a80\u1a00"
+ + "\u1980\u1900\u1880\u1800\u1780\u1700\u1680\u1600\u1580\u1500\u1480"
+ + "\u1400\u1380\u1300\u1280\u1200\u1180\u1100\u1080\u1000\u0f80\u0f00"
+ + "\u0e80\u0e00\u0d80\u0d00\u0c80\u0c00\u0b80\u0b00\u0a80\u0a00\u0980"
+ + "\u0900\u0880\u0800\u0780\u0700\u0680\u0600\u0580\u0500\u0480\u0400"
+ + "\u0380\u0300\u0280\u0200\u0180\u0100",
+
+ "",
+
+ ""};
+
+ /**
+ * The array containing the numeric values that are too large to be stored as
+ * chars in NUM_VALUE. NUM_VALUE in this case will contain a negative integer
+ * N such that LARGENUMS[-N - 3] contains the correct numeric value.
+ */
+ int[] LARGENUMS
+ = new int[] {40000, 50000, 60000, 70000, 80000, 90000};
/**
* Information about each character. The low order 5 bits form the
@@ -282,496 +700,594 @@ public interface CharData
* next bit is a flag for mirrored directionality. The high order 9 bits
* form the offset into the attribute tables. Note that this limits the
* number of unique character attributes to 512, which is not a problem
- * as of Unicode version 3.2.0, but may soon become one.
+ * as of Unicode version 4.0.0, but may soon become one.
*/
- String DATA
- = "\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
- + "\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082"
- + "\u3e80\u3e80\u3001\u3082\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3a85"
- + "\u3a85\u3e80\u3e80\u3e80\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85"
- + "\u3e80\u3e80\u3e80\u3e80\u5b88\u5b88\u3e80\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80"
- + "\u3e80\u3e80\u3e80\u5198\u3e80\u3e80\u3e80\u3e80\u4606\u3e80\u3e80"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u3a85"
- + "\u3a85\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u3e80\u3e80\u3e80\u3e80\u5202\u5202\u5202\u5202"
- + "\u5202\u5202\u5202\u5202\u5202\u5202\u5202\u5202\u5202\u5202\u5202"
- + "\u5202\u5202\u5202\u5202\u5202\u5202\u5202\u5202\u5202\u5202\u5202"
- + "\u5202\u5202\u5202\u5202\u5202\u2e82\u3e80\u5198\u2a14\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u4606\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4686\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u1a1b\u1a1b\u3e80\u3e80\u3e80\u3e80\u4584\u3e80\u3e80"
- + "\u3e80\u0298\u3e80\u0298\u6615\u6696\u0298\u1a97\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u4584\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u4584\u4584\u1a1b\u1a1b\u1a1b\u1a1b"
- + "\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u4584"
- + "\u4584\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b"
- + "\u1a1b\u1a1b\u1a1b\u1a1b\u2e82\u7282\u2e82\u3e80\u2e82\u4902\u7481"
- + "\u7481\u7481\u7481\u7383\u1a1b\u1a1b\u1a1b\u6d82\u6d82\u4902\u4902"
- + "\u3e80\u3e80\u2e82\u4902\u6e01\u6e01\u7501\u7501\u3e80\u1a1b\u1a1b"
- + "\u1a1b\u1b02\u1b82\u1c02\u1c82\u1d02\u1d82\u1e02\u1e82\u1f02\u1f82"
- + "\u2002\u2082\u2102\u2182\u2202\u2282\u2302\u2382\u2402\u2482\u2502"
- + "\u2582\u2602\u2682\u2702\u2782\u0455\u0c99\u04d6\u0c99\017\017"
- + "\017\017\017\u010f\017\017\017\017\017\017\017"
- + "\017\017\017\017\017\017\017\017\017\017\017"
- + "\017\017\017\017\017\017\017\017\u008f\u010f\u008f"
- + "\u018f\u010f\017\017\017\017\017\017\017\017\017"
- + "\017\017\017\017\017\u010f\u010f\u010f\u008f\u020c\u0298"
- + "\u0298\u0318\u039a\u0318\u0298\u0298\u0455\u04d6\u0298\u0519\u0598"
- + "\u0614\u0598\u0698\u0709\u0789\u0809\u0889\u0909\u0989\u0a09\u0a89"
- + "\u0b09\u0b89\u0598\u0298\u0c59\u0c99\u0c59\u0298\u0d01\u0d81\u0e01"
- + "\u0e81\u0f01\u0f81\u1001\u1081\u1101\u1181\u1201\u1281\u1301\u1381"
- + "\u1401\u1481\u1501\u1581\u1601\u1681\u1701\u1781\u1801\u1881\u1901"
- + "\u1981\u0455\u0298\u04d6\u1a1b\u1a97\u0298\u0298\u0298\u0c99\u0455"
- + "\u04d6\u3e80\u0298\u0298\u0298\u0298\u0298\u0298\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u282c\u0298\u039a\u039a\u039a\u039a\u289c"
- + "\u289c\u1a1b\u289c\u2902\u29dd\u0c99\u2a14\u289c\u1a1b\u2a9c\u0519"
- + "\u2b0b\u2b8b\u1a1b\u2c02\u289c\u0298\u1a1b\u2c8b\u2902\u2d5e\u2d8b"
- + "\u2d8b\u2d8b\u0298\u0298\u0519\u0614\u0c99\u0c99\u0c99\u3e80\u0298"
- + "\u039a\u0318\u0298\u3e80\u3e80\u3e80\u3e80\u5405\u5405\u5405\u3e80"
- + "\u5405\u3e80\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u3e80\u3e80\u3e80\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u3e80\u501c\u501c\u4f81\u4f81"
- + "\u4f81\u4f81\u4f81\u4f81\u4f81\u4f81\u4f81\u4f81\u4f81\u4f81\u4f81"
- + "\u4f81\u4f81\u4f81\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01"
- + "\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01"
- + "\u2e01\u2e01\u2e01\u2e01\u0c99\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01"
- + "\u2e01\u2e82\u2e82\u2e82\u4902\u4902\u2e82\u2e82\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u2e82\u2e82"
- + "\u2e82\u2e82\u2e82\u3e80\u3e80\u3e80\u3e80\u3e80\u5305\u4606\u5305"
- + "\u5305\u3e80\u5305\u5305\u3e80\u5305\u5305\u5305\u5305\u5305\u5305"
- + "\u5305\u5305\u5305\u5305\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5398\u5405\u4606\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u5087\u5087\u4606\u5087\u5087\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b"
- + "\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u840b\u3082\u3001\u3082\u3001\u3082"
- + "\u3001\u3082\u3001\u3082\u2e82\u3001\u3082\u3001\u3082\u3001\u3082"
- + "\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
- + "\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082"
- + "\u3001\u3082\u3001\u3082\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u5c09"
- + "\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09\u5f89\u6009\u6089\u4606\u4606"
- + "\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u1a1b\u1a1b\u4701\u0298\u4781\u4781\u4781\u3e80"
- + "\u4801\u3e80\u4881\u4881\u4902\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01"
- + "\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2f02"
- + "\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02"
+ String[] DATA = new String[]{
+ "\u2282\u2302\u2382\u2402\u2482\u2502\u2582\u2602\u2682\u2702\u2782"
+ + "\u0455\u0c99\u04d6\u0c99\017\017\017\017\017\017\017"
+ + "\017\017\u008f\u010f\u008f\u018f\u010f\017\017\017\017"
+ + "\017\u010f\017\017\017\017\017\017\017\017\017"
+ + "\017\017\017\017\017\017\017\u010f\u010f\u010f\u008f"
+ + "\u0709\u0789\u0809\u0889\u0909\u0989\u0a09\u0a89\u0b09\u0b89\u0598"
+ + "\u0298\u0c59\u0c99\u0c59\u0298\u0298\u0c99\u0298\u1a97\u3f80\u3f80"
+ + "\u0298\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u020c\u0298\u0298"
+ + "\u0318\u039a\u0318\u0298\u0298\u0455\u04d6\u0298\u0519\u0598\u0614"
+ + "\u0598\u0698\u2a9c\u0519\u2b0b\u2b8b\u1a1b\u2c02\u289c\u0298\u1a1b"
+ + "\u2c8b\u2902\u2d5e\u2d8b\u2d8b\u2d8b\u0298\u0d01\u0d81\u0e01\u0e81"
+ + "\u0f01\u0f81\u1001\u1081\u1101\u1181\u1201\u1281\u1301\u1381\u1401"
+ + "\u1481\u1501\u1581\u1601\u1681\u1701\u1781\u1801\u1881\u1901\u1981"
+ + "\u0455\u0298\u04d6\u1a1b\u1a97\u0298\u0298\u0298\u0c99\u0455\u04d6"
+ + "\u0298\u0298\u0298\u0298\u0298\u0298\u0298\u0298\u0298\u858d\u860e"
+ + "\u8690\u8710\u8790\u8810\u8890\u82ac\u282c\u0298\u039a\u039a\u039a"
+ + "\u039a\u289c\u289c\u1a1b\u289c\u2902\u29dd\u0c99\u2a10\u289c\u1a1b"
+ + "\u1b02\u1b82\u1c02\u1c82\u1d02\u1d82\u1e02\u1e82\u1f02\u1f82\u2002"
+ + "\u2082\u2102\u2182\u2202\u4a82\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01"
+ + "\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u0c99"
+ + "\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e82\u3c01\u3c83\u3d02"
+ + "\u3001\u3082\u3e01\u3e81\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
+ + "\u3082\u3201\u3001\u3082\u3001\u3082\u3001\u3082\u3282\u4a82\u2f02"
+ "\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02"
- + "\u0c99\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f82\u2f02\u2f02"
- + "\u4a82\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u4b02"
- + "\u4b82\u4b82\u3e80\u4c02\u4c82\u4d01\u4d01\u4d01\u4d82\u4e02\u2902"
- + "\u3e80\u3e80\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
- + "\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u2e82\u3b81\u3c03\u3c82"
- + "\u3001\u3082\u3d81\u3e01\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
- + "\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3101\u3182"
- + "\u3001\u3082\u3001\u3082\u3001\u3082\u2902\u3001\u3082\u3001\u3082"
- + "\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
- + "\u3082\u4e82\u4f02\u3d02\u2902\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u5b10\u5b10\u5b10\u5b10\u5b10"
- + "\u5b10\u7f0b\u3e80\u3e80\u3e80\u7f8b\u800b\u808b\u810b\u818b\u820b"
- + "\u0519\u0519\u0c99\u0455\u04d6\u2902\u3301\u3001\u3082\u3001\u3082"
- + "\u3381\u3001\u3082\u3401\u3401\u3001\u3082\u2902\u3481\u3501\u3581"
- + "\u3001\u3082\u3401\u3601\u3682\u3701\u3781\u3001\u3082\u2902\u2902"
- + "\u3701\u3801\u2902\u3881\u3a85\u3a85\u3a85\u3a85\u3b81\u3c03\u3c82"
- + "\u3b81\u3c03\u3c82\u3b81\u3c03\u3c82\u3001\u3082\u3001\u3082\u3001"
- + "\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082"
- + "\u3d02\u3001\u3082\u501c\u4606\u4606\u4606\u4606\u3e80\u5087\u5087"
- + "\u3e80\u3e80\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
- + "\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082"
- + "\u3001\u3082\u3001\u3082\u3201\u3001\u3082\u3001\u3082\u3001\u3082"
- + "\u3282\u3001\u3082\u3001\u3082\u3001\u3082\u3901\u3001\u3082\u3901"
- + "\u2902\u2902\u3001\u3082\u3901\u3001\u3082\u3981\u3981\u3001\u3082"
- + "\u3001\u3082\u3a01\u3001\u3082\u2902\u3a85\u3001\u3082\u2902\u3b02"
- + "\u4d01\u3001\u3082\u3001\u3082\u3e80\u3e80\u3001\u3082\u3e80\u3e80"
- + "\u3001\u3082\u3e80\u3e80\u3e80\u3001\u3082\u3001\u3082\u3001\u3082"
- + "\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
- + "\u3082\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u0598\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u5398\u3e80\u3e80\u3e80\u5398"
- + "\u5398\u5398\u5398\u5398\u5398\u5398\u5398\u5398\u5398\u5398\u5398"
- + "\u5398\u5398\u3e80\u5b10\u5405\u4606\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u3e80\u3e80\u5b10\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01"
- + "\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01"
- + "\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01\u4d01"
- + "\u4d01\u4d01\u4d01\u4d01\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u5c09\u5c89\u5d09\u5d89\u5e09\u5e89"
- + "\u5f09\u5f89\u6009\u6089\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u2902\u2902\u2902\u3f02\u3f82\u2902\u4002"
- + "\u4002\u2902\u4082\u2902\u4102\u2902\u2902\u2902\u2902\u4002\u2902"
- + "\u2902\u4182\u2902\u2902\u2902\u2902\u4202\u4282\u2902\u2902\u2902"
- + "\u2902\u2902\u4282\u2902\u2902\u4302\u2902\u2902\u4382\u2902\u2902"
- + "\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u4402\u2902\u2902"
- + "\u4402\u2902\u2902\u2902\u2902\u4402\u2902\u4482\u4482\u2902\u2902"
- + "\u2902\u2902\u2902\u2902\u4502\u2902\u2902\u2902\u2902\u2902\u2902"
- + "\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u3e80\u3e80\u4584"
- + "\u4584\u4584\u4584\u4584\u4584\u4584\u4584\u4584\u1a1b\u1a1b\u4584"
- + "\u4584\u4584\u4584\u4584\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b"
- + "\u1a1b\u1a1b\u4584\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u5101\u5101"
- + "\u5101\u5101\u5101\u5101\u5101\u5101\u5101\u5101\u5101\u5101\u5101"
- + "\u5101\u5101\u5101\u5101\u5101\u5101\u5101\u5101\u5101\u5101\u3e80"
- + "\u3e80\u4584\u5198\u5198\u5198\u5198\u5198\u5198\u2e01\u2e01\u3e80"
- + "\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u4982\u4a02"
- + "\u4a02\u4a02\u4902\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02"
- + "\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u4f02\u4f02\u4f02"
- + "\u4f02\u4f02\u4f02\u4f02\u4f02\u4f02\u4f02\u4f02\u4f02\u4f02\u4f02"
- + "\u4f02\u4f02\u4606\u4606\u4606\u4606\u4606\u5198\u4606\u4606\u3a85"
- + "\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u3e80\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u3e80\u4606\u4606\u4606\u5298"
- + "\u4606\u4606\u5298\u4606\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u5305\u5305\u5305\u5305\u5305\u5305\u5305"
- + "\u5305\u5305\u5305\u5305\u5305\u5305\u5305\u5305\u5305\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u5305\u5305\u5305\u5298\u5298\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u5c89\u5d09\u5d89"
- + "\u5e09\u5e89\u5f09\u5f89\u6009\u6089\u640b\u648b\u650b\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u4606\u5b88\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80"
- + "\u3e80\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80"
- + "\u3e80\u3a85\u3a85\u3e80\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3e80"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u5b88\u5b88\u5b88\u5b88\u3e80\u4606\u4606\u4606\u3e80\u4606"
- + "\u4606\u4606\u4606\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u4606"
- + "\u4606\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u4606"
- + "\u5b88\u5b88\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3e80\u3e80\u3a85\u3a85\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3e80\u3e80\u3e80\u3e80\u5b88\u5b88\u3e80\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3a85\u3a85\u3a85"
- + "\u3e80\u3e80\u3e80\u3e80\u5c09\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09"
- + "\u5f89\u6009\u6089\u501c\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u5509\u5589\u5609"
- + "\u5689\u5709\u5789\u5809\u5889\u5909\u5989\u0318\u5a18\u5a18\u5398"
- + "\u3e80\u3e80\u4606\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u3e80\u3e80\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u6615\u6696\u5484\u5405\u5405\u5405\u5405"
- + "\u5405\u5405\u5405\u5405\u5405\u5405\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u5b88\u5b88\u5198\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u4606\u4606\u5b88"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3e80"
- + "\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u5198\u5198\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u4606\u4606\u4606\u4606\u4606\u5484\u5484\u4606"
- + "\u4606\u289c\u4606\u4606\u4606\u4606\u3e80\u3e80\u0709\u0789\u0809"
- + "\u0889\u0909\u0989\u0a09\u0a89\u0b09\u0b89\u5405\u5405\u5405\u5a9c"
- + "\u5a9c\u3e80\u3a85\u3a85\u3a85\u3e80\u3a85\u3e80\u3a85\u3e80\u3e80"
- + "\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u4606\u3a85\u3a85\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u3e80\u4606\u4606\u3a85\u3e80\u3e80"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u4606\u4606\u5b88"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3e80\u3e80\u4606\u3a85\u5b88\u5b88\u5b88\u5b88\u5b88\u3e80\u4606"
- + "\u5b88\u5b88\u3e80\u5b88\u5b88\u4606\u4606\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u5b88\u5b88\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3a85\u3e80\u5198\u5198\u5198\u5198\u5198\u5198\u5198\u5198"
- + "\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09\u5f89\u6009\u6089\u640b\u670b"
- + "\u678b\u680b\u688b\u690b\u698b\u6a0b\u6a8b\u648b\u6b0b\u3e80\u3e80"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3e80"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u4606\u3a85\u5b88\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u5b88\u5b88\u5b88\u5b88"
- + "\u4606\u3e80\u3e80\u3a85\u4606\u4606\u4606\u4606\u3e80\u3e80\u3e80"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3e80\u3e80\u3e80"
- + "\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u4606\u3e80\u5b88\u5b88\u5b88"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85"
- + "\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3e80\u3a85"
- + "\u3a85\u3a85\u3a85\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3e80\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u4606\u3a85\u3a85\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u3e80\u3e80\u3e80\u3e80\u039a\u039a\u039a"
- + "\u039a\u039a\u039a\u039a\u039a\u039a\u039a\u039a\u039a\u039a\u039a"
- + "\u039a\u039a\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3a85\u3a85\u4606\u4606"
- + "\u5198\u5198\u5c09\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09\u5f89\u6009"
- + "\u6089\u5198\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u0298\u0298\u0318\u039a\u0318"
- + "\u0298\u0298\u6615\u6696\u0298\u0519\u0598\u0614\u0598\u0698\u0709"
- + "\u0789\u0809\u0889\u0909\u0989\u0a09\u0a89\u0b09\u0b89\u0598\u0298"
- + "\u0c99\u0c99\u0c99\u0298\u0298\u0298\u0298\u0298\u0298\u2a14\u0298"
- + "\u0298\u0298\u0298\u5b10\u5b10\u5b10\u5b10\u3e80\u5c09\u5c89\u5d09"
- + "\u5d89\u5e09\u5e89\u5f09\u5f89\u6009\u6089\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u5b88"
- + "\u4606\u4606\u4606\u4606\u3e80\u3e80\u5b88\u5b88\u3e80\u3e80\u5b88"
- + "\u5b88\u4606\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u5b88\u3e80\u3e80\u3e80\u3e80\u3a85\u3a85\u3e80\u3a85\u3e80\u3e80"
- + "\u3a85\u3a85\u3e80\u3a85\u3e80\u3e80\u3a85\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3e80\u3a85\u3a85\u3e80\u3a85\u3a85\u3e80\u3a85\u3a85"
- + "\u3e80\u3e80\u4606\u3e80\u5b88\u5b88\u4606\u4606\u3e80\u3e80\u3e80"
- + "\u3e80\u4606\u4606\u3e80\u3e80\u4606\u4606\u4606\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3a85\u3a85\u3a85"
- + "\u3a85\u3e80\u3a85\u3e80\u3a85\u3a85\u4606\u4606\u3e80\u3e80\u5c09"
- + "\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09\u5f89\u6009\u6089\u3a85\u3a85"
- + "\u039a\u039a\u610b\u618b\u620b\u628b\u630b\u638b\u501c\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3a85"
- + "\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u4606\u3a85"
- + "\u5b88\u5b88\u4606\u4606\u4606\u4606\u4606\u3e80\u4606\u4606\u5b88"
- + "\u3e80\u5b88\u5b88\u4606\u3e80\u3e80\u3a85\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u5c09\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09\u5f89\u6009\u6089\u630b"
- + "\u630b\u630b\u630b\u630b\u630b\u630b\u630b\u630b\u630b\u501c\u4606"
- + "\u501c\u4606\u501c\u4606\u6615\u6696\u6615\u6696\u5b88\u5b88\u4606"
- + "\u4606\u4606\u3e80\u3e80\u3e80\u5b88\u5b88\u3e80\u3e80\u5b88\u5b88"
- + "\u4606\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u4606\u5b88"
- + "\u3e80\u3e80\u3e80\u3e80\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3e80\u3a85\u3a85\u3e80\u5b88\u4606\u4606\u4606\u4606\u5b88"
- + "\u4606\u3e80\u3e80\u3e80\u4606\u4606\u5b88\u4606\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u5b88\u5b88\u5b88\u4606\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u5b88\u5b88\u3e80\u3e80\u3e80\u5b88\u5b88\u5b88\u3e80\u5b88\u5b88"
- + "\u5b88\u4606\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u5b88\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3e80\u4584\u3e80\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u3e80\u3e80\u5c09\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09\u5f89"
- + "\u6009\u6089\u3e80\u3e80\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u5c09"
- + "\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09\u5f89\u6009\u6089\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u5087\u5087\u5087\u5b88\u4606\u4606"
- + "\u4606\u3e80\u3e80\u5b88\u5b88\u5b88\u3e80\u5b88\u5b88\u5b88\u4606"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u5b88\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u4606\u3e80\u3e80\u3e80\u3e80"
- + "\u5b88\u5b88\u5b88\u4606\u4606\u4606\u3e80\u4606\u3e80\u5b88\u5b88"
- + "\u5b88\u5b88\u5b88\u5b88\u5b88\u5b88\u4606\u5b88\u5b88\u4606\u4606"
- + "\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u4606\u5198\u5198"
- + "\u5198\u5198\u5198\u5198\u5198\u039a\u5198\u3e80\u3e80\u3e80\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u4584\u4606\u4606\u4606\u4606\u4606"
- + "\u4606\u4606\u4606\u5198\u5c09\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09"
- + "\u5f89\u6009\u6089\u5198\u5198\u3e80\u3e80\u3e80\u3e80\u3a85\u501c"
- + "\u501c\u501c\u5198\u5198\u5198\u5198\u5198\u5198\u5198\u5198\u65b8"
- + "\u5198\u5198\u5198\u5198\u5198\u5198\u501c\u501c\u501c\u501c\u501c"
- + "\u4606\u4606\u501c\u501c\u501c\u501c\u501c\u501c\u4606\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u3e80\u3e80\u501c\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u3e80\u3e80\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u1a97\u4584\u4584\u4584"
- + "\u3e80\u5c09\u5c89\u5d09\u5d89\u5e09\u5e89\u5f09\u5f89\u6009\u6089"
- + "\u5198\u5198\u5198\u5198\u5198\u5198\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u5b88\u5b88\u4606\u4606\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u020c\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u6615\u6696\u3e80\u3e80\u3e80\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u5198"
- + "\u5198\u5198\u6b8b\u6c0b\u6c8b\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u4606\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3001\u3082\u3001"
- + "\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082"
- + "\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u2e82\u2e82\u2e82"
- + "\u2e82\u2e82\u6d02\u3e80\u3e80\u3e80\u3e80\u6d82\u6d82\u6d82\u6d82"
- + "\u6d82\u6d82\u6d82\u6d82\u6e01\u6e01\u6e01\u6e01\u6e01\u6e01\u6e01"
- + "\u6e01\u6d82\u6d82\u6d82\u6d82\u6d82\u6d82\u6d82\u6d82\u6e01\u6e01"
- + "\u6e01\u6e01\u6e01\u6e01\u6e01\u6e01\u6d82\u6d82\u6d82\u6d82\u6d82"
- + "\u6d82\u3e80\u3e80\u6e01\u6e01\u6e01\u6e01\u6e01\u6e01\u3e80\u3e80"
- + "\u2e82\u6d82\u4902\u6d82\u4902\u6d82\u4902\u6d82\u3e80\u6e01\u3e80"
- + "\u6e01\u3e80\u6e01\u3e80\u6e01\u6d82\u6d82\u6d82\u6d82\u6d82\u6d82"
- + "\u6d82\u6d82\u6e01\u6e01\u6e01\u6e01\u6e01\u6e01\u6e01\u6e01\u6e82"
- + "\u6e82\u6f02\u6f02\u6f02\u6f02\u6f82\u6f82\u7002\u7002\u7082\u7082"
- + "\u7102\u7102\u3e80\u3e80\u7182\u7182\u7182\u7182\u7182\u7182\u7182"
- + "\u7182\u7203\u7203\u7203\u7203\u7203\u7203\u7203\u7203\u7182\u7182"
- + "\u7182\u7182\u7182\u7182\u7182\u7182\u7203\u7203\u7203\u7203\u7203"
- + "\u7203\u7203\u7203\u6d82\u6d82\u2e82\u7282\u2e82\u3e80\u2e82\u4902"
- + "\u6e01\u6e01\u7301\u7301\u7383\u1a1b\u7402\u1a1b\u1b02\u1b82\u1c02"
- + "\u1c82\u1d02\u1d82\u1e02\u1e82\u1f02\u1f82\u2002\u2082\u2102\u2182"
- + "\u2202\u2282\u2302\u2382\u2402\u2482\u2502\u2582\u2602\u2682\u2702"
- + "\u2782\u6615\u0c99\u6696\u0c99\u3e80\u6d82\u6d82\u4902\u4902\u2e82"
- + "\u7582\u2e82\u4902\u6e01\u6e01\u7601\u7601\u7681\u1a1b\u1a1b\u1a1b"
- + "\u3e80\u3e80\u2e82\u7282\u2e82\u3e80\u2e82\u4902\u7701\u7701\u7781"
- + "\u7781\u7383\u1a1b\u1a1b\u3e80\u020c\u020c\u020c\u020c\u020c\u020c"
- + "\u020c\u782c\u020c\u020c\u020c\u788c\u5b10\u5b10\u7910\u7990\u2a14"
- + "\u7a34\u2a14\u2a14\u2a14\u2a14\u0298\u0298\u7a9d\u7b1e\u6615\u7a9d"
- + "\u7a9d\u7b1e\u6615\u7a9d\u0298\u0298\u0298\u0298\u0298\u0298\u0298"
- + "\u0298\u7b8d\u7c0e\u7c90\u7d10\u7d90\u7e10\u7e90\u782c\u0318\u0318"
- + "\u0318\u0318\u0318\u0298\u0298\u0298\u0298\u29dd\u2d5e\u0298\u0298"
- + "\u0298\u0298\u1a97\u7f0b\u2c8b\u2b0b\u2b8b\u7f8b\u800b\u808b\u810b"
- + "\u818b\u820b\u0519\u0519\u0c99\u0455\u04d6\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u3e80\u3e80\u3e80\u3e80\u3e80\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u4d01\u289c\u289c\u289c\u289c"
- + "\u4d01\u289c\u289c\u2902\u4d01\u4d01\u4d01\u2902\u2902\u4d01\u4d01"
- + "\u4d01\u2902\u289c\u4d01\u289c\u289c\u289c\u4d01\u4d01\u4d01\u4d01"
- + "\u4d01\u289c\u289c\ua20a\ua28a\ua30a\ua38a\ua40a\ua48a\ua50a\ua58a"
- + "\ua60a\u4606\u4606\u4606\u4606\u4606\u4606\u2a14\u4584\u4584\u4584"
- + "\u4584\u4584\u289c\u289c\ua68a\ua70a\ua78a\u3e80\u3e80\u3e80\u289c"
- + "\u289c\u289c\u289c\u3e80\u289c\u289c\u289c\u289c\u3e80\u3e80\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u0c99\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u0c99\u0c99\u289c\u289c\u0c99\u289c\u0c99"
+ + "\u2f02\u2f02\u2f02\u2f02\u0c99\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02"
+ + "\u2f02\u2f82\u3f01\u2902\u3001\u3082\u3001\u3082\u3001\u3082\u3001"
+ + "\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3d82\u3001"
+ + "\u3082\u539c\u4786\u4786\u4786\u4786\u3f80\u5407\u5407\u3001\u3082"
+ + "\u3001\u3082\u3001\u3082\u3f80\u3f80\u3001\u3082\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u4786\u6008\u3f80\u3f80\u3f80\u3f80\u3b05\u3b05"
+ + "\u3f80\u3b05\u3f80\u3f80\u3b05\u3b05\u3f80\u3b05\u3f80\u3f80\u3b05"
+ + "\u3f80\u3f80\u2e82\u7e02\u2e82\u3f80\u2e82\u4a82\u8181\u8181\u8201"
+ + "\u8201\u7f03\u1a1b\u1a1b\u3f80\u4786\u4786\u6008\u3f80\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3b05\u3f80\u3b05"
+ + "\u3b05\u3b05\u3b05\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3f80\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80"
+ + "\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u5518\u5518\u3b05\u3b05\u3b05\u3b05\u3c01\u3c83"
+ + "\u3d02\u3c01\u3c83\u3d02\u3c01\u3c83\u3d02\u3001\u3082\u3001\u3082"
+ + "\u2902\u2902\u2902\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3b05\u3b05\u3b05\u3b05\u3f80\u3b05\u3f80\u3b05\u3b05\u3f80"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80\u4786\u3b05\u6008\u6008"
+ + "\u4786\u4786\u4786\u3f80\u3f80\u3f80\u6008\u6008\u3f80\u3f80\u6008"
+ + "\u6008\u4786\u3f80\u3f80\u3101\u3182\u3001\u3082\u3001\u3082\u3001"
+ + "\u3082\u2902\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u2e82"
+ + "\u2e82\u2e82\u2e82\u2e82\u7882\u3f80\u3f80\u3f80\u3f80\u1a1b\u1a1b"
+ + "\u3f80\u3f80\u3f80\u3f80\u4684\u3f80\u3f80\u3f80\u0298\u3f80\u5481"
+ + "\u5481\u5481\u5481\u5481\u5481\u5481\u5481\u5481\u5481\u5481\u5481"
+ + "\u5481\u5481\u5481\u5481\u3f80\u3f80\u4684\u5518\u5518\u5518\u5518"
+ + "\u5518\u5518\u539c\u539c\u539c\u539c\u539c\u4786\u4786\u539c\u539c"
+ + "\u539c\u539c\u539c\u539c\u4786\u539c\u539c\u539c\u539c\u539c\u539c"
+ + "\u3f80\u3f80\u539c\u3b05\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u4d82\u4e02\u4e81"
+ + "\u4e81\u4e81\u4f02\u4f82\u2902\u3001\u3082\u3001\u3082\u3001\u3082"
+ + "\u3001\u3082\u3001\u3082\u2e82\u3001\u3082\u3001\u3082\u3001\u3082"
+ + "\u3981\u3001\u3082\u3981\u2902\u2902\u3001\u3082\u3981\u3001\u4502"
+ + "\u2902\u2902\u4502\u2902\u2902\u2902\u2902\u4502\u2902\u4582\u4582"
+ + "\u2902\u2902\u2902\u2902\u4402\u2902\u2902\u4482\u2902\u2902\u2902"
+ + "\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u4002\u4082\u2902\u4102"
+ + "\u4102\u2902\u4182\u2902\u4202\u2902\u2902\u2902\u2902\u3301\u3001"
+ + "\u3082\u3001\u3082\u3381\u3001\u3082\u3401\u3401\u3001\u3082\u2902"
+ + "\u3481\u3501\u3581\u3001\u3082\u3401\u3601\u3682\u3701\u3781\u3001"
+ + "\u3082\u2902\u2902\u3701\u3801\u3882\u3901\u3082\u3a01\u3a01\u3001"
+ + "\u3082\u3001\u3082\u3a81\u3001\u3082\u2902\u3b05\u3001\u3082\u2902"
+ + "\u3b82\u4786\u4786\u4786\u4786\u4786\u4806\u4786\u4786\u4786\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u4786\u3f80\u4786\u4786\u4786\u5698"
+ + "\u4786\u4786\u5698\u4786\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u6008\u3f80\u3f80\u3f80\u3f80\u3b05\u3b05"
+ + "\u3f80\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80\u3f80\u3b05\u3b05\u3f80"
+ + "\u3b05\u3f80\u3b05\u3b05\u3f80\u3b05\u3b05\u3f80\u3b05\u3b05\u3f80"
+ + "\u3f80\u4786\u3f80\u6008\u6008\u6008\u3f80\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3f80\u3b05\u3b05\u3b05\u3f80\u3f80\u3f80"
+ + "\u3f80\u6008\u6008\u5518\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u5f90\u5f90"
+ + "\u5f90\u289c\u289c\u3f80\u3f80\u3f80\u0298\u0298\u6089\u6109\u6189"
+ + "\u6209\u6289\u6309\u6389\u6409\u6489\u6509\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u4786\u3b05\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3f80\u3f80\u3f80\u3b05\u3b05\u3f80\u3f80\u3f80\u3b05\u3b05\u3b05"
+ + "\u3f80\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80"
+ + "\u3b05\u3b05\u3b05\u3f80\u3f80\u3f80\u5582\u5582\u5582\u5582\u5582"
+ + "\u5582\u5582\u5582\u5582\u5582\u5582\u5582\u5582\u5582\u5582\u5582"
+ + "\u2e82\u3f80\u5518\u5614\u3f80\u3f80\u3f80\u3f80\u3f80\u4786\u4786"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u5885\u5885"
+ + "\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885"
+ + "\u5885\u5885\u5885\u6b95\u6c16\u4102\u2902\u2902\u4282\u2902\u2902"
+ + "\u2902\u2902\u4302\u4382\u2902\u2902\u2902\u2902\u2902\u4382\u5790"
+ + "\u5790\u5790\u5790\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u0598\u5818\u289c\u289c\u4e81\u289c\u289c\u289c\u289c\u4e81\u289c"
+ + "\u289c\u2902\u4e81\u4e81\u4e81\u2902\u2902\u4602\u2902\u2902\u2902"
+ + "\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u2902\u2902"
+ + "\u2902\u2902\u4684\u4684\u4684\u4684\u4684\u4684\u4684\u4684\u4684"
+ + "\u4684\u4684\u4684\u4684\u4684\u4684\u4684\u4704\u4704\u4684\u4684"
+ + "\u4684\u4684\u4684\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b"
+ + "\u1a1b\u4684\u1a1b\u5614\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u4684\u4684\u1a1b\u1a1b\u1a1b\u1a1b\u4704\u4704"
+ + "\u4704\u4704\u4704\u4704\u4704\u4704\u4704\u4704\u4684\u4684\u1a1b"
+ + "\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b\u1a1b"
+ + "\u1a1b\u1a1b\u1a1b\u1a1b\u2e82\u7e02\u2e82\u3f80\u2e82\u4a82\u8001"
+ + "\u8001\u8001\u8001\u7f03\u1a1b\u1a1b\u1a1b\u289c\uac8a\uad0a\uad8a"
+ + "\uae0a\uae8a\uaf0a\uaf8a\ub00a\ub08a\u4786\u4786\u4786\u4786\u4786"
+ + "\u4786\u4786\u4786\u3f80\u4786\u4786\u4786\u4786\u4786\u4786\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u3f80\u539c"
+ + "\u539c\u658b\u660b\u668b\u670b\u539c\u539c\u539c\u539c\u539c\u539c"
+ + "\u539c\u539c\u539c\u539c\u539c\u289c\u0c99\u289c\u289c\u289c\u289c"
+ + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u3f80\u289c\u3f80"
+ + "\u289c\u289c\u289c\u289c\u3f80\u289c\u289c\u289c\u289c\u3f80\u3f80"
+ + "\u289c\u289c\u289c\u289c\u289c\u539c\u289c\u289c\u289c\u289c\u289c"
+ + "\u0c99\u0c99\u0c99\u0c99\u0c99\u6b95\u6c16\u0298\u289c\u289c\u289c"
+ + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u3f80\u289c\u289c\u289c"
+ + "\u289c\u289c\u289c\u289c\u0455\u04d6\u0455\u04d6\u0455\u04d6\u0455"
+ + "\u04d6\u738b\u740b\u748b\u750b\u758b\u760b\u768b\u770b\u778b\uab8b"
+ + "\u738b\u740b\u748b\u750b\u758b\u760b\u4786\u4786\u4786\u4786\u4786"
+ + "\u4786\u4786\u4786\u3f80\u3f80\u3f80\u3f80\u3f80\u4786\u4786\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786"
+ + "\u6008\u6008\u3f80\u3f80\u3f80\u6008\u6008\u6008\u3f80\u6008\u6008"
+ + "\u6008\u4786\u3f80\u3f80\u4786\u6008\u6008\u3f80\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80\u3b05\u3b05\u3b05\u3f80"
+ + "\u3b05\u3f80\u3b05\u3f80\u3f80\u3b05\u3b05\u3f80\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3f80\u3b05\u3b05\u3f80\u6008\u4786\u4786\u4786\u4786"
+ + "\u3f80\u3f80\u6008\u6008\u3f80\u3f80\u6008\u6008\u4786\u3f80\u3f80"
+ + "\u5002\u5082\u5102\u2902\u5181\u5202\u0c99\u3001\u3082\u5281\u3001"
+ + "\u3082\u3f80\u3f80\u3f80\u3f80\u1a1b\u1a1b\u4881\u0298\u4901\u4901"
+ + "\u4901\u3f80\u4981\u3f80\u4a01\u4a01\u2e01\u2e01\u3f80\u2e01\u2e01"
+ + "\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u2e01\u4b02\u4b82\u4b82\u4b82"
+ + "\u2f02\u2f02\u4c02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02\u2f02"
+ + "\u2f02\u4c82\u4d02\u4d02\u3f80\u4786\u4786\u6008\u3f80\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80\u3f80\u3f80\u3b05\u3b05\u3b05"
+ + "\u3b05\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3f80\u3b05\u3f80\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80"
+ + "\u4786\u3b05\u6008\u6008\u4786\u6008\u6008\u6008\u6008\u6008\u6008"
+ + "\u4786\u4786\u4786\u3f80\u3f80\u3f80\u3f80\u5301\u5301\u5301\u5301"
+ + "\u5301\u5301\u5301\u5301\u5301\u5301\u5301\u5301\u5301\u5301\u5301"
+ + "\u5301\u5082\u5082\u5082\u5082\u5082\u5082\u5082\u5082\u5082\u5082"
+ + "\u5082\u5082\u5082\u5082\u5082\u5082\u4e81\u3001\u3082\u3001\u3082"
+ + "\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3001\u3082\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u6089\u6109\u6189\u6209\u6289\u6309"
+ + "\u6389\u6409\u6489\u6509\u6b0b\u6b0b\u6b0b\u6b0b\u6b0b\u6b0b\u539c"
+ + "\u4786\u539c\u4786\u539c\u4786\u6b95\u6c16\u6b95\u6c16\u6008\u6008"
+ + "\u4786\u4786\u4786\u3f80\u4786\u3f80\u6008\u6008\u6008\u6008\u6008"
+ + "\u6008\u6008\u6008\u4786\u6008\u6008\u4786\u4786\u4786\u4786\u4786"
+ + "\u4786\u4786\u4786\u6008\u6008\u6008\u6008\u4786\u3f80\u3f80\u5518"
+ + "\u5518\u5518\u5518\u5518\u5518\u5518\u5518\u6109\u6189\u6209\u6289"
+ + "\u6309\u6389\u6409\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786"
+ + "\u4786\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u2e82\u2e82\u2e82\u2e82\u2e82\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u5705\u4786\u5705\u5705\u3f80\u5705\u5705\u3f80\u5705\u5705"
+ + "\u5705\u5705\u5705\u5705\u5705\u5705\u5705\u5705\u5705\u5705\u5705"
+ + "\u5705\u5705\u5705\u3f80\u3f80\u3f80\u3f80\u3f80\u6008\u6008\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3b05\u3f80\u3b05\u3b05\u3f80"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80\u4786\u3b05\u6008\u4786"
+ + "\u4786\u4786\u4786\u4786\u3f80\u4786\u4786\u6008\u3f80\u6008\u6008"
+ + "\u4786\u3f80\u3f80\u0298\u0298\u0318\u039a\u0318\u0298\u0298\u0455"
+ + "\u04d6\u0298\u0519\u0598\u0614\u0598\u0698\u5705\u5705\u5705\u5698"
+ + "\u5698\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u6008\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u2d8b"
+ + "\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b\u2d8b"
+ + "\u738b\u5989\u5a09\u5a89\u5b09\u5b89\u5c09\u5c89\u5d09\u5d89\u5e09"
+ + "\u0318\u5e98\u5e98\u5818\u5885\u5885\u5885\u5885\u5818\u5885\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u4786\u5790\u5407\u4786\u5407\u5407"
+ + "\u5407\u4786\u4786\u4786\u4786\u4786\u4786\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u5818\u3f80\u3f80\u3f80\u5818\u5818\u5818\u5818\u5818\u5818"
+ + "\u5818\u5818\u5818\u5818\u5818\u5818\u5818\u5818\u3f80\u5f90\u5904"
+ + "\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u3f80"
+ + "\u3f80\u5885\u5885\u5885\u5885\u5885\u3f80\u5885\u5885\u5885\u5885"
+ + "\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u6109"
+ + "\u6189\u6209\u6289\u6309\u6389\u6409\u6489\u6509\u688b\u6c8b\u6d0b"
+ + "\u6d8b\u6e0b\u6e8b\u6f0b\u6f8b\u700b\u690b\u708b\u3f80\u3f80\u3f80"
+ + "\u0709\u0789\u0809\u0889\u0909\u0989\u0a09\u0a89\u0b09\u0b89\u5885"
+ + "\u5885\u5885\u5f1c\u5f1c\u5885\u4786\u5885\u5885\u5885\u5885\u5885"
+ + "\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u3f80"
+ + "\u3f80\u5f90\u5f90\u5f90\u5f90\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u5f90\u5f90\u5f90\u5f90\u5f90\u5f90\u4786\u4786\u4786\u4786\u4786"
+ + "\u5904\u5904\u4786\u4786\u289c\u4786\u4786\u4786\u4786\u5885\u5885"
+ + "\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\u5885\uc51a"
+ + "\u289c\u3f80\u3f80\u4786\u5885\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u04d6\u0298\u0455"
+ + "\u04d6\u0298\u1a97\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3f80\u3f80\u3f80\u3f80\u6008\u6008\u3f80\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3f80\u3f80\u3f80\u3f80\u4786\u4786\u6008\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u6b95\u6c16"
+ + "\u3f80\u3f80\u3f80\u020c\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u1a97\u4684\u4684\u4684\u3b05\u3b05\u3b05\u4684\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3f80\u3f80\u4786\u3b05\u6008\u6008\u6008\u6008"
+ + "\u6008\u3f80\u6a06\u6008\u6008\u3f80\u6008\u6008\u4786\u4786\u3f80"
+ + "\u3f80\u3f80\u3f80\u4786\u4786\u3f80\u3f80\u4786\u4786\u4786\u3f80"
+ + "\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80\u4786"
+ + "\u4786\u1a1b\u1a1b\u4684\u4684\u3b05\u4786\u4786\u4786\u4786\u3f80"
+ + "\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3f80\u3f80\u5518\u3f80\u3f80\u3f80\u3f80\u3b05\u3b05\u4786\u4786"
+ + "\u5518\u5518\u6089\u6109\u6189\u6209\u6289\u6309\u6389\u6409\u6489"
+ + "\u6509\u5518\u5518\u3f80\u3f80\u3f80\u3f80\u3b05\u3b05\u4786\u4786"
+ + "\u3f80\u3f80\u6089\u6109\u6189\u6209\u6289\u6309\u6389\u6409\u6489"
+ + "\u6509\u3f80\u3f80\u3b05\u3b05\u3f80\u3f80\u3b05\u3b05\u039a\u039a"
+ + "\u658b\u660b\u668b\u670b\u678b\u680b\u539c\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u4786\u4786\u3b05\u3b05\u3b05\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3b05\u4786\u3b05\u3b05\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u4786\u3f80\u3f80\u3f80\u3f80\u039a"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u4684\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u5518\u4786\u4786\u3b05"
+ + "\u3b05\u3b05\u3b05\u3f80\u3f80\u3f80\u3f80\u6089\u6109\u6189\u6209"
+ + "\u6289\u6309\u6389\u6409\u6489\u6509\u5518\u5518\u5518\u5518\u5518"
+ + "\u5518\u688b\u690b\u698b\u289c\u289c\u289c\u289c\u289c\u289c\u039a"
+ + "\u289c\u3f80\u3f80\u3f80\u3f80\u3f80\u4786\u6008\u6008\u6008\u6008"
+ + "\u3f80\u4786\u4786\u4786\u3f80\u4786\u4786\u4786\u4786\u3f80\u3f80"
+ + "\u3b05\u3b05\u3b05\u3b05\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80"
+ + "\u3f80\u4786\u3b05\u6008\u6a06\u6008\u4786\u4786\u4786\u3f80\u3f80"
+ + "\u6008\u6008\u6008\u3f80\u6008\u6008\u6008\u4786\u3f80\u3f80\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80\u3f80\u4786\u3f80"
+ + "\u3f80\u3f80\u3f80\u6008\u6008\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u5518\u5518\u5518\u710a\u718a"
+ + "\u3b05\u4786\u3b05\u3b05\u4786\u4786\u4786\u4786\u4786\u4786\u3f80"
+ + "\u4786\u4786\u3b05\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80"
+ + "\u4684\u3f80\u4786\u4786\u4786\u4786\u4786\u4786\u3f80\u3f80\u3b05"
+ + "\u539c\u539c\u539c\u5518\u5518\u5518\u5518\u5518\u5518\u5518\u5518"
+ + "\u6ab8\u5518\u5518\u5518\u4786\u6008\u4786\u3f80\u3f80\u3f80\u4786"
+ + "\u4786\u6008\u4786\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3b05\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u6008\u6008\u4786\u4786\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u4e81\u4e81\u289c\u4e81\u2902\u3b05\u3b05\u3b05"
+ + "\u3b05\u2902\u289c\u289c\u3f80\u2902\u4e81\u4e81\u4e81\u4e81\u4e81"
+ + "\u4e81\u4e81\u4e81\u4e81\u4e81\u4e81\u4e81\u4e81\u4e81\u4e81\u4e81"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3b05"
+ + "\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u720a"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3b05\u3b05\u4786\u4786\u4786\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3b05\u3b05"
+ + "\u4786\u4786\u4786\u5518\u5518\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3b05\u3b05\u4786\u4786\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3b05\u3f80\u4786"
+ + "\u4786\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3b05\u3b05\u3b05\u3b05\u7290\u7290\u6008\u4786\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u6008\u6008\u6008\u6008\u4786\u4786"
+ + "\u7808\u7808\u7808\u3f80\u3f80\u3f80\u3f80\u4786\u4786\u4786\u4786"
+ + "\u5518\u5518\u5518\u4684\u5518\u5518\u5518\u039a\u3b05\u4786\u3f80"
+ + "\u3f80\ua90b\ua98b\uaa0b\uaa8b\uab0b\u738b\u740b\u748b\u750b\u758b"
+ + "\u760b\u768b\u770b\u778b\uab8b\u730b\u738b\u740b\u748b\u750b\u758b"
+ + "\u760b\u768b\u770b\u778b\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u0298"
+ + "\u0298\u0298\u0298\u0298\u0298\u5614\u0298\u0298\u0298\u0298\u4786"
+ + "\u4786\u4786\u020c\u3f80\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05\u3b05"
+ + "\u3b05\u3b05\u4786\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u4e81\u4e81"
+ + "\u4e81\u2902\u289c\u4e81\u289c\u289c\u289c\u4e81\u4e81\u4e81\u4e81"
+ + "\u4e81\u289c\u289c\u0c99\u289c\u0c99\u289c\u289c\u289c\u289c\u289c"
+ "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u0c99\u289c\u289c\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u948a"
- + "\u950a\u958a\u960a\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u0c99\u0c99\u0c99\u0c99\u0c99\u289c\u289c"
- + "\u289c\u289c\u289c\u0c99\u0c99\u289c\u289c\u289c\u289c\u4d01\u289c"
- + "\u8281\u289c\u4d01\u289c\u8301\u8381\u4d01\u4d01\u2a9c\u2902\u4d01"
- + "\u4d01\u289c\u4d01\u2902\u3a85\u3a85\u3a85\u3a85\u2902\u289c\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u848a\u850a\u858a\u860a\u868a\u870a\u878a"
- + "\u880a\u888a\u890a\u898a\u8a0a\u8a8a\u8b0a\u8b8a\u8c0a\u8c8a\u8d0a"
- + "\u8d8a\u8e0a\u8e8a\u8f0a\u8f8a\u900a\u908a\u910a\u918a\u920a\u928a"
- + "\u930a\u938a\u940a\u0c99\u0c99\u0c59\u0c59\u0c99\u0c99\u0c59\u0c59"
+ + "\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99"
+ + "\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59"
+ + "\u0c99\u0c99\u0455\u04d6\u0c99\u0c99\u0c99\u0455\u04d6\u0455\u04d6"
+ + "\u0455\u04d6\u0455\u04d6\u0455\u04d6\u0455\u04d6\u0455\u04d6\u0c99"
+ + "\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99"
+ + "\u0c59\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99"
+ + "\u0c99\u0c99\u0c99\u0c59\u0c99\u0c59\u0c99\u0c59\u0c59\u0c59\u0c59"
+ + "\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59"
+ + "\u0c59\u0c59\u0c59\u0c99\u0c59\u0c99\u0c59\u0c59\u0c59\u0c99\u0c99"
+ + "\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59\u0c99\u0c99"
+ + "\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c59\u0c99\u0c99\u0c59"
+ + "\u0c59\u0c99\u0c99\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59"
+ + "\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c59\u0c99"
+ + "\u0c59\u0c99\u0c99\u0c59\u0c99\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99"
+ + "\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c59"
+ + "\u0c99\u0c99\u0c99\u0c99\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99"
+ + "\u0c99\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59\u0c99"
+ + "\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59\u0c99\u0c99\u0c99"
+ + "\u0c99\u0c99\u0c99\u0c99\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99"
+ + "\u0c99\u0c99\u289c\u289c\u289c\u289c\u289c\u0c99\u0c99\u289c\u289c"
+ + "\u289c\u289c\u4e81\u289c\u8c81\u289c\u4e81\u289c\u8d01\u8d81\u4e81"
+ + "\u4e81\u2a9c\u2902\u4684\u4684\u2902\u2902\u2902\u2902\u2902\u2902"
+ + "\u2902\u2902\u2902\u2902\u3f80\u3f80\u3f80\u3f80\u7902\u7902\u7902"
+ + "\u7902\u7902\u7902\u7902\u7902\u7981\u7981\u7981\u7981\u7981\u7981"
+ + "\u7981\u7981\u7902\u7902\u7902\u7902\u7902\u7902\u3f80\u3f80\u7981"
+ + "\u7981\u7981\u7981\u7981\u7981\u3f80\u3f80\u2e82\u7902\u4a82\u7902"
+ + "\u4a82\u7902\u4a82\u7902\u3f80\u7981\u3f80\u7981\u3f80\u7981\u3f80"
+ + "\u7981\u7a02\u7a02\u7a82\u7a82\u7a82\u7a82\u7b02\u7b02\u7b82\u7b82"
+ + "\u7c02\u7c02\u7c82\u7c82\u3f80\u3f80\u7d02\u7d02\u7d02\u7d02\u7d02"
+ + "\u7d02\u7d02\u7d02\u7d83\u7d83\u7d83\u7d83\u7d83\u7d83\u7d83\u7d83"
+ + "\u7902\u7902\u2e82\u7e02\u2e82\u3f80\u2e82\u4a82\u7981\u7981\u7e81"
+ + "\u7e81\u7f03\u1a1b\u7f82\u1a1b\u7902\u7902\u4a82\u4a82\u3f80\u3f80"
+ + "\u2e82\u4a82\u7981\u7981\u8081\u8081\u3f80\u1a1b\u1a1b\u1a1b\u7902"
+ + "\u7902\u4a82\u4a82\u2e82\u5102\u2e82\u4a82\u7981\u7981\u8101\u8101"
+ + "\u5281\u1a1b\u1a1b\u1a1b\u020c\u020c\u020c\u020c\u020c\u020c\u020c"
+ + "\u82ac\u020c\u020c\u020c\u830c\u5f90\u5f90\u7290\u8390\u5614\u8434"
+ + "\u5614\u5614\u5614\u5614\u0298\u0298\u849d\u851e\u6b95\u849d\u849d"
+ + "\u851e\u6b95\u849d\u0598\u0298\u0598\u3f80\u0298\u0598\u0298\u0298"
+ + "\u5614\u6b95\u6c16\u6b95\u6c16\u6b95\u6c16\u0318\u0318\u0318\u0318"
+ + "\u0318\u0298\u0298\u0298\u0298\u29dd\u2d5e\u0298\u0298\u0298\u0298"
+ + "\u1a97\u890b\u2902\u3f80\u3f80\u898b\u8a0b\u8a8b\u8b0b\u8b8b\u8c0b"
+ + "\u0519\u0519\u0c99\u0455\u04d6\u2902\u890b\u2c8b\u2b0b\u2b8b\u898b"
+ + "\u8a0b\u8a8b\u8b0b\u8b8b\u8c0b\u0519\u0519\u0c99\u0455\u04d6\u3f80"
+ + "\u039a\u039a\u039a\u039a\u039a\u039a\u039a\u039a\u039a\u039a\u039a"
+ + "\u039a\u039a\u039a\u039a\u039a\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u4786\u4786\u4786"
+ + "\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u4786\u5407"
+ + "\u5407\u5407\u0c99\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99"
+ + "\u0c99\u0c99\u0c99\u0c59\u0c59\u0c59\u0c99\u0c99\u0c59\u0c59\u0c59"
+ + "\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59"
+ + "\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59\u0c59"
+ + "\u0c59\u0c99\u0c99\u0c59\u0c59\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59"
+ "\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59"
- + "\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99"
- + "\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99\u0c99"
- + "\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c59\u0c59"
- + "\u0c99\u0c99\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59"
- + "\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c59\u0c59\u0c59"
- + "\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59\u0c99\u0c99\u0c99\u0c99"
- + "\u0c99\u0c99\u0c99\u289c\u289c\u0c99\u289c\u289c\u0c99\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u0c99\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u3e80\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u0c99\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c59\u0c59\u0c59"
- + "\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c59\u0519\u0519\u0c99\u0c59"
+ + "\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59\u0c59\u0c99\u0c99\u0c99"
+ + "\u0c99\u0c59\u0c59\u0c59\u0c59\u0c99\u0c59\u0519\u0519\u0c99\u0c59"
+ "\u0c59\u0c99\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59\u0c99\u0c59\u0c99"
+ "\u0c59\u0c99\u0c99\u0c99\u0c99\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59"
- + "\u0c59\u0c59\u0c59\u0c99\u0c99\u0c99\u0c99\u0c99\u0c59\u0c99\u0c59"
- + "\u0c59\u0c59\u0c59\u0c59\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u0455\u04d6\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u3e80\u3e80\u3e80\u3e80\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u9c1c\u9c1c\u9c1c\u9c1c"
- + "\u9c1c\u9c1c\u9c1c\u9c1c\u9c1c\u9c1c\u9c1c\u9c1c\u9c1c\u9c1c\u9c1c"
- + "\u9c1c\u9c9c\u9c9c\u9c9c\u9c9c\u9c9c\u9c9c\u9c9c\u9c9c\u9c9c\u9c9c"
- + "\u9c9c\u9c9c\u9c9c\u9c9c\u9c9c\u9c9c\u7f0b\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u0c59\u0c99\u0c59\u0c99\u0c59"
- + "\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c59\u0c59"
- + "\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59"
- + "\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c99\u0c59\u0c59\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u039a\u039a\u0c99\u1a1b\u289c\u039a\u039a\u3e80\u289c\u0c99"
- + "\u0c99\u0c99\u0c99\u289c\u289c\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u5b10\u5b10\u5b10\u289c\u289c\u3e80\u3e80"
+ + "\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c59\u0c99\u0c59\u0c59\u0c99"
+ + "\u0c99\u0455\u04d6\u0455\u04d6\u0c59\u0c99\u0c99\u0c99\u0c99\u4e81"
+ + "\u2902\u2902\u2902\u2902\u289c\u0c99\u3f80\u3f80\u3f80\u3f80\u8e0a"
+ + "\u8e8a\u8f0a\u8f8a\u900a\u908a\u910a\u918a\u920a\u928a\u930a\u938a"
+ + "\u940a\u948a\u950a\u958a\u960a\u968a\u970a\u978a\u980a\u988a\u990a"
+ + "\u998a\u9a0a\u9a8a\u9b0a\u9b8a\u9c0a\u9c8a\u9d0a\u9d8a\u9e0a\u9e8a"
+ + "\u9f0a\u9f8a\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u0c99\u289c\u289c\u0c99\u289c\u289c\u0c99\u289c"
+ + "\u289c\u289c\u289c\u289c\u289c\u289c\u0c99\u289c\u289c\u289c\u289c"
+ + "\u289c\u289c\u289c\u289c\u0c59\u0c59\u0c59\u0c59\u289c\u289c\u289c"
+ + "\u289c\u289c\u289c\u289c\u0455\u04d6\u289c\u289c\u289c\u289c\u289c"
+ + "\u289c\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c"
+ + "\u539c\u539c\u539c\u539c\u539c\u539c\u289c\u289c\u3f80\u539c\ubc8b"
+ + "\ubd0b\ubd8b\ube0b\ube8b\ubf0b\ubf8b\uc00b\uc08b\uc10b\uc18b\uc20b"
+ + "\uc28b\uc30b\uc38b\u768b\u770b\u778b\uab8b\u289c\u3f80\u3f80\u3f80"
+ "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u3e80\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u3e80\u289c"
- + "\u3e80\u289c\u289c\u289c\u289c\u3e80\u3e80\u3e80\u289c\u3e80\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u840b\u9d0b"
- + "\u9d8b\u9e0b\u9e8b\u9f0b\u9f8b\ua00b\ua08b\ua10b\u840b\u9d0b\u9d8b"
- + "\u9e0b\u9e8b\u9f0b\u9f8b\ua00b\ua08b\ua10b\u289c\u3e80\u3e80\u3e80"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u0c59\u0c59\u0c59"
- + "\u0c59\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u289c"
- + "\u501c\u289c\u289c\u289c\u289c\u289c\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u630b\u630b\u630b\u630b\u630b\u630b\u630b\u630b\u630b\u630b\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u3e80\u3e80"
- + "\u3e80\u501c\u610b\u618b\u620b\u628b\ua80b\ua88b\ua90b\ua98b\uaa0b"
- + "\u640b\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u289c\u3e80\u289c\u289c\u289c"
- + "\u3e80\u289c\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u2c8b\u2b0b\u2b8b\u7f8b\u800b\u808b"
- + "\u810b\u818b\u820b\u968b\u970b\u978b\u980b\u988b\u990b\u998b\u9a0b"
- + "\u9a8b\u9b0b\u9b8b\u2c8b\u2b0b\u2b8b\u7f8b\u800b\u808b\u810b\u818b"
- + "\u820b\u968b\u970b\u978b\u980b\u988b\u990b\u998b\u9a0b\u9a8b\u9b0b"
- + "\u9b8b\u501c\u501c\u501c\u501c\u020c\u0298\u0298\u0298\u289c\u4584"
- + "\u3a85\ua18a\u0455\u04d6\u0455\u04d6\u0455\u04d6\u0455\u04d6\u0455"
- + "\u04d6\u289c\u289c\u0455\u04d6\u0455\u04d6\u0455\u04d6\u0455\u04d6"
- + "\u2a14\u6615\u6696\u6696\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3e80\u3e80\u3e80\u3e80\u4606\u4606\u1a1b\u1a1b"
- + "\u4584\u4584\u3e80\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85"
- + "\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3a85\u3e80\u501c\u501c\u630b"
- + "\u630b\u630b\u630b\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c"
- + "\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u501c\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93"
- + "\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93"
- + "\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93\uaa93"
- + "\uaa93\uaa93\uaa93\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12"
- + "\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12"
- + "\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12\uab12"
- + "\uab12\uab12\u5305\u5305\u5305\u5305\u5305\u5305\u5305\u5305\u5305"
- + "\u0519\u5305\u5305\u5305\u5305\u5305\u5305\u5305\u5305\u5305\u5305"
- + "\u5305\u5305\u5305\u3e80\u5305\u5305\u5305\u5305\u5305\u3e80\u5305"
- + "\u3e80\u4606\u4606\u4606\u4606\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80"
- + "\u3e80\u3e80\u3e80\u3e80\u3e80\u3e80\u0298\u2a14\u2a14\u1a97\u1a97"
- + "\u6615\u6696\u6615\u6696\u6615\u6696\u6615\u6696\u6615\u6696\u6615"
- + "\u6696\u3e80\u3e80\u3e80\u3e80\u0298\u0298\u0298\u0298\u1a97\u1a97"
- + "\u1a97\u0598\u0298\u0598\u3e80\u0298\u0598\u0298\u0298\u2a14\u6615"
- + "\u6696\u6615\u6696\u6615\u6696\u0318\u0298\u0d01\u0d81\u0e01\u0e81"
- + "\u0f01\u0f81\u1001\u1081\u1101\u1181\u1201\u1281\u1301\u1381\u1401"
- + "\u1481\u1501\u1581\u1601\u1681\u1701\u1781\u1801\u1881\u1901\u1981"
- + "\u6615\u0298\u6696\u1a1b\u1a97";
+ + "\u289c\u289c\u289c\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\ua18b\ua20b\ua28b\ua30b"
+ + "\ua38b\ua40b\ua48b\ua50b\u2c8b\u2b0b\u2b8b\u898b\u8a0b\u8a8b\u8b0b"
+ + "\u8b8b\u8c0b\ua00b\ua08b\ua10b\ua18b\ua20b\ua28b\ua30b\ua38b\ua40b"
+ + "\ua48b\ua50b\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c"
+ + "\u539c\u539c\u539c\u289c\u289c\u289c\u289c\u539c\u539c\u539c\u539c"
+ + "\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c\u539c"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80"
+ + "\u3f80\u658b\u660b\u668b\u670b\ub28b\ub30b\ub38b\ub40b\ub48b\u688b"
+ + "\u539c\u539c\u539c\u539c\u539c\u539c\ua59c\ua59c\ua59c\ua59c\ua59c"
+ + "\ua59c\ua59c\ua59c\ua59c\ua59c\ua59c\ua59c\ua59c\ua59c\ua59c\ua59c"
+ + "\ua61c\ua61c\ua61c\ua61c\ua61c\ua61c\ua61c\ua61c\ua61c\ua61c\ua61c"
+ + "\ua61c\ua61c\ua61c\ua61c\ua61c\u890b\ua68b\ua70b\ua78b\ua80b\ua88b"
+ + "\u5614\u4684\u4684\u4684\u4684\u4684\u289c\u289c\ub10a\ub18a\ub20a"
+ + "\u4684\u3b05\u0298\u289c\u289c\u289c\u3f80\u3f80\u3f80\u289c\u3f80"
+ + "\u289c\u289c\u289c\u289c\u289c\u289c\u289c\u3f80\u0c99\u0c99\u0c59"
+ + "\u0c59\u0c59\u0c59\u0455\u04d6\u0455\u04d6\u0455\u04d6\u3f80\u3f80"
+ + "\u3f80\u3f80\u020c\u0298\u0298\u0298\u289c\u4684\u3b05\uac0a\u0455"
+ + "\u04d6\u0455\u04d6\u0455\u04d6\u0455\u04d6\u289c\u289c\u0455\u04d6"
+ + "\u0455\u04d6\u0455\u04d6\u0455\u04d6\u5614\u6b95\u6c16\u6c16\u289c"
+ + "\ub50b\ub58b\ub60b\ub68b\ub70b\ub78b\ub80b\ub88b\ub90b\ub98b\uba0b"
+ + "\uba8b\ubb0b\ubb8b\ubc0b\uc413\uc413\uc413\uc413\uc413\uc413\uc413"
+ + "\uc413\uc413\uc413\uc413\uc413\uc413\uc413\uc413\uc413\uc492\uc492"
+ + "\uc492\uc492\uc492\uc492\uc492\uc492\uc492\uc492\uc492\uc492\uc492"
+ + "\uc492\uc492\uc492\u2e82\u2e82\u2e82\u4a82\u4a82\u2e82\u2e82\u3f80"
+ + "\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u3f80\u5705\u5705\u5705"
+ + "\u5705\u5705\u5705\u5705\u5705\u5705\u0519\u5705\u5705\u5705\u5705"
+ + "\u5705\u5705\u5705\u3f80\u5705\u5705\u5705\u5705\u5705\u3f80\u5705"
+ + "\u3f80\u0298\u5614\u5614\u1a97\u1a97\u6b95\u6c16\u6b95\u6c16\u6b95"
+ + "\u6c16\u6b95\u6c16\u6b95\u6c16\u6b95\u6c16\u0298\u0298\u6b95\u6c16"
+ + "\u0298\u0298\u0298\u0298\u1a97\u1a97\u1a97\u0298\u0298\u0519\u0614"
+ + "\u0c99\u0c99\u0c99\u3f80\u0298\u039a\u0318\u0298\u3f80\u3f80\u3f80"
+ + "\u3f80\u2282\u2302\u2382\u2402\u2482\u2502\u2582\u2602\u2682\u2702"
+ + "\u2782\u0455\u0c99\u04d6\u0c99\u0455\u039a\u039a\u0c99\u1a1b\u289c"
+ + "\u039a\u039a\u3f80\u289c\u0c99\u0c99\u0c99\u0c99\u289c\u289c\u3f80",
+
+ "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\u0080\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\u0080\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\u0080\005\005\u0080\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\u0080\u0080\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u1981\u1981\u1981\u1981\u1981"
+ + "\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981"
+ + "\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981"
+ + "\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981\u1981"
+ + "\u1981\u1981\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02"
+ + "\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02\u1a02"
+ + "\u1a02\u1a02\u1a02\u1a02\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\u0080\u0080\u0080\u0080\u0080\u0118\u0198\u021c\u0080"
+ + "\u0080\u0080\u0080\u028b\u030b\u038b\u040b\u048b\u050b\u058b\u060b"
+ + "\u068b\u070b\u078b\u080b\u088b\u090b\u098b\u0a0b\u0a8b\u0b0b\u0b8b"
+ + "\u0c0b\u0c8b\u0d0b\u0d8b\u0e0b\u0e8b\u0f0b\u0f8b\u100b\u108b\u110b"
+ + "\u118b\u120b\u128b\u130b\u138b\u140b\u148b\u150b\u158b\u160b\u168b"
+ + "\u170b\u178b\u180b\u188b\u0080\u0080\u0080\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u2008\u2008\u2086\u2086\u2086\u021c\u021c\u021c\u2008\u2008\u2008"
+ + "\u2008\u2008\u2008\u2110\u2110\u2110\u2110\u2110\u2110\u2110\u2110"
+ + "\u2086\u2086\u2086\u2086\u2086\u021c\u021c\u2086\u2086\u2086\u2086"
+ + "\u2086\u2086\u2086\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u2086\u2086\u2086\u2086\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u0080"
+ + "\u0080\u0080\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c\u021c"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\005\005\005\005\005\005\005\005\005\005"
+ + "\u190a\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\u0080\u028b\u048b"
+ + "\u070b\u090b\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\u0080\u0118\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\u0080\u0080"
+ + "\u1a89\u1b09\u1b89\u1c09\u1c89\u1d09\u1d89\u1e09\u1e89\u1f09\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u1f85"
+ + "\u1f85\u1f85\u1f85\u1f85\u1f85\u0080\u0080\u1f85\u0080\u1f85\u1f85"
+ + "\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85"
+ + "\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85"
+ + "\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85"
+ + "\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u1f85\u0080\u1f85"
+ + "\u1f85\u0080\u0080\u0080\u1f85\u0080\u0080\u1f85\u219c\u219c\u219c"
+ + "\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c"
+ + "\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c"
+ + "\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c"
+ + "\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c"
+ + "\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c\u219c"
+ + "\u219c\u219c\u219c\u219c\u219c\u219c\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u2201\u2319\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2319\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2319\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u0080\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u0080\u0080\u0080\u0080\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u0080\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u0080\u2201\u0080\u0080\u0080\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u0080\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2201\u0080\u2201\u2201\u0080\u0080\u2201\u0080\u0080\u2201"
+ + "\u2201\u0080\u0080\u2201\u2201\u2201\u2201\u0080\u2201\u2201\u2201"
+ + "\u2201\u2201\u2201\u2201\u2201\u2282\u2282\u2282\u2282\u0080\u2282"
+ + "\u0080\u2282\u2282\u2282\u2282\u2201\u2201\u0080\u2201\u2201\u2201"
+ + "\u2201\u0080\u0080\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u2201"
+ + "\u0080\u2201\u2201\u2201\u2201\u2201\u2201\u2201\u0080\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282\u2282"
+ + "\u2282\u2282\u2201\u2201\u0080\u2201\u2201\u2201\u2201\u0080\u2282"
+ + "\u2282\u2282\u2319\u2282\u2282\u2282\u2282\u2282\u2282\u0080\u0080"
+ + "\u0080\u0080\u2389\u2409\u2489\u2509\u2589\u2609\u2689\u2709\u2789"
+ + "\u2809\u2389\u2409\u2489\u2509\u2589\u2609\u2689\u2709\u2789\u2809"
+ + "\u2389\u2409\u2489\u2509\u2589\u2609\u2689\u2709\u2789\u2809\u2389"
+ + "\u2409\u2489\u2509\u2589\u2609\u2689\u2709\u2789\u2809\u2389\u2409"
+ + "\u2489\u2509\u2589\u2609\u2689\u2709\u2789\u2809",
+
+ "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\005\005\005\005"
+ + "\005\005\005\005\005\005\005\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080"
+ + "\u0080\u0080\u0080",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106\u0106"
+ + "\u0106\u0106\u0106\u0106\u0106\u0106\u0106\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\u0090\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090"
+ + "\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090"
+ + "\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090"
+ + "\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090"
+ + "\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090"
+ + "\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090"
+ + "\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090"
+ + "\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090"
+ + "\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090",
+
+ "",
+
+ ""};
/**
* This is the attribute table for computing the numeric value of a
@@ -780,8 +1296,8 @@ public interface CharData
* Note that this is a signed value, but stored as an unsigned char
* since this is a String literal.
*/
- String NUM_VALUE
- = "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff"
+ String[] NUM_VALUE = new String[]{
+ "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff"
+ "\uffff\uffff\uffff\000\001\002\003\004\005\006\007"
+ "\010\011\uffff\uffff\012\013\014\015\016\017\020"
+ "\021\022\023\024\025\026\027\030\031\032\033"
@@ -796,23 +1312,66 @@ public interface CharData
+ "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff"
+ "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff"
+ "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff"
- + "\uffff\uffff\uffff\uffff\uffff\000\001\002\003\004\005"
- + "\006\007\010\011\uffff\uffff\uffff\uffff\000\001\002"
- + "\003\004\005\006\007\010\011\001\002\003\004"
- + "\uffff\020\012d\u03e8\uffff\uffff\uffff\024\036("
- + "2<FPZ\u2710\021\022\023\uffff\uffff"
+ "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff"
+ + "\uffff\uffff\uffff\000\001\002\003\004\005\006\007"
+ + "\010\011\uffff\uffff\uffff\uffff\000\001\002\003\004"
+ + "\005\006\007\010\011\001\002\003\004\uffff\020"
+ + "\012d\u03e8\uffff\uffff\ufffe\uffff\uffff\024\036("
+ + "2<FPZ\u2710\021\022\023\uffff\000"
+ + "\001\002\003\004\005\006\007\010\011\uffff\uffff"
+ "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff"
+ "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff"
- + "\uffff\000\004\005\006\007\010\011\uffff\uffff\uffff"
- + "\001\001\002\003\004\005\006\007\010\011\012"
- + "\013\0142d\u01f4\u03e8\001\002\003\004\005"
- + "\006\007\010\011\012\013\0142d\u01f4\u03e8"
- + "\u03e8\u1388\u2710\uffff\012\013\014\015\016\017\020"
- + "\021\022\023\024\uffff\uffff\002\003\004\005\006"
- + "\007\010\011\012\000\001\002\003\004\005\006"
- + "\007\010\011\012\024\036\005\006\007\010\011"
- + "\uffff\uffff";
+ + "\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\uffff\000"
+ + "\004\005\006\007\010\011\uffff\uffff\uffff\001\002"
+ + "\003\004\005\006\007\010\011\012\013\0142"
+ + "d\u01f4\u03e8\001\002\003\004\005\006\007\010"
+ + "\011\012\013\0142d\u01f4\u03e8\u03e8\u1388\u2710"
+ + "\uffff\012\013\014\015\016\017\020\021\022\023"
+ + "\024\uffff\uffff\013\014\015\016\017\020\021\022"
+ + "\023\024\012\000\001\002\003\004\005\006\007"
+ + "\010\011\012\024\036\005\006\007\010\011\025"
+ + "\026\027\030\031\032\033\034\035\036\037 "
+ + "!\"#$%&'()*+"
+ + ",-./012\uffff\uffff\uffff",
+
+ "\uffff\uffff\uffff\uffff\uffff\001\002\003\004\005\006"
+ + "\007\010\011\012\024\036(2<FP"
+ + "Zd\u00c8\u012c\u0190\u01f4\u0258\u02bc\u0320\u0384\u03e8"
+ + "\u07d0\u0bb8\u0fa0\u1388\u1770\u1b58\u1f40\u2328\u2710\u4e20\u7530"
+ + "\ufffd\ufffc\ufffb\ufffa\ufff9\ufff8\uffff\uffff\uffff\000\001"
+ + "\002\003\004\005\006\007\010\011\uffff\uffff\uffff"
+ + "\uffff\uffff\uffff\uffff\uffff\000\001\002\003\004\005"
+ + "\006\007\010\011",
+
+ "\uffff\uffff",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "\uffff\uffff\uffff",
+
+ "",
+
+ ""};
/**
* This is the attribute table for computing the single-character uppercase
@@ -822,8 +1381,8 @@ public interface CharData
* capitalizing a String, you must first check if a multi-character uppercase
* sequence exists before using this character.
*/
- String UPPER
- = "\000\000\000\000\000\000\000\000\000\000\000"
+ String[] UPPER = new String[]{
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
@@ -833,28 +1392,71 @@ public interface CharData
+ "\uffe0\uffe0\uffe0\000\000\000\000\000\000\000\000"
+ "\u02e7\000\000\000\000\000\uffe0y\000\uffff\000"
+ "\uff18\000\ufed4\000\000\000\000\000\000\000a"
- + "\000\000\000\000\000\000\000\0008\000\uffff"
- + "\ufffe\uffb1\000\000\000\uff2e\uff32\uff33\uff36\uff35\uff31"
- + "\uff2f\uff2d\uff2b\uff2a\uff26\uff27\uff25\000\000T\000"
- + "\000\000\000\000\uffda\uffdb\uffe1\uffc0\uffc1\uffc2\uffc7"
- + "\000\uffd1\uffca\uffaa\uffb0\000\000\000\000\000\uffd0"
+ + "\000\000\000\u0082\000\000\000\000\0008\000"
+ + "\uffff\ufffe\uffb1\000\000\000\000\uff2e\uff32\uff33\uff36"
+ + "\uff35\uff31\uff2f\uff2d\uff2b\uff2a\uff26\uff27\uff25\000\000"
+ + "\000T\000\000\000\000\000\uffda\uffdb\uffe1\uffc0"
+ + "\uffc1\uffc2\uffc7\000\uffd1\uffca\uffaa\uffb0\007\000\uffa0"
+ + "\000\000\000\000\000\000\uffd0\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\uffc5"
+ + "\010\000JVd\u0080p~\010\000\011"
+ + "\000\000\ue3db\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\uffc5\010"
- + "\000JVd\u0080p~\010\000\011\000"
- + "\000\ue3db\000\000\007\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0"
+ + "\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\ufff0\ufff0\ufff0\ufff0\ufff0"
- + "\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0\ufff0"
+ + "\000\000\uffe6\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\uffe6\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000";
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000",
+
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\uffd8\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000",
+
+ "\000\000",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "\000\000\000",
+
+ "",
+
+ ""};
/**
* This is the attribute table for computing the lowercase representation
@@ -862,34 +1464,82 @@ public interface CharData
* character and its lowercase version. Note that this is stored as an
* unsigned char since this is a String literal.
*/
- String LOWER
- = "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + " "
- + " "
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000 \000\000\000\001\000\uff39\000\uff87\000\u00d2\u00ce"
- + "\u00cdO\u00ca\u00cb\u00cf\000\u00d3\u00d1\u00d5\u00d6\u00da\u00d9\u00db"
- + "\000\000\002\001\000\000\uff9f\uffc8\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000&"
- + "%@?\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000P\000\0000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\ufff8"
- + "\000\000\000\000\000\000\000\ufff8\000\uffb6\ufff7\000\uffaa"
- + "\uff9c\000\uff90\ufff9\uff80\uff82\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\ue2a3\udf41\udfba\000\020\020\020\020\020\020\020\020"
- + "\020\020\020\020\020\020\020\020\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\032\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000";
+ String[] LOWER = new String[]{
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000 "
+ + " "
+ + " \000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000 \000\000\000\001\000\uff39"
+ + "\000\uff87\000\u00d2\u00ce\u00cdO\u00ca\u00cb\u00cf\000"
+ + "\u00d3\u00d1\u00d5\000\u00d6\u00da\u00d9\u00db\000\000\002"
+ + "\001\000\000\uff9f\uffc8\uff7e\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000&%@?\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\uffc4\000"
+ + "\ufff9P\000\0000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\ufff8\000\000\000\000\000\000\000\ufff8\000"
+ + "\uffb6\ufff7\000\uffaa\uff9c\uff90\uff80\uff82\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\ue2a3\udf41\udfba\020\020"
+ + "\020\020\020\020\020\020\020\020\020\020\020"
+ + "\020\020\020\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\032\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000",
+
+ "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000(\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000",
+
+ "\000\000",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "\000\000\000",
+
+ "",
+
+ ""};
/**
* This is the attribute table for computing the directionality class
@@ -903,28 +1553,82 @@ public interface CharData
* when performing the case conversion. Note that this information is stored
* as an unsigned char since this is a String literal.
*/
- String DIRECTION
- = "$,(004\024\02444\024\034\024\020\014\014\014"
- + "\014\014\014\014\014\014\01444\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\00044\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\0344\00044"
- + "\024\014\014\000\01444\000\001\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\ufffc\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000 \000\000\000\000\002\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000 \000\000\000\004\004\010\010\010"
- + "\030\030\030\030\030\030\030\030\030\030\030\010$\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "44\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\001\001\001\000\001\000\000\000\000\000\000"
- + "\000\0000$\000\0044440(8@H<D\014"
- + "\014\014\014\014\014\014\000\000\0004\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\014\014\014\014\014"
- + "\014\014\014\014\014\014\000\000444444444"
- + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
- + "\000\000\000";
+ String[] DIRECTION = new String[]{
+ "$,(004\024\02444\024"
+ + "\034\024\020\014\014\014\014\014\014\014\014"
+ + "\014\01444\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\00044\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\0344\00044\024\014\014"
+ + "\000\01444\000\001\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\ufffc\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\0004"
+ + " \000\000\000\000\002\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000 \000\000\0004\004\004\010"
+ + "\010\010\010\030\030\030\030\030\030\030\030"
+ + "\030\030\030\010$\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\00044\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\0004"
+ + "444444444 \000"
+ + "\000\000\000\000\000\000\000\000\001\001\001"
+ + "\000\001\000\000\000\000\000\0000$\004"
+ + "4440(8@H<D\014"
+ + "\014\014\014\014\014\014\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\014\014\014\014\014\014\014\014\014\014"
+ + "\014\000\00044444444"
+ + "444\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\0004"
+ + "44444444444"
+ + "44444444444"
+ + "4444444\000\000\010",
+
+ "\000\ufffc\0004\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\000\000\000"
+ + "\000\000\000\000\000\000\000\000\004\000 "
+ + "$4\000\000\000\014\014\014\014\014\014"
+ + "\014\014\014\014",
+
+ "\000\ufffc",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "",
+
+ "\ufffc$ ",
+
+ "",
+
+ ""};
/**
* This is the listing of titlecase special cases (all other characters
diff --git a/libjava/classpath/gnu/java/net/CRLFInputStream.java b/libjava/classpath/gnu/java/net/CRLFInputStream.java
index 91fd840b862..ac3482679c5 100644
--- a/libjava/classpath/gnu/java/net/CRLFInputStream.java
+++ b/libjava/classpath/gnu/java/net/CRLFInputStream.java
@@ -1,5 +1,5 @@
/* CRLFInputStream.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,7 +39,6 @@ exception statement from your version. */
package gnu.java.net;
import java.io.BufferedInputStream;
-import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -49,7 +48,7 @@ import java.io.InputStream;
* @author Chris Burdess (dog@gnu.org)
*/
public class CRLFInputStream
- extends FilterInputStream
+ extends InputStream
{
/**
* The CR octet.
@@ -61,6 +60,11 @@ public class CRLFInputStream
*/
public static final int LF = 10;
+ /**
+ * The underlying input stream.
+ */
+ protected InputStream in;
+
private boolean doReset;
/**
@@ -69,7 +73,7 @@ public class CRLFInputStream
*/
public CRLFInputStream(InputStream in)
{
- super(in.markSupported() ? in : new BufferedInputStream(in));
+ this.in = in.markSupported() ? in : new BufferedInputStream(in);
}
/**
@@ -145,13 +149,14 @@ public class CRLFInputStream
throws IOException
{
doReset = false;
- int lm1 = len - 1;
- for (int i = off; i < len; i++)
+ int end = off + len;
+ int em1 = end - 1;
+ for (int i = off; i < end; i++)
{
if (b[i] == CR)
{
int d;
- if (i == lm1)
+ if (i == em1)
{
d = in.read();
doReset = true;
diff --git a/libjava/classpath/gnu/java/net/LineInputStream.java b/libjava/classpath/gnu/java/net/LineInputStream.java
index 81a3c7d1fd4..da307dbddf2 100644
--- a/libjava/classpath/gnu/java/net/LineInputStream.java
+++ b/libjava/classpath/gnu/java/net/LineInputStream.java
@@ -1,5 +1,5 @@
/* LineInputStream.java --
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,7 +40,6 @@ package gnu.java.net;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -50,8 +49,14 @@ import java.io.InputStream;
* @author Chris Burdess (dog@gnu.org)
*/
public class LineInputStream
- extends FilterInputStream
+ extends InputStream
{
+
+ /**
+ * The underlying input stream.
+ */
+ protected InputStream in;
+
/*
* Line buffer.
*/
@@ -88,7 +93,7 @@ public class LineInputStream
*/
public LineInputStream(InputStream in, String encoding)
{
- super(in);
+ this.in = in;
buf = new ByteArrayOutputStream();
this.encoding = encoding;
eof = false;
@@ -96,6 +101,24 @@ public class LineInputStream
blockReads = !(in instanceof BufferedInputStream) && in.markSupported();
}
+ public int read()
+ throws IOException
+ {
+ return in.read();
+ }
+
+ public int read(byte[] buf)
+ throws IOException
+ {
+ return in.read(buf);
+ }
+
+ public int read(byte[] buf, int off, int len)
+ throws IOException
+ {
+ return in.read(buf, off, len);
+ }
+
/**
* Read a line of input.
*/
diff --git a/libjava/classpath/gnu/java/net/protocol/file/Connection.java b/libjava/classpath/gnu/java/net/protocol/file/Connection.java
index 8e4a413667d..f7253b0935b 100644
--- a/libjava/classpath/gnu/java/net/protocol/file/Connection.java
+++ b/libjava/classpath/gnu/java/net/protocol/file/Connection.java
@@ -135,21 +135,18 @@ public class Connection extends URLConnection
* @exception MalformedURLException If the given string contains invalid
* escape sequences.
*
- * Sadly the same as URI.unquote, but there's nothing we can do to
- * make it accessible.
- *
*/
public static String unquote(String str) throws MalformedURLException
{
if (str == null)
return null;
- byte[] buf = new byte[str.length()];
+
+ final int MAX_BYTES_PER_UTF_8_CHAR = 3;
+ byte[] buf = new byte[str.length()*MAX_BYTES_PER_UTF_8_CHAR];
int pos = 0;
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
- if (c > 127)
- throw new MalformedURLException(str + " : Invalid character");
if (c == '%')
{
if (i + 2 >= str.length())
@@ -160,6 +157,15 @@ public class Connection extends URLConnection
throw new MalformedURLException(str + " : Invalid quoted character");
buf[pos++] = (byte) (hi * 16 + lo);
}
+ else if (c > 127) {
+ try {
+ byte [] c_as_bytes = Character.toString(c).getBytes("utf-8");
+ System.arraycopy(c_as_bytes, 0, buf, pos, c_as_bytes.length);
+ }
+ catch (java.io.UnsupportedEncodingException x2) {
+ throw (Error) new InternalError().initCause(x2);
+ }
+ }
else
buf[pos++] = (byte) c;
}
diff --git a/libjava/classpath/gnu/java/net/protocol/ftp/ActiveModeDTP.java b/libjava/classpath/gnu/java/net/protocol/ftp/ActiveModeDTP.java
index 3755e8beb8d..aa3c412b6a1 100644
--- a/libjava/classpath/gnu/java/net/protocol/ftp/ActiveModeDTP.java
+++ b/libjava/classpath/gnu/java/net/protocol/ftp/ActiveModeDTP.java
@@ -84,6 +84,7 @@ final class ActiveModeDTP
}
this.connectionTimeout = connectionTimeout;
acceptThread = new Thread(this, "ActiveModeDTP");
+ acceptThread.setDaemon(true);
acceptThread.start();
}
diff --git a/libjava/classpath/gnu/java/net/protocol/ftp/FTPURLConnection.java b/libjava/classpath/gnu/java/net/protocol/ftp/FTPURLConnection.java
index 62c40f19e04..f937e51f606 100644
--- a/libjava/classpath/gnu/java/net/protocol/ftp/FTPURLConnection.java
+++ b/libjava/classpath/gnu/java/net/protocol/ftp/FTPURLConnection.java
@@ -1,5 +1,5 @@
/* FTPURLConnection.java --
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,10 +38,9 @@ exception statement from your version. */
package gnu.java.net.protocol.ftp;
+import gnu.classpath.SystemProperties;
import gnu.java.net.GetLocalHostAction;
-import gnu.java.security.action.GetPropertyAction;
-import java.io.FileNotFoundException;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
@@ -51,7 +50,6 @@ import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
@@ -113,11 +111,9 @@ public class FTPURLConnection
else
{
username = "anonymous";
- PrivilegedAction a = new GetPropertyAction("user.name");
- String systemUsername =(String) AccessController.doPrivileged(a);
- a = new GetLocalHostAction();
+ GetLocalHostAction a = new GetLocalHostAction();
InetAddress localhost =(InetAddress) AccessController.doPrivileged(a);
- password = systemUsername + "@" +
+ password = SystemProperties.getProperty("user.name") + "@" +
((localhost == null) ? "localhost" : localhost.getHostName());
}
connection = new FTPConnection(host, port);
@@ -167,24 +163,13 @@ public class FTPURLConnection
connect();
}
String path = url.getPath();
- String filename = null;
- int lsi = path.lastIndexOf('/');
- if (lsi != -1)
+ if (connection.changeWorkingDirectory(path))
{
- filename = path.substring(lsi + 1);
- path = path.substring(0, lsi);
- if (!connection.changeWorkingDirectory(path))
- {
- throw new FileNotFoundException(path);
- }
- }
- if (filename != null && filename.length() > 0)
- {
- return this.new ClosingInputStream(connection.retrieve(filename));
+ return this.new ClosingInputStream(connection.list(null));
}
else
{
- return this.new ClosingInputStream(connection.list(null));
+ return this.new ClosingInputStream(connection.retrieve(path));
}
}
@@ -198,20 +183,8 @@ public class FTPURLConnection
{
connect();
}
- String dir = url.getPath();
- String filename = url.getFile();
- if (!connection.changeWorkingDirectory(dir))
- {
- throw new FileNotFoundException(dir);
- }
- if (filename != null)
- {
- return this.new ClosingOutputStream(connection.store(filename));
- }
- else
- {
- throw new FileNotFoundException(filename);
- }
+ String path = url.getPath();
+ return this.new ClosingOutputStream(connection.store(path));
}
public String getRequestProperty(String key)
diff --git a/libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java b/libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java
index a4487d146e8..9870412f2da 100644
--- a/libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java
+++ b/libjava/classpath/gnu/java/net/protocol/http/ChunkedInputStream.java
@@ -1,5 +1,5 @@
/* ChunkedInputStream.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,28 +38,46 @@ exception statement from your version. */
package gnu.java.net.protocol.http;
-import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ProtocolException;
+
+//
+// Note that we rely on the implemtation of skip() in the super class
+// (InputStream) calling our read methods to account for chunk headers
+// while skipping.
+//
+
+
/**
* Input stream wrapper for the "chunked" transfer-coding.
*
* @author Chris Burdess (dog@gnu.org)
*/
public class ChunkedInputStream
- extends FilterInputStream
+ extends InputStream
{
private static final byte CR = 0x0d;
private static final byte LF = 0x0a;
+ Headers headers;
+
+ /** The underlying stream. */
+ private InputStream in;
+
+ /** Size of the chunk we're reading. */
int size;
+ /** Number of bytes we've read in this chunk. */
int count;
+ /**
+ * True when we should read meta-information, false when we should
+ * read data.
+ */
boolean meta;
+ /** True when we've hit EOF. */
boolean eof;
- Headers headers;
/**
* Constructor.
@@ -68,7 +86,7 @@ public class ChunkedInputStream
*/
public ChunkedInputStream(InputStream in, Headers headers)
{
- super(in);
+ this.in = in;
this.headers = headers;
size = -1;
count = 0;
@@ -84,21 +102,10 @@ public class ChunkedInputStream
{
return -1;
}
- int ret = (int) buf[0];
- if (ret < 0)
- {
- ret += 0x100;
- }
- return ret;
- }
-
- public int read(byte[] buffer)
- throws IOException
- {
- return read(buffer, 0, buffer.length);
+ return 0xff & buf[0];
}
- public int read(byte[] buffer, int offset, int length)
+ public synchronized int read(byte[] buffer, int offset, int length)
throws IOException
{
if (eof)
@@ -120,7 +127,18 @@ public class ChunkedInputStream
}
else if (c == 0x0a && last == 0x0d) // CRLF
{
- size = Integer.parseInt(buf.toString(), 16);
+ try
+ {
+ size = Integer.parseInt(buf.toString(), 16);
+ }
+ catch (NumberFormatException nfe)
+ {
+ IOException ioe = new IOException("Bad chunk header");
+ ioe.initCause(nfe);
+ // Unrecoverable. Don't try to read more.
+ in.close();
+ throw ioe;
+ }
break;
}
else if (!seenSemi && c >= 0x30)
@@ -142,17 +160,22 @@ public class ChunkedInputStream
}
else
{
- int diff = length - offset;
- int max = size - count;
- max = (diff < max) ? diff : max;
- int len = (max > 0) ? in.read(buffer, offset, max) : 0;
+ int canRead = Math.min(size - count, length);
+ int len = in.read(buffer, offset, canRead);
+ if (len == -1)
+ {
+ // This is an error condition but it isn't clear what we
+ // should do with it.
+ eof = true;
+ return -1;
+ }
count += len;
if (count == size)
{
// Read CRLF
int c1 = in.read();
int c2 = in.read();
- if (c1 == -1 && c2 == -1)
+ if (c1 == -1 || c2 == -1)
{
// EOF before CRLF: bad, but ignore
eof = true;
@@ -167,6 +190,37 @@ public class ChunkedInputStream
return len;
}
}
+
+ /**
+ * This method returns the number of bytes that can be read from
+ * this stream before a read might block. Even if the underlying
+ * InputStream has data available past the end of the current chunk,
+ * we have no way of knowing how large the next chunk header will
+ * be. So we cannot report available data past the current chunk.
+ *
+ * @return The number of bytes that can be read before a read might
+ * block
+ *
+ * @exception IOException If an error occurs
+ */
+ public int available() throws IOException
+ {
+ if (meta)
+ return 0;
+
+ return Math.min(in.available(), size - count);
+ }
+
+ /**
+ * This method closes the ChunkedInputStream by closing the underlying
+ * InputStream.
+ *
+ * @exception IOException If an error occurs
+ */
+ public void close() throws IOException
+ {
+ in.close();
+ }
}
diff --git a/libjava/classpath/gnu/java/net/protocol/http/HTTPConnection.java b/libjava/classpath/gnu/java/net/protocol/http/HTTPConnection.java
index 573a7918d82..33d9756aa0c 100644
--- a/libjava/classpath/gnu/java/net/protocol/http/HTTPConnection.java
+++ b/libjava/classpath/gnu/java/net/protocol/http/HTTPConnection.java
@@ -1,5 +1,5 @@
/* HTTPConnection.java --
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,7 +38,6 @@ exception statement from your version. */
package gnu.java.net.protocol.http;
-import gnu.classpath.Configuration;
import gnu.classpath.SystemProperties;
import gnu.java.net.EmptyX509TrustManager;
@@ -53,8 +52,9 @@ import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedHashMap;
+import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import javax.net.ssl.HandshakeCompletedListener;
@@ -164,7 +164,7 @@ public class HTTPConnection
/**
* The pool that this connection is a member of (if any).
*/
- private LinkedHashMap pool;
+ private Pool pool;
/**
* Creates a new HTTP connection.
@@ -266,7 +266,8 @@ public class HTTPConnection
/**
* Returns the HTTP version string supported by this connection.
- * @see #version
+ * @see #majorVersion
+ * @see #minorVersion
*/
public String getVersion()
{
@@ -331,27 +332,227 @@ public class HTTPConnection
}
/**
+ * Manages a pool of HTTPConections. The pool will have a maximum
+ * size determined by the value of the maxConn parameter passed to
+ * the {@link #get} method. This value inevitably comes from the
+ * http.maxConnections system property. If the
+ * classpath.net.http.keepAliveTTL system property is set, that will
+ * be the maximum time (in seconds) that an idle connection will be
+ * maintained.
+ */
+ static class Pool
+ {
+ /**
+ * Singleton instance of the pool.
+ */
+ static Pool instance = new Pool();
+
+ /**
+ * The pool
+ */
+ final LinkedList connectionPool = new LinkedList();
+
+ /**
+ * Maximum size of the pool.
+ */
+ int maxConnections;
+
+ /**
+ * If greater than zero, the maximum time a connection will remain
+ * int the pool.
+ */
+ int connectionTTL;
+
+ /**
+ * A thread that removes connections older than connectionTTL.
+ */
+ class Reaper
+ implements Runnable
+ {
+ public void run()
+ {
+ synchronized (Pool.this)
+ {
+ try
+ {
+ do
+ {
+ while (connectionPool.size() > 0)
+ {
+ long currentTime = System.currentTimeMillis();
+
+ HTTPConnection c =
+ (HTTPConnection)connectionPool.getFirst();
+
+ long waitTime = c.timeLastUsed
+ + connectionTTL - currentTime;
+
+ if (waitTime <= 0)
+ removeOldest();
+ else
+ try
+ {
+ Pool.this.wait(waitTime);
+ }
+ catch (InterruptedException _)
+ {
+ // Ignore the interrupt.
+ }
+ }
+ // After the pool is empty, wait TTL to see if it
+ // is used again. This is because in the
+ // situation where a single thread is making HTTP
+ // requests to the same server it can remove the
+ // connection from the pool before the Reaper has
+ // a chance to start. This would cause the Reaper
+ // to exit if it were not for this extra delay.
+ // The result would be starting a Reaper thread
+ // for each HTTP request. With the delay we get
+ // at most one Reaper created each TTL.
+ try
+ {
+ Pool.this.wait(connectionTTL);
+ }
+ catch (InterruptedException _)
+ {
+ // Ignore the interrupt.
+ }
+ }
+ while (connectionPool.size() > 0);
+ }
+ finally
+ {
+ reaper = null;
+ }
+ }
+ }
+ }
+
+ Reaper reaper;
+
+ /**
+ * Private constructor to ensure singleton.
+ */
+ private Pool()
+ {
+ }
+
+ /**
+ * Tests for a matching connection.
+ *
+ * @param c connection to match.
+ * @param h the host name.
+ * @param p the port.
+ * @param sec true if using https.
+ *
+ * @return true if c matches h, p, and sec.
+ */
+ private static boolean matches(HTTPConnection c,
+ String h, int p, boolean sec)
+ {
+ return h.equals(c.hostname) && (p == c.port) && (sec == c.secure);
+ }
+
+ /**
+ * Get a pooled HTTPConnection. If there is an existing idle
+ * connection to the requested server it is returned. Otherwise a
+ * new connection is created.
+ *
+ * @param host the name of the host to connect to
+ * @param port the port on the host to connect to
+ * @param secure whether to use a secure connection
+ *
+ * @return the HTTPConnection.
+ */
+ synchronized HTTPConnection get(String host,
+ int port,
+ boolean secure)
+ {
+ String ttl =
+ SystemProperties.getProperty("classpath.net.http.keepAliveTTL");
+ connectionTTL = (ttl != null && ttl.length() > 0) ?
+ 1000 * Math.max(1, Integer.parseInt(ttl)) : 10000;
+
+ String mc = SystemProperties.getProperty("http.maxConnections");
+ maxConnections = (mc != null && mc.length() > 0) ?
+ Math.max(Integer.parseInt(mc), 1) : 5;
+ if (maxConnections < 1)
+ maxConnections = 1;
+
+ HTTPConnection c = null;
+
+ ListIterator it = connectionPool.listIterator(0);
+ while (it.hasNext())
+ {
+ HTTPConnection cc = (HTTPConnection)it.next();
+ if (matches(cc, host, port, secure))
+ {
+ c = cc;
+ it.remove();
+ break;
+ }
+ }
+ if (c == null)
+ {
+ c = new HTTPConnection(host, port, secure);
+ c.setPool(this);
+ }
+ return c;
+ }
+
+ /**
+ * Put an idle HTTPConnection back into the pool. If this causes
+ * the pool to be come too large, the oldest connection is removed
+ * and closed.
+ *
+ */
+ synchronized void put(HTTPConnection c)
+ {
+ c.timeLastUsed = System.currentTimeMillis();
+ connectionPool.addLast(c);
+
+ // maxConnections must always be >= 1
+ while (connectionPool.size() >= maxConnections)
+ removeOldest();
+
+ if (connectionTTL > 0 && null == reaper) {
+ // If there is a connectionTTL, then the reaper has removed
+ // any stale connections, so we don't have to check for stale
+ // now. We do have to start a reaper though, as there is not
+ // one running now.
+ reaper = new Reaper();
+ Thread t = new Thread(reaper, "HTTPConnection.Reaper");
+ t.setDaemon(true);
+ t.start();
+ }
+ }
+
+ /**
+ * Remove the oldest connection from the pool and close it.
+ */
+ void removeOldest()
+ {
+ HTTPConnection cx = (HTTPConnection)connectionPool.removeFirst();
+ try
+ {
+ cx.closeConnection();
+ }
+ catch (IOException ioe)
+ {
+ // Ignore it. We are just cleaning up.
+ }
+ }
+ }
+
+ /**
* The number of times this HTTPConnection has be used via keep-alive.
*/
int useCount;
/**
- * Generates a key for connections in the connection pool.
- *
- * @param h the host name.
- * @param p the port.
- * @param sec true if using https.
- *
- * @return the key.
+ * If this HTTPConnection is in the pool, the time it was put there.
*/
- static Object getPoolKey(String h, int p, boolean sec)
- {
- StringBuilder buf = new StringBuilder(sec ? "https://" : "http://");
- buf.append(h);
- buf.append(':');
- buf.append(p);
- return buf.toString();
- }
+ long timeLastUsed;
/**
* Set the connection pool that this HTTPConnection is a member of.
@@ -360,7 +561,7 @@ public class HTTPConnection
*
* @param p the pool.
*/
- void setPool(LinkedHashMap p)
+ void setPool(Pool p)
{
pool = p;
}
@@ -374,25 +575,20 @@ public class HTTPConnection
{
if (pool != null)
{
- synchronized (pool)
+ useCount++;
+ pool.put(this);
+
+ }
+ else
+ {
+ // If there is no pool, just close.
+ try
{
- useCount++;
- Object key = HTTPConnection.getPoolKey(hostname, port, secure);
- pool.put(key, this);
- while (pool.size() >= HTTPURLConnection.maxConnections)
- {
- // maxConnections must always be >= 1
- Object lru = pool.keySet().iterator().next();
- HTTPConnection c = (HTTPConnection)pool.remove(lru);
- try
- {
- c.closeConnection();
- }
- catch (IOException ioe)
- {
- // Ignore it. We are just cleaning up.
- }
- }
+ closeConnection();
+ }
+ catch (IOException ioe)
+ {
+ // Ignore it. We are just cleaning up.
}
}
}
diff --git a/libjava/classpath/gnu/java/net/protocol/http/HTTPURLConnection.java b/libjava/classpath/gnu/java/net/protocol/http/HTTPURLConnection.java
index d5da7d61ae4..5c2af9eb7f6 100644
--- a/libjava/classpath/gnu/java/net/protocol/http/HTTPURLConnection.java
+++ b/libjava/classpath/gnu/java/net/protocol/http/HTTPURLConnection.java
@@ -1,5 +1,5 @@
/* HTTPURLConnection.java --
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.java.net.protocol.http;
+import gnu.classpath.SystemProperties;
+
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -45,11 +47,11 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.ProtocolException;
import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.security.cert.Certificate;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -70,13 +72,6 @@ public class HTTPURLConnection
extends HttpsURLConnection
implements HandshakeCompletedListener
{
-
- /**
- * Pool of reusable connections, used if keepAlive is true.
- */
- private static final LinkedHashMap connectionPool = new LinkedHashMap();
- static int maxConnections;
-
/*
* The underlying connection.
*/
@@ -108,38 +103,23 @@ public class HTTPURLConnection
{
super(url);
requestHeaders = new Headers();
- AccessController.doPrivileged(this.new GetHTTPPropertiesAction());
- }
-
- class GetHTTPPropertiesAction
- implements PrivilegedAction
- {
-
- public Object run()
- {
- proxyHostname = System.getProperty("http.proxyHost");
- if (proxyHostname != null && proxyHostname.length() > 0)
- {
- String port = System.getProperty("http.proxyPort");
- if (port != null && port.length() > 0)
- {
- proxyPort = Integer.parseInt(port);
- }
- else
- {
- proxyHostname = null;
- proxyPort = -1;
- }
- }
- agent = System.getProperty("http.agent");
- String ka = System.getProperty("http.keepAlive");
- keepAlive = !(ka != null && "false".equals(ka));
- String mc = System.getProperty("http.maxConnections");
- maxConnections = (mc != null && mc.length() > 0) ?
- Math.max(Integer.parseInt(mc), 1) : 5;
- return null;
- }
-
+ proxyHostname = SystemProperties.getProperty("http.proxyHost");
+ if (proxyHostname != null && proxyHostname.length() > 0)
+ {
+ String port = SystemProperties.getProperty("http.proxyPort");
+ if (port != null && port.length() > 0)
+ {
+ proxyPort = Integer.parseInt(port);
+ }
+ else
+ {
+ proxyHostname = null;
+ proxyPort = -1;
+ }
+ }
+ agent = SystemProperties.getProperty("http.agent");
+ String ka = SystemProperties.getProperty("http.keepAlive");
+ keepAlive = !(ka != null && "false".equals(ka));
}
public void connect()
@@ -254,8 +234,24 @@ public class HTTPURLConnection
}
}
- if (response.getCodeClass() == 3 && getInstanceFollowRedirects())
+ if (response.isRedirect() && getInstanceFollowRedirects())
{
+ // Read the response body, if there is one. If the
+ // redirect points us back at the same server, we will use
+ // the cached connection, so we must make sure there is no
+ // pending data in it.
+ InputStream body = response.getBody();
+ if (body != null)
+ {
+ byte[] ignore = new byte[1024];
+ while (true)
+ {
+ int n = body.read(ignore, 0, ignore.length);
+ if (n == -1)
+ break;
+ }
+ }
+
// Follow redirect
String location = response.getHeader("Location");
if (location != null)
@@ -333,16 +329,13 @@ public class HTTPURLConnection
{
responseSink = response.getBody();
- if (response.getCode() == 404)
- {
- errorSink = responseSink;
- throw new FileNotFoundException(url.toString());
- }
+ if (response.isError())
+ errorSink = responseSink;
}
}
while (retry);
connected = true;
- }
+ }
/**
* Returns a connection, from the pool if necessary.
@@ -353,16 +346,7 @@ public class HTTPURLConnection
HTTPConnection connection;
if (keepAlive)
{
- Object key = HTTPConnection.getPoolKey(host, port, secure);
- synchronized (connectionPool)
- {
- connection = (HTTPConnection) connectionPool.remove(key);
- if (connection == null)
- {
- connection = new HTTPConnection(host, port, secure);
- connection.setPool(connectionPool);
- }
- }
+ connection = HTTPConnection.Pool.instance.get(host, port, secure);
}
else
{
@@ -427,30 +411,32 @@ public class HTTPURLConnection
public String getRequestProperty(String key)
{
+ if (key == null)
+ return null;
+
return requestHeaders.getValue(key);
}
public Map getRequestProperties()
{
- return requestHeaders;
+ if (connected)
+ throw new IllegalStateException("Already connected");
+
+ Map m = requestHeaders.getAsMap();
+ return Collections.unmodifiableMap(m);
}
public void setRequestProperty(String key, String value)
{
+ super.setRequestProperty(key, value);
+
requestHeaders.put(key, value);
}
public void addRequestProperty(String key, String value)
{
- String old = requestHeaders.getValue(key);
- if (old == null)
- {
- requestHeaders.put(key, value);
- }
- else
- {
- requestHeaders.put(key, old + "," + value);
- }
+ super.addRequestProperty(key, value);
+ requestHeaders.addValue(key, value);
}
public OutputStream getOutputStream()
@@ -493,6 +479,17 @@ public class HTTPURLConnection
{
throw new ProtocolException("doInput is false");
}
+
+ if (response.isError())
+ {
+ int code = response.getCode();
+ if (code == 404 || code == 410)
+ throw new FileNotFoundException(url.toString());
+
+ throw new IOException("Server returned HTTP response code " + code
+ + " for URL " + url.toString());
+ }
+
return responseSink;
}
@@ -514,17 +511,9 @@ public class HTTPURLConnection
return null;
}
}
- Headers headers = response.getHeaders();
- LinkedHashMap ret = new LinkedHashMap();
- ret.put(null, Collections.singletonList(getStatusLine(response)));
- for (Iterator i = headers.entrySet().iterator(); i.hasNext(); )
- {
- Map.Entry entry = (Map.Entry) i.next();
- String key = (String) entry.getKey();
- String value = (String) entry.getValue();
- ret.put(key, Collections.singletonList(value));
- }
- return Collections.unmodifiableMap(ret);
+ Map m = response.getHeaders().getAsMap();
+ m.put(null, Collections.singletonList(getStatusLine(response)));
+ return Collections.unmodifiableMap(m);
}
String getStatusLine(Response response)
@@ -552,20 +541,7 @@ public class HTTPURLConnection
{
return getStatusLine(response);
}
- Iterator i = response.getHeaders().entrySet().iterator();
- Map.Entry entry;
- int count = 1;
- do
- {
- if (!i.hasNext())
- {
- return null;
- }
- entry = (Map.Entry) i.next();
- count++;
- }
- while (count <= index);
- return (String) entry.getValue();
+ return response.getHeaders().getHeaderValue(index - 1);
}
public String getHeaderFieldKey(int index)
@@ -581,24 +557,8 @@ public class HTTPURLConnection
return null;
}
}
- if (index == 0)
- {
- return null;
- }
- Iterator i = response.getHeaders().entrySet().iterator();
- Map.Entry entry;
- int count = 1;
- do
- {
- if (!i.hasNext())
- {
- return null;
- }
- entry = (Map.Entry) i.next();
- count++;
- }
- while (count <= index);
- return (String) entry.getKey();
+ // index of zero is the status line.
+ return response.getHeaders().getHeaderName(index - 1);
}
public String getHeaderField(String name)
@@ -614,7 +574,7 @@ public class HTTPURLConnection
return null;
}
}
- return (String) response.getHeader(name);
+ return response.getHeader(name);
}
public long getHeaderFieldDate(String name, long def)
diff --git a/libjava/classpath/gnu/java/net/protocol/http/Headers.java b/libjava/classpath/gnu/java/net/protocol/http/Headers.java
index 9306fc411c9..b42faaa315d 100644
--- a/libjava/classpath/gnu/java/net/protocol/http/Headers.java
+++ b/libjava/classpath/gnu/java/net/protocol/http/Headers.java
@@ -1,5 +1,5 @@
/* Headers.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -44,125 +44,75 @@ import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
-import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
- * A collection of HTTP header names and associated values.
- * Retrieval of values is case insensitive. An iteration over the keys
+ * A collection of HTTP header names and associated values. The
+ * values are {@link ArrayList ArrayLists} of Strings. Retrieval of
+ * values is case insensitive. An iteration over the collection
* returns the header names in the order they were received.
*
* @author Chris Burdess (dog@gnu.org)
+ * @author David Daney (ddaney@avtrex.com)
*/
-public class Headers
- extends LinkedHashMap
+class Headers
{
-
+ /**
+ * A list of HeaderElements
+ *
+ */
+ private final ArrayList headers = new ArrayList();
+
static final DateFormat dateFormat = new HTTPDateFormat();
- static class Header
+ static class HeaderElement
{
+ String name;
+ String value;
- final String name;
-
- Header(String name)
+ HeaderElement(String name, String value)
{
- if (name == null || name.length() == 0)
- {
- throw new IllegalArgumentException(name);
- }
this.name = name;
+ this.value = value;
}
-
- public int hashCode()
- {
- return name.toLowerCase().hashCode();
- }
-
- public boolean equals(Object other)
- {
- if (other instanceof Header)
- {
- return ((Header) other).name.equalsIgnoreCase(name);
- }
- return false;
- }
-
- public String toString()
- {
- return name;
- }
-
- }
-
- static class HeaderEntry
- implements Map.Entry
- {
-
- final Map.Entry entry;
-
- HeaderEntry(Map.Entry entry)
- {
- this.entry = entry;
- }
-
- public Object getKey()
- {
- return ((Header) entry.getKey()).name;
- }
-
- public Object getValue()
- {
- return entry.getValue();
- }
-
- public Object setValue(Object value)
- {
- return entry.setValue(value);
- }
-
- public int hashCode()
- {
- return entry.hashCode();
- }
-
- public boolean equals(Object other)
- {
- return entry.equals(other);
- }
-
- public String toString()
- {
- return getKey().toString() + "=" + getValue();
- }
-
}
public Headers()
{
}
- public boolean containsKey(Object key)
- {
- return super.containsKey(new Header((String) key));
- }
-
- public Object get(Object key)
+ /**
+ * Return an Iterator over this collection of headers.
+ * Iterator.getNext() returns objects of type {@link HeaderElement}.
+ *
+ * @return the Iterator.
+ */
+ Iterator iterator()
{
- return super.get(new Header((String) key));
+ return headers.iterator();
}
-
+
/**
- * Returns the value of the specified header as a string.
+ * Returns the value of the specified header as a string. If
+ * multiple values are present, the last one is returned.
*/
public String getValue(String header)
{
- return (String) super.get(new Header(header));
+ for (int i = headers.size() - 1; i >= 0; i--)
+ {
+ HeaderElement e = (HeaderElement)headers.get(i);
+ if (e.name.equalsIgnoreCase(header))
+ {
+ return e.value;
+ }
+ }
+ return null;
}
/**
@@ -228,51 +178,62 @@ public class Headers
}
}
- public Object put(Object key, Object value)
- {
- return super.put(new Header((String) key), value);
- }
-
- public Object remove(Object key)
+ /**
+ * Add a header to this set of headers. If there is an existing
+ * header with the same name, it is discarded.
+ *
+ * @param name the header name
+ * @param value the header value
+ *
+ * @see #addValue
+ */
+ public void put(String name, String value)
{
- return super.remove(new Header((String) key));
+ remove(name);
+ headers.add(headers.size(), new HeaderElement(name, value));
}
- public void putAll(Map t)
+ /**
+ * Add all headers from a set of headers to this set. If any of the
+ * headers to be added have the same name as existing headers, the
+ * existing headers will be discarded.
+ *
+ * @param o the headers to be added
+ */
+ public void putAll(Headers o)
{
- for (Iterator i = t.keySet().iterator(); i.hasNext(); )
+ for (Iterator it = o.iterator(); it.hasNext(); )
{
- String key = (String) i.next();
- String value = (String) t.get(key);
- put(key, value);
+ HeaderElement e = (HeaderElement)it.next();
+ remove(e.name);
}
- }
-
- public Set keySet()
- {
- Set keys = super.keySet();
- Set ret = new LinkedHashSet();
- for (Iterator i = keys.iterator(); i.hasNext(); )
+ for (Iterator it = o.iterator(); it.hasNext(); )
{
- ret.add(((Header) i.next()).name);
+ HeaderElement e = (HeaderElement)it.next();
+ addValue(e.name, e.value);
}
- return ret;
}
- public Set entrySet()
+ /**
+ * Remove a header from this set of headers. If there is more than
+ * one instance of a header of the given name, they are all removed.
+ *
+ * @param name the header name
+ */
+ public void remove(String name)
{
- Set entries = super.entrySet();
- Set ret = new LinkedHashSet();
- for (Iterator i = entries.iterator(); i.hasNext(); )
+ for (Iterator it = headers.iterator(); it.hasNext(); )
{
- Map.Entry entry = (Map.Entry) i.next();
- ret.add(new HeaderEntry(entry));
+ HeaderElement e = (HeaderElement)it.next();
+ if (e.name.equalsIgnoreCase(name))
+ it.remove();
}
- return ret;
}
/**
- * Parse the specified input stream, adding headers to this collection.
+ * Parse the specified InputStream, adding headers to this collection.
+ *
+ * @param in the InputStream.
*/
public void parse(InputStream in)
throws IOException
@@ -334,18 +295,90 @@ public class Headers
}
}
- private void addValue(String name, String value)
+
+ /**
+ * Add a header to this set of headers. If there is an existing
+ * header with the same name, it is not effected.
+ *
+ * @param name the header name
+ * @param value the header value
+ *
+ * @see #put
+ */
+ public void addValue(String name, String value)
+ {
+ headers.add(headers.size(), new HeaderElement(name, value));
+ }
+
+ /**
+ * Get a new Map containing all the headers. The keys of the Map
+ * are Strings (the header names). The values of the Map are
+ * unmodifiable Lists containing Strings (the header values).
+ *
+ * <p>
+ *
+ * The returned map is modifiable. Changing it will not effect this
+ * collection of Headers in any way.
+ *
+ * @return a Map containing all the headers.
+ */
+ public Map getAsMap()
{
- Header key = new Header(name);
- String old = (String) super.get(key);
- if (old == null)
+ LinkedHashMap m = new LinkedHashMap();
+ for (Iterator it = headers.iterator(); it.hasNext(); )
{
- super.put(key, value);
+ HeaderElement e = (HeaderElement)it.next();
+ ArrayList l = (ArrayList)m.get(e.name);
+ if (l == null)
+ {
+ l = new ArrayList(1);
+ l.add(e.value);
+ m.put(e.name, l);
+ }
+ else
+ l.add(0, e.value);
}
- else
+ for (Iterator it = m.entrySet().iterator(); it.hasNext(); )
{
- super.put(key, old + ", " + value);
+ Map.Entry me = (Map.Entry)it.next();
+ ArrayList l = (ArrayList)me.getValue();
+ me.setValue(Collections.unmodifiableList(l));
}
+ return m;
+ }
+
+ /**
+ * Get the name of the Nth header.
+ *
+ * @param i the header index.
+ *
+ * @return the header name.
+ *
+ * @see #getHeaderValue
+ */
+ public String getHeaderName(int i)
+ {
+ if (i >= headers.size() || i < 0)
+ return null;
+
+ return ((HeaderElement)headers.get(i)).name;
+ }
+
+ /**
+ * Get the value of the Nth header.
+ *
+ * @param i the header index.
+ *
+ * @return the header value.
+ *
+ * @see #getHeaderName
+ */
+ public String getHeaderValue(int i)
+ {
+ if (i >= headers.size() || i < 0)
+ return null;
+
+ return ((HeaderElement)headers.get(i)).value;
}
}
diff --git a/libjava/classpath/gnu/java/net/protocol/http/Request.java b/libjava/classpath/gnu/java/net/protocol/http/Request.java
index b9441b3f736..e15ec4182a4 100644
--- a/libjava/classpath/gnu/java/net/protocol/http/Request.java
+++ b/libjava/classpath/gnu/java/net/protocol/http/Request.java
@@ -1,5 +1,5 @@
/* Request.java --
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -94,11 +94,6 @@ public class Request
protected RequestBodyWriter requestBodyWriter;
/**
- * Request body negotiation threshold for 100-continue expectations.
- */
- protected int requestBodyNegotiationThreshold;
-
- /**
* Map of response header handlers.
*/
protected Map responseHeaderHandlers;
@@ -127,7 +122,6 @@ public class Request
this.path = path;
requestHeaders = new Headers();
responseHeaderHandlers = new HashMap();
- requestBodyNegotiationThreshold = 4096;
}
/**
@@ -251,21 +245,6 @@ public class Request
}
/**
- * Sets the request body negotiation threshold.
- * If this is set, it determines the maximum size that the request body
- * may be before body negotiation occurs(via the
- * <code>100-continue</code> expectation). This ensures that a large
- * request body is not sent when the server wouldn't have accepted it
- * anyway.
- * @param threshold the body negotiation threshold, or &lt;=0 to disable
- * request body negotation entirely
- */
- public void setRequestBodyNegotiationThreshold(int threshold)
- {
- requestBodyNegotiationThreshold = threshold;
- }
-
- /**
* Dispatches this request.
* A request can only be dispatched once; calling this method a second
* time results in a protocol exception.
@@ -291,10 +270,10 @@ public class Request
if (requestBodyWriter != null)
{
contentLength = requestBodyWriter.getContentLength();
- if (contentLength > requestBodyNegotiationThreshold)
+ String expect = getHeader("Expect");
+ if (expect != null && expect.equals("100-continue"))
{
expectingContinue = true;
- setHeader("Expect", "100-continue");
}
else
{
@@ -323,12 +302,10 @@ public class Request
String line = method + ' ' + requestUri + ' ' + version + CRLF;
out.write(line.getBytes(US_ASCII));
// Request headers
- for (Iterator i = requestHeaders.keySet().iterator();
- i.hasNext(); )
+ for (Iterator i = requestHeaders.iterator(); i.hasNext(); )
{
- String name =(String) i.next();
- String value =(String) requestHeaders.get(name);
- line = name + HEADER_SEP + value + CRLF;
+ Headers.HeaderElement elt = (Headers.HeaderElement)i.next();
+ line = elt.name + HEADER_SEP + elt.value + CRLF;
out.write(line.getBytes(US_ASCII));
}
out.write(CRLF.getBytes(US_ASCII));
@@ -459,23 +436,17 @@ public class Request
void notifyHeaderHandlers(Headers headers)
{
- for (Iterator i = headers.entrySet().iterator(); i.hasNext(); )
+ for (Iterator i = headers.iterator(); i.hasNext(); )
{
- Map.Entry entry = (Map.Entry) i.next();
- String name =(String) entry.getKey();
+ Headers.HeaderElement entry = (Headers.HeaderElement) i.next();
// Handle Set-Cookie
- if ("Set-Cookie".equalsIgnoreCase(name))
- {
- String value = (String) entry.getValue();
- handleSetCookie(value);
- }
+ if ("Set-Cookie".equalsIgnoreCase(entry.name))
+ handleSetCookie(entry.value);
+
ResponseHeaderHandler handler =
- (ResponseHeaderHandler) responseHeaderHandlers.get(name);
+ (ResponseHeaderHandler) responseHeaderHandlers.get(entry.name);
if (handler != null)
- {
- String value = (String) entry.getValue();
- handler.setValue(value);
- }
+ handler.setValue(entry.value);
}
}
@@ -528,6 +499,9 @@ public class Request
throw new ProtocolException("Unsupported Content-Encoding: " +
contentCoding);
}
+ // Remove the Content-Encoding header because the content is
+ // no longer compressed.
+ responseHeaders.remove("Content-Encoding");
}
return in;
}
diff --git a/libjava/classpath/gnu/java/net/protocol/http/Response.java b/libjava/classpath/gnu/java/net/protocol/http/Response.java
index 58d74542c30..76fac9344f5 100644
--- a/libjava/classpath/gnu/java/net/protocol/http/Response.java
+++ b/libjava/classpath/gnu/java/net/protocol/http/Response.java
@@ -1,5 +1,5 @@
/* Response.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -188,6 +188,28 @@ public class Response
{
return headers.getDateValue(name);
}
+
+ /**
+ * Tests whether this response indicates a redirection.
+ *
+ * @return <code>true</code> if, <code>false</code> otherwise.
+ */
+ public boolean isRedirect()
+ {
+ return (code != 304 && getCodeClass() == 3);
+ }
+
+ /**
+ * Tests whether this response indicates an error.
+ * Errors are the response codes <code>4xx</code> - Client error and
+ * <code>5xx</code> - Server error.
+ *
+ * @return <code>true</code> if, <code>false</code> otherwise.
+ */
+ public boolean isError()
+ {
+ return (getCodeClass() == 4 || getCodeClass() == 5);
+ }
/**
* Returns an InputStream that returns the body of the response.
diff --git a/libjava/classpath/gnu/java/net/protocol/http/ResponseHeaderHandler.java b/libjava/classpath/gnu/java/net/protocol/http/ResponseHeaderHandler.java
index 8e4e6492acf..4c5261da160 100644
--- a/libjava/classpath/gnu/java/net/protocol/http/ResponseHeaderHandler.java
+++ b/libjava/classpath/gnu/java/net/protocol/http/ResponseHeaderHandler.java
@@ -41,7 +41,7 @@ package gnu.java.net.protocol.http;
/**
* Callback interface for objects that wish to be notified of response
* header values.
- * @see Request#setHeaderHandler(String)
+ * @see Request#setResponseHeaderHandler(String, ResponseHeaderHandler)
*
* @author Chris Burdess (dog@gnu.org)
*/
diff --git a/libjava/classpath/gnu/java/net/protocol/jar/Connection.java b/libjava/classpath/gnu/java/net/protocol/jar/Connection.java
index e2a052ef581..41c5d6dcf69 100644
--- a/libjava/classpath/gnu/java/net/protocol/jar/Connection.java
+++ b/libjava/classpath/gnu/java/net/protocol/jar/Connection.java
@@ -1,5 +1,5 @@
/* Connection - jar url connection for java.net
- Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ exception statement from your version. */
package gnu.java.net.protocol.jar;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -145,7 +146,7 @@ public final class Connection extends JarURLConnection
jar_entry = (JarEntry) jar_file.getEntry (entry_name);
if(jar_entry == null)
- throw new IOException ("No entry for " + entry_name + " exists.");
+ throw new FileNotFoundException("No entry for " + entry_name + " exists.");
}
connected = true;
@@ -159,9 +160,6 @@ public final class Connection extends JarURLConnection
if (! doInput)
throw new ProtocolException("Can't open InputStream if doInput is false");
- if (jar_entry == null)
- throw new IOException (jar_url + " couldn't be found.");
-
return jar_file.getInputStream (jar_entry);
}
diff --git a/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java b/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java
index a557c7d3ba6..671ae5bb15f 100644
--- a/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java
+++ b/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java
@@ -527,7 +527,7 @@ public final class FileChannelImpl extends FileChannel
throws IOException
{
if (newPosition < 0)
- throw new IllegalArgumentException ("newPostition: " + newPosition);
+ throw new IllegalArgumentException ("newPosition: " + newPosition);
if (!isOpen ())
throw new ClosedChannelException ();
diff --git a/libjava/classpath/gnu/java/nio/charset/Provider.java b/libjava/classpath/gnu/java/nio/charset/Provider.java
index 01c2650a81b..ad3b1da8471 100644
--- a/libjava/classpath/gnu/java/nio/charset/Provider.java
+++ b/libjava/classpath/gnu/java/nio/charset/Provider.java
@@ -81,7 +81,8 @@ public final class Provider extends CharsetProvider
*/
private boolean extendedLoaded;
- private Provider ()
+ // Package private to avoid an accessor method in PrivilegedAction below.
+ Provider ()
{
extendedLoaded = false;
canonicalNames = new HashMap ();
diff --git a/libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java b/libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java
index fa6f4970042..f76d3fd5e1a 100644
--- a/libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java
+++ b/libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java
@@ -44,7 +44,6 @@ import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
final class IconvDecoder extends CharsetDecoder
diff --git a/libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java b/libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java
index d5cc8877f75..47446f98fd4 100644
--- a/libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java
+++ b/libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java
@@ -43,7 +43,6 @@ import gnu.classpath.Pointer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
diff --git a/libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java b/libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java
index 6fd8b744082..cf9fc56a2f5 100644
--- a/libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java
+++ b/libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java
@@ -40,8 +40,6 @@ package gnu.java.nio.charset.iconv;
import java.nio.charset.Charset;
import java.nio.charset.spi.CharsetProvider;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
diff --git a/libjava/classpath/gnu/java/rmi/dgc/DGCImpl.java b/libjava/classpath/gnu/java/rmi/dgc/DGCImpl.java
index a32445c343b..a7bc0940ed0 100644
--- a/libjava/classpath/gnu/java/rmi/dgc/DGCImpl.java
+++ b/libjava/classpath/gnu/java/rmi/dgc/DGCImpl.java
@@ -8,7 +8,7 @@ GNU Classpath is free software; you can redistribute 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
@@ -49,70 +49,146 @@ import java.rmi.server.RMISocketFactory;
import java.util.Hashtable;
/**
- * I let DGCImpl to extend UnicastServerRef, but not
- * UnicastRemoteObject, because UnicastRemoteObject must
- * exportObject automatically.
- */
+ * The DGC implementation is used for the server side during the distributed
+ * garbage collection. This interface contains the two methods: dirty and clean.
+ * A dirty call is made when a remote reference is unmarshaled in a client. A
+ * corresponding clean call is made by client it no longer uses that remote
+ * reference. A reference to a remote object is also automatically released
+ * after so called lease period that starts after the dirty call is received. It
+ * is the client's responsibility to renew the leases, by making additional
+ * dirty calls before such leases expire.
+ */
public class DGCImpl
- extends UnicastServerRef implements DGC {
-
- private static final long LEASE_VALUE = 600000L;
- // leaseCache caches a LeaseRecord associated with a vmid
- private Hashtable leaseCache = new Hashtable();
-
-public DGCImpl() throws RemoteException {
- super(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory());
-}
-
-public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) throws RemoteException {
- VMID vmid = lease.getVMID();
- if (vmid == null)
- vmid = new VMID();
- long leaseValue = LEASE_VALUE;
- //long leaseValue = lease.getValue();
+ extends UnicastServerRef
+ implements DGC
+{
+ /*
+ * The DGCImpl extends UnicastServerRef and not UnicastRemoteObject, because
+ * UnicastRemoteObject must exportObject automatically.
+ */
+
+ /**
+ * This defauld lease value is used if the lease value, passed to the
+ * {@link #dirty} is equal to zero.
+ */
+ static final long LEASE_VALUE = 600000L;
+
+ // leaseCache caches a LeaseRecord associated with a vmid
+ Hashtable leaseCache = new Hashtable();
+
+ public DGCImpl() throws RemoteException
+ {
+ super(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory());
+ }
+
+ /**
+ * Mark the given objects referecnes as used on the client side.
+ *
+ * @param ids the ids of the used objects.
+ * @param sequenceNum the number of the call (used to detect and discard late
+ * calls).
+ * @param lease the requested lease
+ * @return the granted lease
+ */
+ public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease)
+ throws RemoteException
+ {
+ VMID vmid = lease.getVMID();
+ if (vmid == null)
+ vmid = new VMID();
+
+ long leaseValue = lease.getValue();
+ if (leaseValue <= 0)
+ leaseValue = LEASE_VALUE;
+
lease = new Lease(vmid, leaseValue);
- synchronized(leaseCache){
- LeaseRecord lr = (LeaseRecord)leaseCache.get(vmid);
- if (lr != null)
- lr.reset(leaseValue);
- else{
- lr = new LeaseRecord(vmid, leaseValue);
- leaseCache.put(vmid, lr);
- }
- }
-
- return (lease);
-}
-
-public void clean(ObjID[] ids, long sequenceNum, VMID vmid, boolean strong) throws RemoteException {
- // Not implemented
-}
+ LeaseRecord lr = (LeaseRecord) leaseCache.get(vmid);
+ if (lr != null)
+ lr.reset(leaseValue);
+ else
+ {
+ lr = new LeaseRecord(vmid, leaseValue, ids);
+ leaseCache.put(vmid, lr);
+ }
+ return (lease);
+ }
+
+ /**
+ * Mark the given objects as no longer used on the client side.
+ *
+ * @param ids the ids of the objects that are no longer used.
+ * @param sequenceNum the number of the call (used to detect and discard late
+ * calls)
+ * @param vmid the VMID of the client.
+ * @param strong make the "strong" clean call.
+ */
+ public void clean(ObjID[] ids, long sequenceNum, VMID vmid, boolean strong)
+ throws RemoteException
+ {
+ // Not implemented
+ // TODO implement
+ }
+
/**
* LeaseRecord associates a vmid to expireTime.
*/
- private static class LeaseRecord{
- private VMID vmid;
- private long expireTime;
+ static class LeaseRecord
+ {
+ /**
+ * The lease id.
+ */
+ final VMID vmid;
+
+ /**
+ * The lease expiration time.
+ */
+ long expireTime;
- LeaseRecord(VMID vmid, long leaseValue){
+ /**
+ * The array of ObjeID's that must be protected from being garbage
+ * collected.
+ */
+ final ObjID [] objects;
+
+ /**
+ * Create the new lease record.
+ *
+ * @param vmid lease id.
+ * @param leaseValue lease value
+ */
+ LeaseRecord(VMID vmid, long leaseValue, ObjID [] an_objects)
+ {
this.vmid = vmid;
reset(leaseValue);
+ objects = an_objects;
}
-
- // reset expireTime
- void reset(long leaseValue){
+
+ /**
+ * Prolong the expiration time till current time + passed value
+ *
+ * @param leaseValue the value after that (since the current moment)
+ * the lease should expire in the future.
+ */
+ void reset(long leaseValue)
+ {
long l = System.currentTimeMillis();
expireTime = l + leaseValue;
}
-
- boolean isExpired(){
+
+ /**
+ * Check if the lease has been expired.
+ *
+ * @return true if the lease has been expired, false if it is still valid.
+ */
+ boolean isExpired()
+ {
long l = System.currentTimeMillis();
- if ( l > expireTime)
- return true;
+ if (l > expireTime)
+ return true;
return false;
}
-
- } //End of LeaseRecord
-} //End of DGCImpl
+ } // End of LeaseRecord
+
+} // End of DGCImpl
diff --git a/libjava/classpath/gnu/java/rmi/registry/RegistryImpl.java b/libjava/classpath/gnu/java/rmi/registry/RegistryImpl.java
index 0c94434d806..7dcca612ab2 100644
--- a/libjava/classpath/gnu/java/rmi/registry/RegistryImpl.java
+++ b/libjava/classpath/gnu/java/rmi/registry/RegistryImpl.java
@@ -111,7 +111,7 @@ public static void version() {
+ System.getProperty("java.vm.name")
+ ") "
+ System.getProperty("java.vm.version"));
- System.out.println("Copyright 2005 Free Software Foundation, Inc.");
+ System.out.println("Copyright 2006 Free Software Foundation, Inc.");
System.out.println("This is free software; see the source for copying conditions. There is NO");
System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
System.exit(0);
diff --git a/libjava/classpath/gnu/java/rmi/server/CombinedClassLoader.java b/libjava/classpath/gnu/java/rmi/server/CombinedClassLoader.java
new file mode 100644
index 00000000000..3d2e37d5377
--- /dev/null
+++ b/libjava/classpath/gnu/java/rmi/server/CombinedClassLoader.java
@@ -0,0 +1,149 @@
+/* CombinedClassLoader.java -- Multiple class loader support for proxy.
+ 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.java.rmi.server;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+/**
+ * This class supports the multiple class loaders to load the resources. It is
+ * used for constructing proxy classes that implement interfaces, loaded by
+ * the several different class loaders.
+ *
+ * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
+ */
+public class CombinedClassLoader extends ClassLoader
+{
+ /**
+ * The class loader array.
+ */
+ ClassLoader[] loaders;
+
+ /**
+ * Create a new combined class loader that uses the given collection of
+ * loaders to load the classes and resources. The loader order is equal to
+ * the order, returned by the collection interator. The duplicate loaders
+ * are discarded and the system class loader is added as the last loader.
+ *
+ * @param a_loaders the loadery collection (may contain duplicate instances
+ * that will be discarded.
+ */
+ public CombinedClassLoader(Collection a_loaders)
+ {
+ ArrayList sLoaders = new ArrayList(a_loaders.size());
+
+ Iterator iter = a_loaders.iterator();
+ Object cl;
+ while (iter.hasNext())
+ {
+ cl = iter.next();
+ if (!sLoaders.contains(cl))
+ sLoaders.add(iter.next());
+ }
+
+ loaders = new ClassLoader[sLoaders.size()];
+
+ for (int i = 0; i < loaders.length; i++)
+ loaders[i] = (ClassLoader) sLoaders.get(i);
+ }
+
+ /**
+ * Find the class with the given name.
+ */
+ protected Class findClass(String name) throws ClassNotFoundException
+ {
+ for (int i = 0; i < loaders.length; i++)
+ {
+ try
+ {
+ return findClass(name);
+ }
+ catch (ClassNotFoundException e)
+ {
+ // try another.
+ }
+ }
+ return super.findClass(name);
+ }
+
+ /**
+ * Find the library with the given name
+ */
+ protected String findLibrary(String name)
+ {
+ for (int i = 0; i < loaders.length; i++)
+ {
+ String lib = findLibrary(name);
+ if (lib != null)
+ return lib;
+ }
+ return super.findLibrary(name);
+ }
+
+ /**
+ * Find resource with the given name.
+ */
+ protected URL findResource(String name)
+ {
+ for (int i = 0; i < loaders.length; i++)
+ {
+ URL resource = findResource(name);
+ if (resource != null)
+ return resource;
+ }
+ return super.findResource(name);
+ }
+
+ /**
+ * Find resources with the given name.
+ */
+ protected Enumeration findResources(String name) throws IOException
+ {
+ for (int i = 0; i < loaders.length; i++)
+ {
+ Enumeration resource = findResources(name);
+ if (resource != null)
+ return resource;
+ }
+ return super.findResources(name); }
+}
diff --git a/libjava/classpath/gnu/java/rmi/server/RMIObjectInputStream.java b/libjava/classpath/gnu/java/rmi/server/RMIObjectInputStream.java
index 587d57fc7bb..e76535447be 100644
--- a/libjava/classpath/gnu/java/rmi/server/RMIObjectInputStream.java
+++ b/libjava/classpath/gnu/java/rmi/server/RMIObjectInputStream.java
@@ -46,6 +46,7 @@ import java.io.ObjectStreamClass;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.rmi.server.RMIClassLoader;
+import java.util.ArrayList;
public class RMIObjectInputStream
extends ObjectInputStream {
@@ -76,28 +77,51 @@ protected Object getAnnotation()
return readObject();
}
-protected Class resolveProxyClass(String intfs[])
- throws IOException, ClassNotFoundException
-{
- String annotation = (String)getAnnotation();
-
+
+ protected Class resolveProxyClass(String intfs[]) throws IOException,
+ ClassNotFoundException
+ {
+ String annotation = (String) getAnnotation();
+
Class clss[] = new Class[intfs.length];
- if(annotation == null)
- clss[0] = RMIClassLoader.loadClass(intfs[0]);
- else
- clss[0] = RMIClassLoader.loadClass(annotation, intfs[0]);
-
- //assume all interfaces can be loaded by the same classloader
- ClassLoader loader = clss[0].getClassLoader();
+
for (int i = 0; i < intfs.length; i++)
- clss[i] = Class.forName(intfs[i], false, loader);
-
- try {
- return Proxy.getProxyClass(loader, clss);
- } catch (IllegalArgumentException e) {
- throw new ClassNotFoundException(null, e);
- }
-}
+ {
+ if (annotation == null)
+ clss[i] = RMIClassLoader.loadClass(intfs[i]);
+ else
+ clss[i] = RMIClassLoader.loadClass(annotation, intfs[i]);
+ }
+
+ ClassLoader loader;
+
+ if (clss.length > 0)
+ {
+ // Chain all class loaders (they may differ).
+ ArrayList loaders = new ArrayList(intfs.length);
+ ClassLoader cx;
+ for (int i = 0; i < clss.length; i++)
+ {
+ cx = clss[i].getClassLoader();
+ if (!loaders.contains(cx))
+ {
+ loaders.add(0, cx);
+ }
+ }
+ loader = new CombinedClassLoader(loaders);
+ }
+ else
+ loader = ClassLoader.getSystemClassLoader();
+
+ try
+ {
+ return Proxy.getProxyClass(loader, clss);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ClassNotFoundException(null, e);
+ }
+ }
protected Object readValue(Class valueClass) throws IOException, ClassNotFoundException {
if(valueClass.isPrimitive()){
diff --git a/libjava/classpath/gnu/java/rmi/server/UnicastServerRef.java b/libjava/classpath/gnu/java/rmi/server/UnicastServerRef.java
index 1f6eedec68a..dcb12a53b82 100644
--- a/libjava/classpath/gnu/java/rmi/server/UnicastServerRef.java
+++ b/libjava/classpath/gnu/java/rmi/server/UnicastServerRef.java
@@ -1,5 +1,5 @@
/* UnicastServerRef.java --
- Copyright (c) 1996, 1997, 1998, 1999, 2002, 2003, 2004
+ Copyright (c) 1996, 1997, 1998, 1999, 2002, 2003, 2004, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -43,263 +43,433 @@ import java.io.ObjectInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.ObjID;
import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RemoteObjectInvocationHandler;
import java.rmi.server.RemoteRef;
import java.rmi.server.RemoteServer;
import java.rmi.server.RemoteStub;
import java.rmi.server.ServerNotActiveException;
-import java.rmi.server.ServerRef;
import java.rmi.server.Skeleton;
+import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Iterator;
public class UnicastServerRef
- extends UnicastRef
- implements ServerRef{ //SHOULD implement ServerRef
+ extends UnicastRef
+{
+
+ /**
+ * Use GNU Classpath v 0.20 SVUID for interoperability
+ */
+ private static final long serialVersionUID = - 5585608108300801246L;
+
+ /**
+ * The class array, defining parameters of the jdk 1.2 RMI stub constructor.
+ */
+ private static final Class[] stubprototype = new Class[] { RemoteRef.class };
+
+ /**
+ * The exported remote object itself.
+ */
+ Remote myself; // save the remote object itself
+
+ /**
+ * The skeleton (if any), associated with the exported remote object.
+ */
+ private Skeleton skel;
+
+ /**
+ * The stub, associated with the exported remote object (may be proxy class).
+ */
+ private Remote stub;
+
+ /**
+ * The method table (RMI hash code to method) of the methods of the
+ * exported object.
+ */
+ private Hashtable methods = new Hashtable();
+
+ /**
+ * Used by serialization.
+ */
+ UnicastServerRef()
+ {
+ }
+
+ public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf)
+ throws RemoteException
+ {
+ super(id);
+ manager = UnicastConnectionManager.getInstance(port, ssf);
+ }
+
+ /**
+ * Export the object and return its remote stub. The method tries to locate
+ * existing stubs and skeletons. If this fails, the method instantiates the
+ * proxy stub class.
+ *
+ * Stubs and skeletons are always ignored (even if present) if the
+ * java.rmi.server.ignoreStubClasses property is set to true.
+ *
+ * @param obj the object being exported.
+ * @return the stub (existing class or proxy) of the exported object.
+ * @throws RemoteException if the export failed due any reason
+ */
+ public Remote exportObject(Remote obj) throws RemoteException
+ {
+ if (myself == null)
+ {
+ myself = obj;
+ // Save it to server manager, to let client calls in the same VM to
+ // issue
+ // local call
+ manager.serverobj = obj;
+
+ String ignoreStubs;
+
+ ClassLoader loader =obj.getClass().getClassLoader();
+
+ // Stubs are always searched for the bootstrap classes that may have
+ // obsolete pattern and may still need also skeletons.
+ if (loader==null)
+ ignoreStubs = "false";
+ else
+ ignoreStubs = System.getProperty("java.rmi.server.ignoreStubClasses",
+ "false");
+
+ if (! ignoreStubs.equals("true"))
+ {
+ // Find and install the stub
+ Class cls = obj.getClass();
+
+ // where ist the _Stub? (check superclasses also)
+ Class expCls = expCls = findStubSkelClass(cls);
+
+ if (expCls != null)
+ {
+ stub = (RemoteStub) getHelperClass(expCls, "_Stub");
+ // Find and install the skeleton (if there is one)
+ skel = (Skeleton) getHelperClass(expCls, "_Skel");
+ }
+ }
+
+ if (stub == null)
+ stub = createProxyStub(obj.getClass(), this);
+
+ // Build hash of methods which may be called.
+ buildMethodHash(obj.getClass(), true);
+
+ // Export it.
+ UnicastServer.exportObject(this);
+ }
-final static private Class[] stubprototype = new Class[] { RemoteRef.class };
-
-Remote myself; //save the remote object itself
-private Skeleton skel;
-private RemoteStub stub;
-private Hashtable methods = new Hashtable();
-
-/**
- * Used by serialization.
- */
-UnicastServerRef()
-{
-}
-
-public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) throws RemoteException {
- super(id);
- manager = UnicastConnectionManager.getInstance(port, ssf);
-}
-
-public RemoteStub exportObject(Remote obj) throws RemoteException {
- if (myself == null) {
- myself = obj;
- // Save it to server manager, to let client calls in the same VM to issue
- // local call
- manager.serverobj = obj;
-
- // Find and install the stub
- Class cls = obj.getClass();
- Class expCls;
- try {
- // where ist the _Stub? (check superclasses also)
- expCls = findStubSkelClass(cls);
- } catch (Exception ex) {
- throw new RemoteException("can not find stubs for class: " + cls, ex);
- }
-
- stub = (RemoteStub)getHelperClass(expCls, "_Stub");
- if (stub == null) {
- throw new RemoteException("failed to export: " + cls);
- }
-
- // Find and install the skeleton (if there is one)
- skel = (Skeleton)getHelperClass(expCls, "_Skel");
-
- // Build hash of methods which may be called.
- buildMethodHash(obj.getClass(), true);
-
- // Export it.
- UnicastServer.exportObject(this);
- }
-
- return (stub);
-}
-
-public RemoteStub exportObject(Remote remote, Object obj)
- throws RemoteException
-{
- //FIX ME
- return exportObject(remote);
-}
-
-public RemoteStub getStub(){
return stub;
-}
-
-
-public boolean unexportObject(Remote obj, boolean force) {
+ }
+
+ /**
+ * Get the stub (actual class or proxy) of the exported remote object.
+ *
+ * @return the remote stub (null if exportObject has not been called).
+ */
+ public Remote getStub()
+ {
+ return stub;
+ }
+
+ /**
+ * Unexport the object (remove methods from the method hashcode table
+ * and call UnicastServer.unexportObject.
+ *
+ * @param obj the object being unexported
+ * @param force passed to the UnicastServer.unexportObject.
+ * @return value, returned by the UnicastServer.unexportObject.
+ */
+ public boolean unexportObject(Remote obj, boolean force)
+ {
// Remove all hashes of methods which may be called.
buildMethodHash(obj.getClass(), false);
return UnicastServer.unexportObject(this, force);
-}
-
-/**
-*
-* The Subs/Skels might not there for the actual class, but maybe
-* for one of the superclasses.
-*
-*/
-private Class findStubSkelClass(Class startCls) throws Exception {
- Class cls = startCls;
-
- while (true) {
- try {
- String stubClassname = cls.getName() + "_Stub";
- ClassLoader cl = cls.getClassLoader();
- Class scls = cl == null ? Class.forName(stubClassname)
- : cl.loadClass(stubClassname);
- return cls; // found it
- } catch (ClassNotFoundException e) {
- Class superCls = cls.getSuperclass();
- if (superCls == null
- || superCls == java.rmi.server.UnicastRemoteObject.class)
- {
- throw new Exception("Neither " + startCls
- + " nor one of their superclasses (like" + cls + ")"
- + " has a _Stub");
- }
- cls = superCls;
- }
- }
-}
-
-
-
-private Object getHelperClass(Class cls, String type) {
- try {
- String classname = cls.getName();
- ClassLoader cl = cls.getClassLoader();
- Class scls = cl == null ? Class.forName(classname + type)
- : cl.loadClass(classname + type);
- if (type.equals("_Stub")) {
- try {
- // JDK 1.2 stubs
- Constructor con = scls.getConstructor(stubprototype);
- return (con.newInstance(new Object[]{this}));
- }
- catch (NoSuchMethodException e) {
- }
- catch (InstantiationException e) {
- }
- catch (IllegalAccessException e) {
- }
- catch (IllegalArgumentException e) {
- }
- catch (InvocationTargetException e) {
- }
- // JDK 1.1 stubs
- RemoteStub stub = (RemoteStub)scls.newInstance();
- UnicastRemoteStub.setStubRef(stub, this);
- return (stub);
- }
- else {
- // JDK 1.1 skel
- return (scls.newInstance());
- }
- }
- catch (ClassNotFoundException e) {
- }
- catch (InstantiationException e) {
- }
- catch (IllegalAccessException e) {
- }
- return (null);
-}
-
-
-
-public String getClientHost() throws ServerNotActiveException {
- return RemoteServer.getClientHost();
-}
-
-private void buildMethodHash(Class cls, boolean build) {
- Method[] meths = cls.getMethods();
- for (int i = 0; i < meths.length; i++) {
- /* Don't need to include any java.xxx related stuff */
- if (meths[i].getDeclaringClass().getName().startsWith("java.")) {
- continue;
- }
- long hash = RMIHashes.getMethodHash(meths[i]);
- if(build)
- methods.put(new Long (hash), meths[i]);
- else
- methods.remove(new Long (hash));
-//System.out.println("meth = " + meths[i] + ", hash = " + hash);
- }
-}
-
-Class getMethodReturnType(int method, long hash) throws Exception
-{
- if (method == -1) {
- Method meth = (Method)methods.get(new Long (hash));
+ }
+
+ /**
+ * Return the class in the hierarchy for that the stub class is defined.
+ * The Subs/Skels might not there for the actual class, but maybe for one of
+ * the superclasses.
+ *
+ * @return the class having stub defined, null if none.
+ */
+ private Class findStubSkelClass(Class startCls)
+ {
+ Class cls = startCls;
+
+ while (true)
+ {
+ try
+ {
+ String stubClassname = cls.getName() + "_Stub";
+ ClassLoader cl = cls.getClassLoader();
+ Class scls = cl == null ? Class.forName(stubClassname)
+ : cl.loadClass(stubClassname);
+ return cls; // found it
+ }
+ catch (ClassNotFoundException e)
+ {
+ Class superCls = cls.getSuperclass();
+ if (superCls == null
+ || superCls == java.rmi.server.UnicastRemoteObject.class)
+ {
+ return null;
+ }
+ cls = superCls;
+ }
+ }
+ }
+
+ /**
+ * Get the helper (assisting) class with the given type.
+ *
+ * @param cls the class, for that the helper class is requested. This class
+ * and the requested helper class must share the same class loader.
+ *
+ * @param type the type of the assisting helper. The only currently supported
+ * non deprecated value is "_Stub" (load jdk 1.1 or 1.2 RMI stub). Another
+ * (deprecated) value is "_Skel" (load skeleton).
+ *
+ * @return the instantiated instance of the helper class or null if the
+ * helper class cannot be found or instantiated.
+ */
+ private Object getHelperClass(Class cls, String type)
+ {
+ try
+ {
+ String classname = cls.getName();
+ ClassLoader cl = cls.getClassLoader();
+ Class scls = cl == null ? Class.forName(classname + type)
+ : cl.loadClass(classname + type);
+ if (type.equals("_Stub"))
+ {
+ try
+ {
+ // JDK 1.2 stubs
+ Constructor con = scls.getConstructor(stubprototype);
+ return (con.newInstance(new Object[] { this }));
+ }
+ catch (NoSuchMethodException e)
+ {
+ }
+ catch (InstantiationException e)
+ {
+ }
+ catch (IllegalAccessException e)
+ {
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+ catch (InvocationTargetException e)
+ {
+ }
+ // JDK 1.1 stubs
+ RemoteStub stub = (RemoteStub) scls.newInstance();
+ UnicastRemoteStub.setStubRef(stub, this);
+ return (stub);
+ }
+ else
+ {
+ // JDK 1.1 skel
+ return (scls.newInstance());
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ }
+ catch (InstantiationException e)
+ {
+ }
+ catch (IllegalAccessException e)
+ {
+ }
+ return (null);
+ }
+
+ public String getClientHost() throws ServerNotActiveException
+ {
+ return RemoteServer.getClientHost();
+ }
+
+ /**
+ * Build the method has code table and put it into {@link #methods}
+ * (mapping RMI hashcode tos method). The same method is used to remove
+ * the table.
+ *
+ * @param cls the class for that the method table is built.
+ * @param build if true, the class methods are added to the table. If
+ * false, they are removed from the table.
+ */
+ private void buildMethodHash(Class cls, boolean build)
+ {
+ Method[] meths = cls.getMethods();
+ for (int i = 0; i < meths.length; i++)
+ {
+ /* Don't need to include any java.xxx related stuff */
+ if (meths[i].getDeclaringClass().getName().startsWith("java."))
+ {
+ continue;
+ }
+ long hash = RMIHashes.getMethodHash(meths[i]);
+ if (build)
+ methods.put(new Long(hash), meths[i]);
+ else
+ methods.remove(new Long(hash));
+ // System.out.println("meth = " + meths[i] + ", hash = " + hash);
+ }
+ }
+
+ Class getMethodReturnType(int method, long hash) throws Exception
+ {
+ if (method == - 1)
+ {
+ Method meth = (Method) methods.get(new Long(hash));
return meth.getReturnType();
- }else
- return null;
-}
-
-public Object incomingMessageCall(UnicastConnection conn, int method, long hash) throws Exception {
-//System.out.println("method = " + method + ", hash = " + hash);
- // If method is -1 then this is JDK 1.2 RMI - so use the hash
- // to locate the method
- if (method == -1) {
- Method meth = (Method)methods.get(new Long (hash));
-//System.out.println("class = " + myself.getClass() + ", meth = " + meth);
- if (meth == null) {
- throw new NoSuchMethodException();
- }
-
- ObjectInputStream in = conn.getObjectInputStream();
- int nrargs = meth.getParameterTypes().length;
- Object[] args = new Object[nrargs];
- for (int i = 0; i < nrargs; i++) {
- /**
- * For debugging purposes - we don't handle CodeBases
- * quite right so we don't always find the stubs. This
- * lets us know that.
- */
- try {
- // need to handle primitive types
- args[i] = ((RMIObjectInputStream)in).readValue(meth.getParameterTypes()[i]);
-
- }
- catch (Exception t) {
- t.printStackTrace();
- throw t;
- }
- }
- //We must reinterpret the exception thrown by meth.invoke()
- //return (meth.invoke(myself, args));
- Object ret = null;
- try{
- ret = meth.invoke(myself, args);
- }catch(InvocationTargetException e){
- Throwable cause = e.getTargetException();
- if (cause instanceof Exception) {
- throw (Exception)cause;
- }
- else if (cause instanceof Error) {
- throw (Error)cause;
- }
- else {
- throw new Error("The remote method threw a java.lang.Throwable that is neither java.lang.Exception nor java.lang.Error.", e);
- }
- }
- return ret;
- }
- // Otherwise this is JDK 1.1 style RMI - we find the skeleton
- // and invoke it using the method number. We wrap up our
- // connection system in a UnicastRemoteCall so it appears in a
- // way the Skeleton can handle.
- else {
- if (skel == null) {
- throw new NoSuchMethodException();
- }
- UnicastRemoteCall call = new UnicastRemoteCall(conn);
- skel.dispatch(myself, call, method, hash);
- if (!call.isReturnValue())
- return RMIVoidValue.INSTANCE;
- else
- return (call.returnValue());
- }
-}
+ }
+ else
+ return null;
+ }
+
+ public Object incomingMessageCall(UnicastConnection conn, int method,
+ long hash) throws Exception
+ {
+ // System.out.println("method = " + method + ", hash = " + hash);
+ // If method is -1 then this is JDK 1.2 RMI - so use the hash
+ // to locate the method
+ if (method == - 1)
+ {
+ Method meth = (Method) methods.get(new Long(hash));
+ // System.out.println("class = " + myself.getClass() + ", meth = " +
+ // meth);
+ if (meth == null)
+ {
+ throw new NoSuchMethodException();
+ }
+
+ ObjectInputStream in = conn.getObjectInputStream();
+ int nrargs = meth.getParameterTypes().length;
+ Object[] args = new Object[nrargs];
+ for (int i = 0; i < nrargs; i++)
+ {
+ /**
+ * For debugging purposes - we don't handle CodeBases quite right so
+ * we don't always find the stubs. This lets us know that.
+ */
+ try
+ {
+ // need to handle primitive types
+ args[i] = ((RMIObjectInputStream) in)
+ .readValue(meth.getParameterTypes()[i]);
+
+ }
+ catch (Exception t)
+ {
+ t.printStackTrace();
+ throw t;
+ }
+ }
+ //We must reinterpret the exception thrown by meth.invoke()
+ //return (meth.invoke(myself, args));
+ Object ret = null;
+ try
+ {
+ ret = meth.invoke(myself, args);
+ }
+ catch (InvocationTargetException e)
+ {
+ Throwable cause = e.getTargetException();
+ if (cause instanceof Exception)
+ {
+ throw (Exception) cause;
+ }
+ else if (cause instanceof Error)
+ {
+ throw (Error) cause;
+ }
+ else
+ {
+ throw new Error(
+ "The remote method threw a java.lang.Throwable that"+
+ " is neither java.lang.Exception nor java.lang.Error.",
+ e);
+ }
+ }
+ return ret;
+ }
+ // Otherwise this is JDK 1.1 style RMI - we find the skeleton
+ // and invoke it using the method number. We wrap up our
+ // connection system in a UnicastRemoteCall so it appears in a
+ // way the Skeleton can handle.
+ else
+ {
+ if (skel == null)
+ {
+ throw new NoSuchMethodException();
+ }
+ UnicastRemoteCall call = new UnicastRemoteCall(conn);
+ skel.dispatch(myself, call, method, hash);
+ if (! call.isReturnValue())
+ return RMIVoidValue.INSTANCE;
+ else
+ return (call.returnValue());
+ }
+ }
+
+ /**
+ * Create the 1.2 proxy stub in the case when the pre-generated stub is not
+ * available of the system is explicitly instructed to use proxy stubs.
+ *
+ * @param stubFor the class for that the proxy class must be constructed.
+ * @param reference the remote reference, used to find the given object
+ *
+ * @return the applicable proxy stub.
+ *
+ * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
+ */
+ Remote createProxyStub(Class stubFor, RemoteRef reference)
+ {
+ // Collect all interfaces, implemented by stubFor and derived from
+ // Remote (also Remote itself):
+ HashSet interfaces = new HashSet();
+ Class c = stubFor;
+ Class[] intfs;
+
+ while (c != null)
+ {
+ intfs = c.getInterfaces();
+ for (int i = 0; i < intfs.length; i++)
+ {
+ if (Remote.class.isAssignableFrom(intfs[i]))
+ interfaces.add(intfs[i]);
+ }
+ c = c.getSuperclass();
+ }
+
+ intfs = new Class[interfaces.size()];
+ Iterator it = interfaces.iterator();
+
+ for (int i = 0; i < intfs.length; i++)
+ intfs[i] = (Class) it.next();
+
+ RemoteObjectInvocationHandler handler =
+ new RemoteObjectInvocationHandler(reference);
+
+ Object proxy =
+ Proxy.newProxyInstance(stubFor.getClassLoader(), intfs, handler);
+
+ return (Remote) proxy;
+ }
+
}
diff --git a/libjava/classpath/gnu/java/security/Properties.java b/libjava/classpath/gnu/java/security/Properties.java
new file mode 100644
index 00000000000..813888c20a8
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/Properties.java
@@ -0,0 +1,374 @@
+/* Properties.java -- run-time configuration properties.
+ Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.PropertyPermission;
+
+/**
+ * <p>A global object containing build-specific properties that affect the
+ * behaviour of the generated binaries from this library.</p>
+ */
+public final class Properties
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "Properties";
+
+ private static final boolean DEBUG = false;
+
+ // private static final int debuglevel = 9;
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(final String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final String VERSION = "gnu.crypto.version";
+
+ public static final String PROPERTIES_FILE = "gnu.crypto.properties.file";
+
+ public static final String REPRODUCIBLE_PRNG = "gnu.crypto.with.reproducible.prng";
+
+ public static final String CHECK_WEAK_KEYS = "gnu.crypto.with.check.for.weak.keys";
+
+ public static final String DO_RSA_BLINDING = "gnu.crypto.with.rsa.blinding";
+
+ private static final String TRUE = Boolean.TRUE.toString();
+
+ private static final String FALSE = Boolean.FALSE.toString();
+
+ private static final HashMap props = new HashMap();
+
+ private static Properties singleton = null;
+
+ private boolean reproducible = false;
+
+ private boolean checkForWeakKeys = true;
+
+ private boolean doRSABlinding = true;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private Properties()
+ {
+ super();
+ init();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the string representation of the library global configuration
+ * property with the designated <code>key</code>.</p>
+ *
+ * @param key the case-insensitive, non-null and non-empty name of a
+ * configuration property.
+ * @return the string representation of the designated property, or
+ * <code>null</code> if such property is not yet set, or <code>key</code> is
+ * empty.
+ */
+ public static final synchronized String getProperty(String key)
+ {
+ if (key == null)
+ return null;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(key, "read"));
+ key = key.trim().toLowerCase();
+ if ("".equals(key))
+ return null;
+ return (String) props.get(key);
+ }
+
+ /**
+ * <p>Sets the value of a designated library global configuration property,
+ * to a string representation of what should be a legal value.</p>
+ *
+ * @param key the case-insensitive, non-null and non-empty name of a
+ * configuration property.
+ * @param value the non-null, non-empty string representation of a legal
+ * value of the configuration property named by <code>key</code>.
+ */
+ public static final synchronized void setProperty(String key, String value)
+ {
+ if (key == null || value == null)
+ return;
+ key = key.trim().toLowerCase();
+ if ("".equals(key))
+ return;
+ if (key.equals(VERSION))
+ return;
+ value = value.trim();
+ if ("".equals(value))
+ return;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(key, "write"));
+ if (key.equals(REPRODUCIBLE_PRNG)
+ && (value.equalsIgnoreCase(TRUE) || value.equalsIgnoreCase(FALSE)))
+ setReproducible(Boolean.valueOf(value).booleanValue());
+ else if (key.equals(CHECK_WEAK_KEYS)
+ && (value.equalsIgnoreCase(TRUE) || value.equalsIgnoreCase(FALSE)))
+ setCheckForWeakKeys(Boolean.valueOf(value).booleanValue());
+ else if (key.equals(DO_RSA_BLINDING)
+ && (value.equalsIgnoreCase(TRUE) || value.equalsIgnoreCase(FALSE)))
+ setDoRSABlinding(Boolean.valueOf(value).booleanValue());
+ else
+ props.put(key, value);
+ }
+
+ /**
+ * <p>A convenience method that returns, as a boolean, the library global
+ * configuration property indicating if the default Pseudo Random Number
+ * Generator produces, or not, the same bit stream when instantiated.</p>
+ *
+ * @return <code>true</code> if the default PRNG produces the same bit stream
+ * with every VM instance. Returns <code>false</code> if the default PRNG is
+ * seeded with the time of day of its first invocation.
+ */
+ public static final synchronized boolean isReproducible()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(REPRODUCIBLE_PRNG, "read"));
+ return instance().reproducible;
+ }
+
+ /**
+ * <p>A convenience method that returns, as a boolean, the library global
+ * configuration property indicating if the implementations of symmetric
+ * key block ciphers check, or not, for possible/potential weak and semi-weak
+ * keys that may be produced in the course of generating round encryption
+ * and/or decryption keys.</p>
+ *
+ * @return <code>true</code> if the cipher implementations check for weak and
+ * semi-weak keys. Returns <code>false</code> if the cipher implementations
+ * do not check for weak or semi-weak keys.
+ */
+ public static final synchronized boolean checkForWeakKeys()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(CHECK_WEAK_KEYS, "read"));
+ return instance().checkForWeakKeys;
+ }
+
+ /**
+ * <p>A convenience method that returns, as a boolean, the library global
+ * configuration property indicating if RSA decryption (RSADP primitive),
+ * does, or not, blinding against timing attacks.</p>
+ *
+ * @return <code>true</code> if the RSA decryption primitive includes a
+ * blinding operation. Returns <code>false</code> if the RSA decryption
+ * primitive does not include the additional blinding operation.
+ */
+ public static final synchronized boolean doRSABlinding()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(DO_RSA_BLINDING, "read"));
+ return instance().doRSABlinding;
+ }
+
+ /**
+ * <p>A convenience method to set the global property for reproducibility of
+ * the default PRNG bit stream output.</p>
+ *
+ * @param value if <code>true</code> then the default PRNG bit stream output
+ * is the same with every invocation of the VM.
+ */
+ public static final synchronized void setReproducible(final boolean value)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(REPRODUCIBLE_PRNG, "write"));
+ instance().reproducible = value;
+ props.put(REPRODUCIBLE_PRNG, String.valueOf(value));
+ }
+
+ /**
+ * <p>A convenience method to set the global property for checking for weak
+ * and semi-weak cipher keys.</p>
+ *
+ * @param value if <code>true</code> then the cipher implementations will
+ * invoke additional checks for weak and semi-weak key values that may get
+ * generated.
+ */
+ public static final synchronized void setCheckForWeakKeys(final boolean value)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(CHECK_WEAK_KEYS, "write"));
+ instance().checkForWeakKeys = value;
+ props.put(CHECK_WEAK_KEYS, String.valueOf(value));
+ }
+
+ /**
+ * <p>A convenience method to set the global property fo adding a blinding
+ * operation when executing the RSA decryption primitive.</p>
+ *
+ * @param value if <code>true</code> then the code for performing the RSA
+ * decryption primitive will include a blinding operation.
+ */
+ public static final synchronized void setDoRSABlinding(final boolean value)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(DO_RSA_BLINDING, "write"));
+ instance().doRSABlinding = value;
+ props.put(DO_RSA_BLINDING, String.valueOf(value));
+ }
+
+ private static final synchronized Properties instance()
+ {
+ if (singleton == null)
+ singleton = new Properties();
+ return singleton;
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+ private void init()
+ {
+ // default values
+ props.put(REPRODUCIBLE_PRNG, (reproducible ? "true" : "false"));
+ props.put(CHECK_WEAK_KEYS, (checkForWeakKeys ? "true" : "false"));
+ props.put(DO_RSA_BLINDING, (doRSABlinding ? "true" : "false"));
+
+ // 1. allow site-wide override by reading a properties file
+ String propFile = null;
+ try
+ {
+ propFile = (String) AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return System.getProperty(PROPERTIES_FILE);
+ }
+ });
+ }
+ catch (SecurityException se)
+ {
+ if (DEBUG)
+ debug("Reading property " + PROPERTIES_FILE
+ + " not allowed. Ignored.");
+ }
+ if (propFile != null)
+ {
+ try
+ {
+ final java.util.Properties temp = new java.util.Properties();
+ final FileInputStream fin = new FileInputStream(propFile);
+ temp.load(fin);
+ temp.list(System.out);
+ props.putAll(temp);
+ }
+ catch (IOException ioe)
+ {
+ if (DEBUG)
+ debug("IO error reading " + propFile + ": " + ioe.getMessage());
+ }
+ catch (SecurityException se)
+ {
+ if (DEBUG)
+ debug("Security error reading " + propFile + ": "
+ + se.getMessage());
+ }
+ }
+
+ // 2. allow vm-specific override by allowing -D options in launcher
+ handleBooleanProperty(REPRODUCIBLE_PRNG);
+ handleBooleanProperty(CHECK_WEAK_KEYS);
+ handleBooleanProperty(DO_RSA_BLINDING);
+
+ // re-sync the 'known' properties
+ reproducible = new Boolean((String) props.get(REPRODUCIBLE_PRNG)).booleanValue();
+ checkForWeakKeys = new Boolean((String) props.get(CHECK_WEAK_KEYS)).booleanValue();
+ doRSABlinding = new Boolean((String) props.get(DO_RSA_BLINDING)).booleanValue();
+
+ // This does not change.
+ props.put(VERSION, Registry.VERSION_STRING);
+ }
+
+ private void handleBooleanProperty(final String name)
+ {
+ String s = null;
+ try
+ {
+ s = System.getProperty(name);
+ }
+ catch (SecurityException x)
+ {
+ if (DEBUG)
+ debug("SecurityManager forbids reading system properties. Ignored");
+ }
+ if (s != null)
+ {
+ s = s.trim().toLowerCase();
+ // we have to test for explicit "true" or "false". anything else may
+ // hide valid value set previously
+ if (s.equals(TRUE) || s.equals(FALSE))
+ {
+ if (DEBUG)
+ debug("Setting " + name + " to '" + s + "'");
+ props.put(name, s);
+ }
+ else
+ {
+ if (DEBUG)
+ debug("Invalid value for -D" + name + ": " + s + ". Ignored");
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/Registry.java b/libjava/classpath/gnu/java/security/Registry.java
new file mode 100644
index 00000000000..efb54e71470
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/Registry.java
@@ -0,0 +1,455 @@
+/* Registry.java --
+ Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security;
+
+/**
+ * A placeholder for <i>names</i> and <i>literals</i> used throughout this
+ * library.
+ */
+public interface Registry
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** The name of our Providers. */
+ String GNU_SECURITY = "GNU";
+ String GNU_CRYPTO = "GNU-CRYPTO";
+ String GNU_SASL = "GNU-SASL";
+
+ /** Our version number. */
+ String VERSION_STRING = "2.1.0";
+
+ // Names of properties to use in Maps when initialising primitives .........
+
+ // Symmetric block cipher algorithms and synonyms...........................
+
+ String ANUBIS_CIPHER = "anubis";
+
+ String BLOWFISH_CIPHER = "blowfish";
+
+ String DES_CIPHER = "des";
+
+ String KHAZAD_CIPHER = "khazad";
+
+ String RIJNDAEL_CIPHER = "rijndael";
+
+ String SERPENT_CIPHER = "serpent";
+
+ String SQUARE_CIPHER = "square";
+
+ String TRIPLEDES_CIPHER = "tripledes";
+
+ String TWOFISH_CIPHER = "twofish";
+
+ String CAST5_CIPHER = "cast5";
+
+ String NULL_CIPHER = "null";
+
+ /** AES is synonymous to Rijndael for 128-bit block size only. */
+ String AES_CIPHER = "aes";
+
+ /** TripleDES is also known as DESede. */
+ String DESEDE_CIPHER = "desede";
+
+ /** CAST5 is also known as CAST-128. */
+ String CAST128_CIPHER = "cast128";
+
+ String CAST_128_CIPHER = "cast-128";
+
+ // Message digest algorithms and synonyms...................................
+
+ String WHIRLPOOL_HASH = "whirlpool";
+
+ String RIPEMD128_HASH = "ripemd128";
+
+ String RIPEMD160_HASH = "ripemd160";
+
+ String SHA160_HASH = "sha-160";
+
+ String SHA256_HASH = "sha-256";
+
+ String SHA384_HASH = "sha-384";
+
+ String SHA512_HASH = "sha-512";
+
+ String TIGER_HASH = "tiger";
+
+ String HAVAL_HASH = "haval";
+
+ String MD5_HASH = "md5";
+
+ String MD4_HASH = "md4";
+
+ String MD2_HASH = "md2";
+
+ /** RIPEMD-128 is synonymous to RIPEMD128. */
+ String RIPEMD_128_HASH = "ripemd-128";
+
+ /** RIPEMD-160 is synonymous to RIPEMD160. */
+ String RIPEMD_160_HASH = "ripemd-160";
+
+ /** SHA-1 is synonymous to SHA-160. */
+ String SHA_1_HASH = "sha-1";
+
+ /** SHA1 is synonymous to SHA-160. */
+ String SHA1_HASH = "sha1";
+
+ /** SHA is synonymous to SHA-160. */
+ String SHA_HASH = "sha";
+
+ // Symmetric block cipher modes of operations...............................
+
+ /** Electronic CodeBook mode. */
+ String ECB_MODE = "ecb";
+
+ /** Counter (NIST) mode. */
+ String CTR_MODE = "ctr";
+
+ /** Integer Counter Mode (David McGrew). */
+ String ICM_MODE = "icm";
+
+ /** Output Feedback Mode (NIST). */
+ String OFB_MODE = "ofb";
+
+ /** Cipher block chaining mode (NIST). */
+ String CBC_MODE = "cbc";
+
+ /** Cipher feedback mode (NIST). */
+ String CFB_MODE = "cfb";
+
+ /** Authenticated-Encrypted mode. */
+ String EAX_MODE = "eax";
+
+ // Padding scheme names and synonyms........................................
+
+ /** PKCS#7 padding scheme. */
+ String PKCS7_PAD = "pkcs7";
+
+ /** Trailing Bit Complement padding scheme. */
+ String TBC_PAD = "tbc";
+
+ /** EME-PKCS1-v1_5 padding as described in section 7.2 in RFC-3447. */
+ String EME_PKCS1_V1_5_PAD = "eme-pkcs1-v1.5";
+
+ /** SSLv3 padding scheme. */
+ String SSL3_PAD = "ssl3";
+
+ /** TLSv1 padding scheme. */
+ String TLS1_PAD = "tls1";
+
+ // Pseudo-random number generators..........................................
+
+ /** (Apparently) RC4 keystream PRNG. */
+ String ARCFOUR_PRNG = "arcfour";
+
+ /** We use "rc4" as an alias for "arcfour". */
+ String RC4_PRNG = "rc4";
+
+ /** PRNG based on David McGrew's Integer Counter Mode. */
+ String ICM_PRNG = "icm";
+
+ /** PRNG based on a designated hash function. */
+ String MD_PRNG = "md";
+
+ /** PRNG based on UMAC's Key Derivation Function. */
+ String UMAC_PRNG = "umac-kdf";
+
+ /**
+ * PRNG based on PBKDF2 from PKCS #5 v.2. This is suffixed with the name
+ * of a MAC to be used as a PRF.
+ */
+ String PBKDF2_PRNG_PREFIX = "pbkdf2-";
+
+ /** The continuously-seeded pseudo-random number generator. */
+ String CSPRNG_PRNG = "csprng";
+
+ /** The Fortuna PRNG. */
+ String FORTUNA_PRNG = "fortuna";
+
+ /** The Fortuna generator PRNG. */
+ String FORTUNA_GENERATOR_PRNG = "fortuna-generator";
+
+ // Asymmetric keypair generators............................................
+
+ String DSS_KPG = "dss";
+
+ String RSA_KPG = "rsa";
+
+ String DH_KPG = "dh";
+
+ String SRP_KPG = "srp";
+
+ /** DSA is synonymous to DSS. */
+ String DSA_KPG = "dsa";
+
+ // Signature-with-appendix schemes..........................................
+
+ String DSS_SIG = "dss";
+
+ String RSA_SIG_PREFIX = "rsa-";
+
+ String RSA_PSS_ENCODING = "pss";
+
+ String RSA_PSS_SIG = RSA_SIG_PREFIX + RSA_PSS_ENCODING;
+
+ String RSA_PKCS1_V1_5_ENCODING = "pkcs1-v1.5";
+
+ String RSA_PKCS1_V1_5_SIG = RSA_SIG_PREFIX + RSA_PKCS1_V1_5_ENCODING;
+
+ /** DSA is synonymous to DSS. */
+ String DSA_SIG = "dsa";
+
+ // Key agreement protocols .................................................
+
+ String DH_KA = "dh";
+
+ String ELGAMAL_KA = "elgamal";
+
+ String SRP6_KA = "srp6";
+
+ String SRP_SASL_KA = "srp-sasl";
+
+ String SRP_TLS_KA = "srp-tls";
+
+ // Keyed-Hash Message Authentication Code ..................................
+
+ /** Name prefix of every HMAC implementation. */
+ String HMAC_NAME_PREFIX = "hmac-";
+
+ // Other MAC algorithms ....................................................
+
+ /** The One-key CBC MAC. */
+ String OMAC_PREFIX = "omac-";
+
+ /** Message Authentication Code using Universal Hashing (Ted Krovetz). */
+ String UHASH32 = "uhash32";
+
+ String UMAC32 = "umac32";
+
+ /** The Truncated Multi-Modular Hash Function -v1 (David McGrew). */
+ String TMMH16 = "tmmh16";
+
+ // String TMMH32 = "tmmh32";
+
+ // Format IDs used to identify how we externalise asymmetric keys ..........
+ // fully-qualified names of the supported codecs
+ String RAW_ENCODING = "gnu.crypto.raw.format";
+ String X509_ENCODING = "gnu.crypto.x509.format";
+ String PKCS8_ENCODING = "gnu.crypto.pkcs8.format";
+ String ASN1_ENCODING = "gnu.crypto.asn1.format";
+
+ // short names of the same. used by JCE adapters
+ String RAW_ENCODING_SHORT_NAME = "RAW";
+ String X509_ENCODING_SORT_NAME = "X.509";
+ String PKCS8_ENCODING_SHORT_NAME = "PKCS#8";
+ String ASN1_ENCODING_SHORT_NAME = "ASN.1";
+
+ // unique identifiers of the same
+ int RAW_ENCODING_ID = 1;
+ int X509_ENCODING_ID = 2;
+ int PKCS8_ENCODING_ID = 3;
+ int ASN1_ENCODING_ID = 4;
+
+ // OID strings used in encoding/decoding keys
+ String DSA_OID_STRING = "1.2.840.10040.4.1";
+ String RSA_OID_STRING = "1.2.840.113549.1.1.1";
+ String DH_OID_STRING = "1.2.840.10046.2.1";
+
+ // Magic bytes we generate/expect in externalised asymmetric keys ..........
+ // the four bytes represent G (0x47) for GNU, 1 (0x01) for Raw format,
+ // D (0x44) for DSS, R (0x52) for RSA, H (0x48) for Diffie-Hellman, or S
+ // (0x53) for SRP-6, and finally P (0x50) for Public, p (0x70) for private,
+ // or S (0x53) for signature.
+ byte[] MAGIC_RAW_DSS_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
+ 0x50 };
+
+ byte[] MAGIC_RAW_DSS_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
+ 0x70 };
+
+ byte[] MAGIC_RAW_DSS_SIGNATURE = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
+ 0x53 };
+
+ byte[] MAGIC_RAW_RSA_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x52,
+ 0x50 };
+
+ byte[] MAGIC_RAW_RSA_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x52,
+ 0x70 };
+
+ byte[] MAGIC_RAW_RSA_PSS_SIGNATURE = new byte[] { 0x47, RAW_ENCODING_ID,
+ 0x52, 0x53 };
+
+ byte[] MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE = new byte[] { 0x47, RAW_ENCODING_ID,
+ 0x52, 0x54 };
+
+ byte[] MAGIC_RAW_DH_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x48,
+ 0x50 };
+
+ byte[] MAGIC_RAW_DH_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x48,
+ 0x70 };
+
+ byte[] MAGIC_RAW_SRP_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x53,
+ 0x50 };
+
+ byte[] MAGIC_RAW_SRP_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x53,
+ 0x70 };
+
+ // SASL Property names .....................................................
+
+ String SASL_PREFIX = "gnu.crypto.sasl";
+
+ /** Name of username property. */
+ String SASL_USERNAME = SASL_PREFIX + ".username";
+
+ /** Name of password property. */
+ String SASL_PASSWORD = SASL_PREFIX + ".password";
+
+ /** Name of authentication information provider packages. */
+ String SASL_AUTH_INFO_PROVIDER_PKGS = SASL_PREFIX
+ + ".auth.info.provider.pkgs";
+
+ /** SASL authorization ID. */
+ String SASL_AUTHORISATION_ID = SASL_PREFIX + ".authorisation.ID";
+
+ /** SASL protocol. */
+ String SASL_PROTOCOL = SASL_PREFIX + ".protocol";
+
+ /** SASL Server name. */
+ String SASL_SERVER_NAME = SASL_PREFIX + ".server.name";
+
+ /** SASL Callback handler. */
+ String SASL_CALLBACK_HANDLER = SASL_PREFIX + ".callback.handler";
+
+ /** SASL channel binding. */
+ String SASL_CHANNEL_BINDING = SASL_PREFIX + ".channel.binding";
+
+ // SASL data element size limits ...........................................
+
+ /** The size limit, in bytes, of a SASL OS (Octet Sequence) element. */
+ int SASL_ONE_BYTE_MAX_LIMIT = 255;
+
+ /**
+ * The size limit, in bytes, of both a SASL MPI (Multi-Precision Integer)
+ * element and a SASL Text element.
+ */
+ int SASL_TWO_BYTE_MAX_LIMIT = 65535;
+
+ /** The size limit, in bytes, of a SASL EOS (Extended Octet Sequence) element. */
+ int SASL_FOUR_BYTE_MAX_LIMIT = 2147483383;
+
+ /** The size limit, in bytes, of a SASL Buffer. */
+ int SASL_BUFFER_MAX_LIMIT = 2147483643;
+
+ // Canonical names of SASL mechanisms ......................................
+
+ String SASL_ANONYMOUS_MECHANISM = "ANONYMOUS";
+
+ String SASL_CRAM_MD5_MECHANISM = "CRAM-MD5";
+
+ String SASL_PLAIN_MECHANISM = "PLAIN";
+
+ String SASL_SRP_MECHANISM = "SRP";
+
+ // Canonical names of Integrity Protection algorithms ......................
+
+ String SASL_HMAC_MD5_IALG = "HMACwithMD5";
+
+ String SASL_HMAC_SHA_IALG = "HMACwithSHA";
+
+ // Quality Of Protection string representations ............................
+
+ /** authentication only. */
+ String QOP_AUTH = "auth";
+
+ /** authentication plus integrity protection. */
+ String QOP_AUTH_INT = "auth-int";
+
+ /** authentication plus integrity and confidentiality protection. */
+ String QOP_AUTH_CONF = "auth-conf";
+
+ // SASL mechanism strength string representation ...........................
+
+ String STRENGTH_HIGH = "high";
+
+ String STRENGTH_MEDIUM = "medium";
+
+ String STRENGTH_LOW = "low";
+
+ // SASL Server Authentication requirement ..................................
+
+ /** Server must authenticate to the client. */
+ String SERVER_AUTH_TRUE = "true";
+
+ /** Server does not need to, or cannot, authenticate to the client. */
+ String SERVER_AUTH_FALSE = "false";
+
+ // SASL mechanism reuse capability .........................................
+
+ String REUSE_TRUE = "true";
+
+ String REUSE_FALSE = "false";
+
+ // Keyrings ...............................................................
+
+ byte[] GKR_MAGIC = new byte[] { 0x47, 0x4b, 0x52, 0x01 };
+
+ // Ring usage fields.
+ int GKR_PRIVATE_KEYS = 1 << 0;
+
+ int GKR_PUBLIC_CREDENTIALS = 1 << 1;
+
+ int GKR_CERTIFICATES = 1 << 2;
+
+ // HMac types.
+ int GKR_HMAC_MD5_128 = 0;
+
+ int GKR_HMAC_SHA_160 = 1;
+
+ int GKR_HMAC_MD5_96 = 2;
+
+ int GKR_HMAC_SHA_96 = 3;
+
+ // Cipher types.
+ int GKR_CIPHER_AES_128_OFB = 0;
+
+ int GKR_CIPHER_AES_128_CBC = 1;
+
+ // Methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/der/DERValue.java b/libjava/classpath/gnu/java/security/der/DERValue.java
index 9a597d724cc..d98ce78ec55 100644
--- a/libjava/classpath/gnu/java/security/der/DERValue.java
+++ b/libjava/classpath/gnu/java/security/der/DERValue.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.java.security.der;
+import gnu.java.security.x509.Util;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -108,7 +110,9 @@ public class DERValue implements DER
}
catch (IOException ioe)
{
- encoded = new byte[0];
+ IllegalArgumentException iae = new IllegalArgumentException ();
+ iae.initCause (ioe);
+ throw iae;
}
}
return length;
@@ -138,7 +142,9 @@ public class DERValue implements DER
}
catch (IOException ioe)
{
- encoded = new byte[0];
+ IllegalArgumentException iae = new IllegalArgumentException ();
+ iae.initCause (ioe);
+ throw iae;
}
}
return (byte[]) encoded.clone();
@@ -156,7 +162,9 @@ public class DERValue implements DER
}
catch (IOException ioe)
{
- encoded = new byte[0];
+ IllegalArgumentException iae = new IllegalArgumentException ();
+ iae.initCause (ioe);
+ throw iae;
}
}
return encoded.length;
@@ -164,7 +172,18 @@ public class DERValue implements DER
public String toString()
{
- return "DERValue [ tag=" + tag + ", class=" + tagClass + ", constructed="
- + constructed + ", value=" + value + " ]";
+ String start = "DERValue ( [";
+ if (tagClass == DER.UNIVERSAL)
+ start = start + "UNIVERSAL ";
+ else if (tagClass == DER.PRIVATE)
+ start = start + "PRIVATE ";
+ else if (tagClass == DER.APPLICATION)
+ start = start + "APPLICATION ";
+ start = start + tag + "] constructed=" + constructed + ", value=";
+ if (constructed)
+ start = start + "\n" + Util.hexDump(getEncoded(), "\t");
+ else
+ start = start + value;
+ return start + " )";
}
}
diff --git a/libjava/classpath/gnu/java/security/der/DERWriter.java b/libjava/classpath/gnu/java/security/der/DERWriter.java
index 78524fc949f..0c26336053c 100644
--- a/libjava/classpath/gnu/java/security/der/DERWriter.java
+++ b/libjava/classpath/gnu/java/security/der/DERWriter.java
@@ -84,6 +84,12 @@ public class DERWriter implements DER
public static int write(OutputStream out, DERValue object)
throws IOException
{
+ if (DER.CONSTRUCTED_VALUE.equals (object.getValue ()))
+ {
+ out.write (object.getEncoded ());
+ return object.getLength ();
+ }
+
out.write(object.getExternalTag());
Object value = object.getValue();
if (value == null)
@@ -216,10 +222,10 @@ public class DERWriter implements DER
throws IOException
{
byte[] buf = bs.getShiftedByteArray();
- out.write(buf.length + 1);
+ writeLength(out, buf.length + 1);
out.write(bs.getIgnoredBits());
out.write(buf);
- return buf.length;
+ return buf.length + 1;
}
private static int writeString(OutputStream out, int tag, String str)
diff --git a/libjava/classpath/gnu/java/security/hash/BaseHash.java b/libjava/classpath/gnu/java/security/hash/BaseHash.java
new file mode 100644
index 00000000000..720b835392a
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/BaseHash.java
@@ -0,0 +1,206 @@
+/* BaseHash.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+/**
+ * <p>A base abstract class to facilitate hash implementations.</p>
+ */
+public abstract class BaseHash implements IMessageDigest
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of the hash. */
+ protected String name;
+
+ /** The hash (output) size in bytes. */
+ protected int hashSize;
+
+ /** The hash (inner) block size in bytes. */
+ protected int blockSize;
+
+ /** Number of bytes processed so far. */
+ protected long count;
+
+ /** Temporary input buffer. */
+ protected byte[] buffer;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name prefix of this instance.
+ * @param hashSize the block size of the output in bytes.
+ * @param blockSize the block size of the internal transform.
+ */
+ protected BaseHash(String name, int hashSize, int blockSize)
+ {
+ super();
+
+ this.name = name;
+ this.hashSize = hashSize;
+ this.blockSize = blockSize;
+ this.buffer = new byte[blockSize];
+
+ resetContext();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IMessageDigest interface implementation ---------------------------------
+
+ public String name()
+ {
+ return name;
+ }
+
+ public int hashSize()
+ {
+ return hashSize;
+ }
+
+ public int blockSize()
+ {
+ return blockSize;
+ }
+
+ public void update(byte b)
+ {
+ // compute number of bytes still unhashed; ie. present in buffer
+ int i = (int) (count % blockSize);
+ count++;
+ buffer[i] = b;
+ if (i == (blockSize - 1))
+ {
+ transform(buffer, 0);
+ }
+ }
+
+ public void update(byte[] b)
+ {
+ update(b, 0, b.length);
+ }
+
+ public void update(byte[] b, int offset, int len)
+ {
+ int n = (int) (count % blockSize);
+ count += len;
+ int partLen = blockSize - n;
+ int i = 0;
+
+ if (len >= partLen)
+ {
+ System.arraycopy(b, offset, buffer, n, partLen);
+ transform(buffer, 0);
+ for (i = partLen; i + blockSize - 1 < len; i += blockSize)
+ {
+ transform(b, offset + i);
+ }
+ n = 0;
+ }
+
+ if (i < len)
+ {
+ System.arraycopy(b, offset + i, buffer, n, len - i);
+ }
+ }
+
+ public byte[] digest()
+ {
+ byte[] tail = padBuffer(); // pad remaining bytes in buffer
+ update(tail, 0, tail.length); // last transform of a message
+ byte[] result = getResult(); // make a result out of context
+
+ reset(); // reset this instance for future re-use
+
+ return result;
+ }
+
+ public void reset()
+ { // reset this instance for future re-use
+ count = 0L;
+ for (int i = 0; i < blockSize;)
+ {
+ buffer[i++] = 0;
+ }
+
+ resetContext();
+ }
+
+ // methods to be implemented by concrete subclasses ------------------------
+
+ public abstract Object clone();
+
+ public abstract boolean selfTest();
+
+ /**
+ * <p>Returns the byte array to use as padding before completing a hash
+ * operation.</p>
+ *
+ * @return the bytes to pad the remaining bytes in the buffer before
+ * completing a hash operation.
+ */
+ protected abstract byte[] padBuffer();
+
+ /**
+ * <p>Constructs the result from the contents of the current context.</p>
+ *
+ * @return the output of the completed hash operation.
+ */
+ protected abstract byte[] getResult();
+
+ /** Resets the instance for future re-use. */
+ protected abstract void resetContext();
+
+ /**
+ * <p>The block digest transformation per se.</p>
+ *
+ * @param in the <i>blockSize</i> long block, as an array of bytes to digest.
+ * @param offset the index where the data to digest is located within the
+ * input buffer.
+ */
+ protected abstract void transform(byte[] in, int offset);
+}
diff --git a/libjava/classpath/gnu/java/security/hash/HashFactory.java b/libjava/classpath/gnu/java/security/hash/HashFactory.java
new file mode 100644
index 00000000000..e5209212365
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/HashFactory.java
@@ -0,0 +1,178 @@
+/* HashFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>A <i>Factory</i> to instantiate message digest algorithm instances.</p>
+ */
+public class HashFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce <i>Singleton</i> pattern. */
+ private HashFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Return an instance of a hash algorithm given its name.</p>
+ *
+ * @param name the name of the hash algorithm.
+ * @return an instance of the hash algorithm, or null if none found.
+ * @exception InternalError if the implementation does not pass its self-
+ * test.
+ */
+ public static IMessageDigest getInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ IMessageDigest result = null;
+ if (name.equalsIgnoreCase(Registry.WHIRLPOOL_HASH))
+ {
+ result = new Whirlpool();
+ }
+ else if (name.equalsIgnoreCase(Registry.RIPEMD128_HASH)
+ || name.equalsIgnoreCase(Registry.RIPEMD_128_HASH))
+ {
+ result = new RipeMD128();
+ }
+ else if (name.equalsIgnoreCase(Registry.RIPEMD160_HASH)
+ || name.equalsIgnoreCase(Registry.RIPEMD_160_HASH))
+ {
+ result = new RipeMD160();
+ }
+ else if (name.equalsIgnoreCase(Registry.SHA160_HASH)
+ || name.equalsIgnoreCase(Registry.SHA_1_HASH)
+ || name.equalsIgnoreCase(Registry.SHA1_HASH)
+ || name.equalsIgnoreCase(Registry.SHA_HASH))
+ {
+ result = new Sha160();
+ }
+ else if (name.equalsIgnoreCase(Registry.SHA256_HASH))
+ {
+ result = new Sha256();
+ }
+ else if (name.equalsIgnoreCase(Registry.SHA384_HASH))
+ {
+ result = new Sha384();
+ }
+ else if (name.equalsIgnoreCase(Registry.SHA512_HASH))
+ {
+ result = new Sha512();
+ }
+ else if (name.equalsIgnoreCase(Registry.TIGER_HASH))
+ {
+ result = new Tiger();
+ }
+ else if (name.equalsIgnoreCase(Registry.HAVAL_HASH))
+ {
+ result = new Haval();
+ }
+ else if (name.equalsIgnoreCase(Registry.MD5_HASH))
+ {
+ result = new MD5();
+ }
+ else if (name.equalsIgnoreCase(Registry.MD4_HASH))
+ {
+ result = new MD4();
+ }
+ else if (name.equalsIgnoreCase(Registry.MD2_HASH))
+ {
+ result = new MD2();
+ }
+ else if (name.equalsIgnoreCase(Registry.HAVAL_HASH))
+ {
+ result = new Haval();
+ }
+
+ if (result != null && !result.selfTest())
+ {
+ throw new InternalError(result.name());
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of names of hash algorithms supported by this
+ * <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of hash names (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.WHIRLPOOL_HASH);
+ hs.add(Registry.RIPEMD128_HASH);
+ hs.add(Registry.RIPEMD160_HASH);
+ hs.add(Registry.SHA160_HASH);
+ hs.add(Registry.SHA256_HASH);
+ hs.add(Registry.SHA384_HASH);
+ hs.add(Registry.SHA512_HASH);
+ hs.add(Registry.TIGER_HASH);
+ hs.add(Registry.HAVAL_HASH);
+ hs.add(Registry.MD5_HASH);
+ hs.add(Registry.MD4_HASH);
+ hs.add(Registry.MD2_HASH);
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/hash/Haval.java b/libjava/classpath/gnu/java/security/hash/Haval.java
new file mode 100644
index 00000000000..f9f3282f278
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/Haval.java
@@ -0,0 +1,759 @@
+/* Haval.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>The <i>HAVAL</i> message-digest algorithm is a variable output length,
+ * with variable number of rounds. By default, this implementation allows
+ * <i>HAVAL</i> to be used as a drop-in replacement for <i>MD5</i>.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>HAVAL - A One-Way Hashing Algorithm with Variable Length of Output<br>
+ * Advances in Cryptology - AUSCRYPT'92, Lecture Notes in Computer Science,<br>
+ * Springer-Verlag, 1993; <br>
+ * Y. Zheng, J. Pieprzyk and J. Seberry.</li>
+ * </ol>
+ */
+public class Haval extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int HAVAL_VERSION = 1;
+
+ public static final int HAVAL_128_BIT = 16;
+
+ public static final int HAVAL_160_BIT = 20;
+
+ public static final int HAVAL_192_BIT = 24;
+
+ public static final int HAVAL_224_BIT = 28;
+
+ public static final int HAVAL_256_BIT = 32;
+
+ public static final int HAVAL_3_ROUND = 3;
+
+ public static final int HAVAL_4_ROUND = 4;
+
+ public static final int HAVAL_5_ROUND = 5;
+
+ private static final int BLOCK_SIZE = 128; // inner block size in bytes
+
+ private static final String DIGEST0 = "C68F39913F901F3DDF44C707357A7D70";
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /**
+ * Number of HAVAL rounds. Allowed values are integers in the range <code>3
+ * .. 5</code>. The default is <code>3</code>.
+ */
+ private int rounds = HAVAL_3_ROUND;
+
+ /** 128-bit interim result. */
+ private int h0, h1, h2, h3, h4, h5, h6, h7;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Calls the constructor with two argument using {@link #HAVAL_128_BIT} as
+ * the value for the output size (i.e. <code>128</code> bits, and
+ * {@link #HAVAL_3_ROUND} for the value of number of rounds.</p>
+ */
+ public Haval()
+ {
+ this(HAVAL_128_BIT, HAVAL_3_ROUND);
+ }
+
+ /**
+ * <p>Calls the constructor with two arguments using the designated output
+ * size, and {@link #HAVAL_3_ROUND} for the value of number of rounds.</p>
+ *
+ * @param size the output size in bytes of this instance.
+ * @throws IllegalArgumentException if the designated output size is invalid.
+ * @see #HAVAL_128_BIT
+ * @see #HAVAL_160_BIT
+ * @see #HAVAL_192_BIT
+ * @see #HAVAL_224_BIT
+ * @see #HAVAL_256_BIT
+ */
+ public Haval(int size)
+ {
+ this(size, HAVAL_3_ROUND);
+ }
+
+ /**
+ * <p>Constructs a <code>Haval</code> instance with the designated output
+ * size (in bytes). Valid output <code>size</code> values are <code>16</code>,
+ * <code>20</code>, <code>24</code>, <code>28</code> and <code>32</code>.
+ * Valid values for <code>rounds</code> are in the range <code>3..5</code>
+ * inclusive.</p>
+ *
+ * @param size the output size in bytes of this instance.
+ * @param rounds the number of rounds to apply when transforming data.
+ * @throws IllegalArgumentException if the designated output size is invalid,
+ * or if the number of rounds is invalid.
+ * @see #HAVAL_128_BIT
+ * @see #HAVAL_160_BIT
+ * @see #HAVAL_192_BIT
+ * @see #HAVAL_224_BIT
+ * @see #HAVAL_256_BIT
+ * @see #HAVAL_3_ROUND
+ * @see #HAVAL_4_ROUND
+ * @see #HAVAL_5_ROUND
+ */
+ public Haval(int size, int rounds)
+ {
+ super(Registry.HAVAL_HASH, size, BLOCK_SIZE);
+
+ if (size != HAVAL_128_BIT && size != HAVAL_160_BIT && size != HAVAL_192_BIT
+ && size != HAVAL_224_BIT && size != HAVAL_256_BIT)
+ {
+ throw new IllegalArgumentException("Invalid HAVAL output size");
+ }
+
+ if (rounds != HAVAL_3_ROUND && rounds != HAVAL_4_ROUND
+ && rounds != HAVAL_5_ROUND)
+ {
+ throw new IllegalArgumentException("Invalid HAVAL number of rounds");
+ }
+
+ this.rounds = rounds;
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Haval(Haval md)
+ {
+ this(md.hashSize, md.rounds);
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.h5 = md.h5;
+ this.h6 = md.h6;
+ this.h7 = md.h7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Haval(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected synchronized void transform(byte[] in, int i)
+ {
+ int X0 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X1 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X2 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X3 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X4 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X5 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X6 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X7 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X8 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X9 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X10 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X11 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X12 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X13 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X14 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X15 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X16 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X17 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X18 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X19 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X20 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X21 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X22 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X23 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X24 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X25 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X26 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X27 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X28 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X29 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X30 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+ int X31 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | (in[i++] & 0xFF) << 24;
+
+ int t0 = h0, t1 = h1, t2 = h2, t3 = h3, t4 = h4, t5 = h5, t6 = h6, t7 = h7;
+
+ // Pass 1
+ t7 = FF1(t7, t6, t5, t4, t3, t2, t1, t0, X0);
+ t6 = FF1(t6, t5, t4, t3, t2, t1, t0, t7, X1);
+ t5 = FF1(t5, t4, t3, t2, t1, t0, t7, t6, X2);
+ t4 = FF1(t4, t3, t2, t1, t0, t7, t6, t5, X3);
+ t3 = FF1(t3, t2, t1, t0, t7, t6, t5, t4, X4);
+ t2 = FF1(t2, t1, t0, t7, t6, t5, t4, t3, X5);
+ t1 = FF1(t1, t0, t7, t6, t5, t4, t3, t2, X6);
+ t0 = FF1(t0, t7, t6, t5, t4, t3, t2, t1, X7);
+
+ t7 = FF1(t7, t6, t5, t4, t3, t2, t1, t0, X8);
+ t6 = FF1(t6, t5, t4, t3, t2, t1, t0, t7, X9);
+ t5 = FF1(t5, t4, t3, t2, t1, t0, t7, t6, X10);
+ t4 = FF1(t4, t3, t2, t1, t0, t7, t6, t5, X11);
+ t3 = FF1(t3, t2, t1, t0, t7, t6, t5, t4, X12);
+ t2 = FF1(t2, t1, t0, t7, t6, t5, t4, t3, X13);
+ t1 = FF1(t1, t0, t7, t6, t5, t4, t3, t2, X14);
+ t0 = FF1(t0, t7, t6, t5, t4, t3, t2, t1, X15);
+
+ t7 = FF1(t7, t6, t5, t4, t3, t2, t1, t0, X16);
+ t6 = FF1(t6, t5, t4, t3, t2, t1, t0, t7, X17);
+ t5 = FF1(t5, t4, t3, t2, t1, t0, t7, t6, X18);
+ t4 = FF1(t4, t3, t2, t1, t0, t7, t6, t5, X19);
+ t3 = FF1(t3, t2, t1, t0, t7, t6, t5, t4, X20);
+ t2 = FF1(t2, t1, t0, t7, t6, t5, t4, t3, X21);
+ t1 = FF1(t1, t0, t7, t6, t5, t4, t3, t2, X22);
+ t0 = FF1(t0, t7, t6, t5, t4, t3, t2, t1, X23);
+
+ t7 = FF1(t7, t6, t5, t4, t3, t2, t1, t0, X24);
+ t6 = FF1(t6, t5, t4, t3, t2, t1, t0, t7, X25);
+ t5 = FF1(t5, t4, t3, t2, t1, t0, t7, t6, X26);
+ t4 = FF1(t4, t3, t2, t1, t0, t7, t6, t5, X27);
+ t3 = FF1(t3, t2, t1, t0, t7, t6, t5, t4, X28);
+ t2 = FF1(t2, t1, t0, t7, t6, t5, t4, t3, X29);
+ t1 = FF1(t1, t0, t7, t6, t5, t4, t3, t2, X30);
+ t0 = FF1(t0, t7, t6, t5, t4, t3, t2, t1, X31);
+
+ // Pass 2
+ t7 = FF2(t7, t6, t5, t4, t3, t2, t1, t0, X5, 0x452821E6);
+ t6 = FF2(t6, t5, t4, t3, t2, t1, t0, t7, X14, 0x38D01377);
+ t5 = FF2(t5, t4, t3, t2, t1, t0, t7, t6, X26, 0xBE5466CF);
+ t4 = FF2(t4, t3, t2, t1, t0, t7, t6, t5, X18, 0x34E90C6C);
+ t3 = FF2(t3, t2, t1, t0, t7, t6, t5, t4, X11, 0xC0AC29B7);
+ t2 = FF2(t2, t1, t0, t7, t6, t5, t4, t3, X28, 0xC97C50DD);
+ t1 = FF2(t1, t0, t7, t6, t5, t4, t3, t2, X7, 0x3F84D5B5);
+ t0 = FF2(t0, t7, t6, t5, t4, t3, t2, t1, X16, 0xB5470917);
+
+ t7 = FF2(t7, t6, t5, t4, t3, t2, t1, t0, X0, 0x9216D5D9);
+ t6 = FF2(t6, t5, t4, t3, t2, t1, t0, t7, X23, 0x8979FB1B);
+ t5 = FF2(t5, t4, t3, t2, t1, t0, t7, t6, X20, 0xD1310BA6);
+ t4 = FF2(t4, t3, t2, t1, t0, t7, t6, t5, X22, 0x98DFB5AC);
+ t3 = FF2(t3, t2, t1, t0, t7, t6, t5, t4, X1, 0x2FFD72DB);
+ t2 = FF2(t2, t1, t0, t7, t6, t5, t4, t3, X10, 0xD01ADFB7);
+ t1 = FF2(t1, t0, t7, t6, t5, t4, t3, t2, X4, 0xB8E1AFED);
+ t0 = FF2(t0, t7, t6, t5, t4, t3, t2, t1, X8, 0x6A267E96);
+
+ t7 = FF2(t7, t6, t5, t4, t3, t2, t1, t0, X30, 0xBA7C9045);
+ t6 = FF2(t6, t5, t4, t3, t2, t1, t0, t7, X3, 0xF12C7F99);
+ t5 = FF2(t5, t4, t3, t2, t1, t0, t7, t6, X21, 0x24A19947);
+ t4 = FF2(t4, t3, t2, t1, t0, t7, t6, t5, X9, 0xB3916CF7);
+ t3 = FF2(t3, t2, t1, t0, t7, t6, t5, t4, X17, 0x0801F2E2);
+ t2 = FF2(t2, t1, t0, t7, t6, t5, t4, t3, X24, 0x858EFC16);
+ t1 = FF2(t1, t0, t7, t6, t5, t4, t3, t2, X29, 0x636920D8);
+ t0 = FF2(t0, t7, t6, t5, t4, t3, t2, t1, X6, 0x71574E69);
+
+ t7 = FF2(t7, t6, t5, t4, t3, t2, t1, t0, X19, 0xA458FEA3);
+ t6 = FF2(t6, t5, t4, t3, t2, t1, t0, t7, X12, 0xF4933D7E);
+ t5 = FF2(t5, t4, t3, t2, t1, t0, t7, t6, X15, 0x0D95748F);
+ t4 = FF2(t4, t3, t2, t1, t0, t7, t6, t5, X13, 0x728EB658);
+ t3 = FF2(t3, t2, t1, t0, t7, t6, t5, t4, X2, 0x718BCD58);
+ t2 = FF2(t2, t1, t0, t7, t6, t5, t4, t3, X25, 0x82154AEE);
+ t1 = FF2(t1, t0, t7, t6, t5, t4, t3, t2, X31, 0x7B54A41D);
+ t0 = FF2(t0, t7, t6, t5, t4, t3, t2, t1, X27, 0xC25A59B5);
+
+ // Pass 3
+ t7 = FF3(t7, t6, t5, t4, t3, t2, t1, t0, X19, 0x9C30D539);
+ t6 = FF3(t6, t5, t4, t3, t2, t1, t0, t7, X9, 0x2AF26013);
+ t5 = FF3(t5, t4, t3, t2, t1, t0, t7, t6, X4, 0xC5D1B023);
+ t4 = FF3(t4, t3, t2, t1, t0, t7, t6, t5, X20, 0x286085F0);
+ t3 = FF3(t3, t2, t1, t0, t7, t6, t5, t4, X28, 0xCA417918);
+ t2 = FF3(t2, t1, t0, t7, t6, t5, t4, t3, X17, 0xB8DB38EF);
+ t1 = FF3(t1, t0, t7, t6, t5, t4, t3, t2, X8, 0x8E79DCB0);
+ t0 = FF3(t0, t7, t6, t5, t4, t3, t2, t1, X22, 0x603A180E);
+
+ t7 = FF3(t7, t6, t5, t4, t3, t2, t1, t0, X29, 0x6C9E0E8B);
+ t6 = FF3(t6, t5, t4, t3, t2, t1, t0, t7, X14, 0xB01E8A3E);
+ t5 = FF3(t5, t4, t3, t2, t1, t0, t7, t6, X25, 0xD71577C1);
+ t4 = FF3(t4, t3, t2, t1, t0, t7, t6, t5, X12, 0xBD314B27);
+ t3 = FF3(t3, t2, t1, t0, t7, t6, t5, t4, X24, 0x78AF2FDA);
+ t2 = FF3(t2, t1, t0, t7, t6, t5, t4, t3, X30, 0x55605C60);
+ t1 = FF3(t1, t0, t7, t6, t5, t4, t3, t2, X16, 0xE65525F3);
+ t0 = FF3(t0, t7, t6, t5, t4, t3, t2, t1, X26, 0xAA55AB94);
+
+ t7 = FF3(t7, t6, t5, t4, t3, t2, t1, t0, X31, 0x57489862);
+ t6 = FF3(t6, t5, t4, t3, t2, t1, t0, t7, X15, 0x63E81440);
+ t5 = FF3(t5, t4, t3, t2, t1, t0, t7, t6, X7, 0x55CA396A);
+ t4 = FF3(t4, t3, t2, t1, t0, t7, t6, t5, X3, 0x2AAB10B6);
+ t3 = FF3(t3, t2, t1, t0, t7, t6, t5, t4, X1, 0xB4CC5C34);
+ t2 = FF3(t2, t1, t0, t7, t6, t5, t4, t3, X0, 0x1141E8CE);
+ t1 = FF3(t1, t0, t7, t6, t5, t4, t3, t2, X18, 0xA15486AF);
+ t0 = FF3(t0, t7, t6, t5, t4, t3, t2, t1, X27, 0x7C72E993);
+
+ t7 = FF3(t7, t6, t5, t4, t3, t2, t1, t0, X13, 0xB3EE1411);
+ t6 = FF3(t6, t5, t4, t3, t2, t1, t0, t7, X6, 0x636FBC2A);
+ t5 = FF3(t5, t4, t3, t2, t1, t0, t7, t6, X21, 0x2BA9C55D);
+ t4 = FF3(t4, t3, t2, t1, t0, t7, t6, t5, X10, 0x741831F6);
+ t3 = FF3(t3, t2, t1, t0, t7, t6, t5, t4, X23, 0xCE5C3E16);
+ t2 = FF3(t2, t1, t0, t7, t6, t5, t4, t3, X11, 0x9B87931E);
+ t1 = FF3(t1, t0, t7, t6, t5, t4, t3, t2, X5, 0xAFD6BA33);
+ t0 = FF3(t0, t7, t6, t5, t4, t3, t2, t1, X2, 0x6C24CF5C);
+
+ if (rounds >= 4)
+ {
+ t7 = FF4(t7, t6, t5, t4, t3, t2, t1, t0, X24, 0x7A325381);
+ t6 = FF4(t6, t5, t4, t3, t2, t1, t0, t7, X4, 0x28958677);
+ t5 = FF4(t5, t4, t3, t2, t1, t0, t7, t6, X0, 0x3B8F4898);
+ t4 = FF4(t4, t3, t2, t1, t0, t7, t6, t5, X14, 0x6B4BB9AF);
+ t3 = FF4(t3, t2, t1, t0, t7, t6, t5, t4, X2, 0xC4BFE81B);
+ t2 = FF4(t2, t1, t0, t7, t6, t5, t4, t3, X7, 0x66282193);
+ t1 = FF4(t1, t0, t7, t6, t5, t4, t3, t2, X28, 0x61D809CC);
+ t0 = FF4(t0, t7, t6, t5, t4, t3, t2, t1, X23, 0xFB21A991);
+ t7 = FF4(t7, t6, t5, t4, t3, t2, t1, t0, X26, 0x487CAC60);
+ t6 = FF4(t6, t5, t4, t3, t2, t1, t0, t7, X6, 0x5DEC8032);
+ t5 = FF4(t5, t4, t3, t2, t1, t0, t7, t6, X30, 0xEF845D5D);
+ t4 = FF4(t4, t3, t2, t1, t0, t7, t6, t5, X20, 0xE98575B1);
+ t3 = FF4(t3, t2, t1, t0, t7, t6, t5, t4, X18, 0xDC262302);
+ t2 = FF4(t2, t1, t0, t7, t6, t5, t4, t3, X25, 0xEB651B88);
+ t1 = FF4(t1, t0, t7, t6, t5, t4, t3, t2, X19, 0x23893E81);
+ t0 = FF4(t0, t7, t6, t5, t4, t3, t2, t1, X3, 0xD396ACC5);
+
+ t7 = FF4(t7, t6, t5, t4, t3, t2, t1, t0, X22, 0x0F6D6FF3);
+ t6 = FF4(t6, t5, t4, t3, t2, t1, t0, t7, X11, 0x83F44239);
+ t5 = FF4(t5, t4, t3, t2, t1, t0, t7, t6, X31, 0x2E0B4482);
+ t4 = FF4(t4, t3, t2, t1, t0, t7, t6, t5, X21, 0xA4842004);
+ t3 = FF4(t3, t2, t1, t0, t7, t6, t5, t4, X8, 0x69C8F04A);
+ t2 = FF4(t2, t1, t0, t7, t6, t5, t4, t3, X27, 0x9E1F9B5E);
+ t1 = FF4(t1, t0, t7, t6, t5, t4, t3, t2, X12, 0x21C66842);
+ t0 = FF4(t0, t7, t6, t5, t4, t3, t2, t1, X9, 0xF6E96C9A);
+ t7 = FF4(t7, t6, t5, t4, t3, t2, t1, t0, X1, 0x670C9C61);
+ t6 = FF4(t6, t5, t4, t3, t2, t1, t0, t7, X29, 0xABD388F0);
+ t5 = FF4(t5, t4, t3, t2, t1, t0, t7, t6, X5, 0x6A51A0D2);
+ t4 = FF4(t4, t3, t2, t1, t0, t7, t6, t5, X15, 0xD8542F68);
+ t3 = FF4(t3, t2, t1, t0, t7, t6, t5, t4, X17, 0x960FA728);
+ t2 = FF4(t2, t1, t0, t7, t6, t5, t4, t3, X10, 0xAB5133A3);
+ t1 = FF4(t1, t0, t7, t6, t5, t4, t3, t2, X16, 0x6EEF0B6C);
+ t0 = FF4(t0, t7, t6, t5, t4, t3, t2, t1, X13, 0x137A3BE4);
+
+ if (rounds == 5)
+ {
+ t7 = FF5(t7, t6, t5, t4, t3, t2, t1, t0, X27, 0xBA3BF050);
+ t6 = FF5(t6, t5, t4, t3, t2, t1, t0, t7, X3, 0x7EFB2A98);
+ t5 = FF5(t5, t4, t3, t2, t1, t0, t7, t6, X21, 0xA1F1651D);
+ t4 = FF5(t4, t3, t2, t1, t0, t7, t6, t5, X26, 0x39AF0176);
+ t3 = FF5(t3, t2, t1, t0, t7, t6, t5, t4, X17, 0x66CA593E);
+ t2 = FF5(t2, t1, t0, t7, t6, t5, t4, t3, X11, 0x82430E88);
+ t1 = FF5(t1, t0, t7, t6, t5, t4, t3, t2, X20, 0x8CEE8619);
+ t0 = FF5(t0, t7, t6, t5, t4, t3, t2, t1, X29, 0x456F9FB4);
+
+ t7 = FF5(t7, t6, t5, t4, t3, t2, t1, t0, X19, 0x7D84A5C3);
+ t6 = FF5(t6, t5, t4, t3, t2, t1, t0, t7, X0, 0x3B8B5EBE);
+ t5 = FF5(t5, t4, t3, t2, t1, t0, t7, t6, X12, 0xE06F75D8);
+ t4 = FF5(t4, t3, t2, t1, t0, t7, t6, t5, X7, 0x85C12073);
+ t3 = FF5(t3, t2, t1, t0, t7, t6, t5, t4, X13, 0x401A449F);
+ t2 = FF5(t2, t1, t0, t7, t6, t5, t4, t3, X8, 0x56C16AA6);
+ t1 = FF5(t1, t0, t7, t6, t5, t4, t3, t2, X31, 0x4ED3AA62);
+ t0 = FF5(t0, t7, t6, t5, t4, t3, t2, t1, X10, 0x363F7706);
+
+ t7 = FF5(t7, t6, t5, t4, t3, t2, t1, t0, X5, 0x1BFEDF72);
+ t6 = FF5(t6, t5, t4, t3, t2, t1, t0, t7, X9, 0x429B023D);
+ t5 = FF5(t5, t4, t3, t2, t1, t0, t7, t6, X14, 0x37D0D724);
+ t4 = FF5(t4, t3, t2, t1, t0, t7, t6, t5, X30, 0xD00A1248);
+ t3 = FF5(t3, t2, t1, t0, t7, t6, t5, t4, X18, 0xDB0FEAD3);
+ t2 = FF5(t2, t1, t0, t7, t6, t5, t4, t3, X6, 0x49F1C09B);
+ t1 = FF5(t1, t0, t7, t6, t5, t4, t3, t2, X28, 0x075372C9);
+ t0 = FF5(t0, t7, t6, t5, t4, t3, t2, t1, X24, 0x80991B7B);
+
+ t7 = FF5(t7, t6, t5, t4, t3, t2, t1, t0, X2, 0x25D479D8);
+ t6 = FF5(t6, t5, t4, t3, t2, t1, t0, t7, X23, 0xF6E8DEF7);
+ t5 = FF5(t5, t4, t3, t2, t1, t0, t7, t6, X16, 0xE3FE501A);
+ t4 = FF5(t4, t3, t2, t1, t0, t7, t6, t5, X22, 0xB6794C3B);
+ t3 = FF5(t3, t2, t1, t0, t7, t6, t5, t4, X4, 0x976CE0BD);
+ t2 = FF5(t2, t1, t0, t7, t6, t5, t4, t3, X1, 0x04C006BA);
+ t1 = FF5(t1, t0, t7, t6, t5, t4, t3, t2, X25, 0xC1A94FB6);
+ t0 = FF5(t0, t7, t6, t5, t4, t3, t2, t1, X15, 0x409F60C4);
+ }
+ }
+
+ h7 += t7;
+ h6 += t6;
+ h5 += t5;
+ h4 += t4;
+ h3 += t3;
+ h2 += t2;
+ h1 += t1;
+ h0 += t0;
+ }
+
+ protected byte[] padBuffer()
+ {
+ // pad out to 118 mod 128. other 10 bytes have special use.
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 118) ? (118 - n) : (246 - n);
+ byte[] result = new byte[padding + 10];
+ result[0] = (byte) 0x01;
+
+ // save the version number (LSB 3), the number of rounds (3 bits in the
+ // middle), the fingerprint length (MSB 2 bits and next byte) and the
+ // number of bits in the unpadded message.
+ int bl = hashSize * 8;
+ result[padding++] = (byte) (((bl & 0x03) << 6) | ((rounds & 0x07) << 3) | (HAVAL_VERSION & 0x07));
+ result[padding++] = (byte) (bl >>> 2);
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) bits;
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding] = (byte) (bits >>> 56);
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ tailorDigestBits(); // tailor context for the designated output size
+ // cast enough top context values into an array of hashSize bytes
+ byte[] result = new byte[hashSize];
+ if (hashSize >= HAVAL_256_BIT)
+ {
+ result[31] = (byte) (h7 >>> 24);
+ result[30] = (byte) (h7 >>> 16);
+ result[29] = (byte) (h7 >>> 8);
+ result[28] = (byte) h7;
+ }
+ if (hashSize >= HAVAL_224_BIT)
+ {
+ result[27] = (byte) (h6 >>> 24);
+ result[26] = (byte) (h6 >>> 16);
+ result[25] = (byte) (h6 >>> 8);
+ result[24] = (byte) h6;
+ }
+ if (hashSize >= HAVAL_192_BIT)
+ {
+ result[23] = (byte) (h5 >>> 24);
+ result[22] = (byte) (h5 >>> 16);
+ result[21] = (byte) (h5 >>> 8);
+ result[20] = (byte) h5;
+ }
+ if (hashSize >= HAVAL_160_BIT)
+ {
+ result[19] = (byte) (h4 >>> 24);
+ result[18] = (byte) (h4 >>> 16);
+ result[17] = (byte) (h4 >>> 8);
+ result[16] = (byte) h4;
+ }
+ result[15] = (byte) (h3 >>> 24);
+ result[14] = (byte) (h3 >>> 16);
+ result[13] = (byte) (h3 >>> 8);
+ result[12] = (byte) h3;
+ result[11] = (byte) (h2 >>> 24);
+ result[10] = (byte) (h2 >>> 16);
+ result[9] = (byte) (h2 >>> 8);
+ result[8] = (byte) h2;
+ result[7] = (byte) (h1 >>> 24);
+ result[6] = (byte) (h1 >>> 16);
+ result[5] = (byte) (h1 >>> 8);
+ result[4] = (byte) h1;
+ result[3] = (byte) (h0 >>> 24);
+ result[2] = (byte) (h0 >>> 16);
+ result[1] = (byte) (h0 >>> 8);
+ result[0] = (byte) h0;
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ h0 = 0x243F6A88;
+ h1 = 0x85A308D3;
+ h2 = 0x13198A2E;
+ h3 = 0x03707344;
+ h4 = 0xA4093822;
+ h5 = 0x299F31D0;
+ h6 = 0x082EFA98;
+ h7 = 0xEC4E6C89;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new Haval().digest())));
+ }
+ return valid.booleanValue();
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /** Tailors the last output. */
+ private void tailorDigestBits()
+ {
+ int t;
+ switch (hashSize)
+ {
+ case HAVAL_128_BIT:
+ t = (h7 & 0x000000FF) | (h6 & 0xFF000000) | (h5 & 0x00FF0000)
+ | (h4 & 0x0000FF00);
+ h0 += t >>> 8 | t << 24;
+ t = (h7 & 0x0000FF00) | (h6 & 0x000000FF) | (h5 & 0xFF000000)
+ | (h4 & 0x00FF0000);
+ h1 += t >>> 16 | t << 16;
+ t = (h7 & 0x00FF0000) | (h6 & 0x0000FF00) | (h5 & 0x000000FF)
+ | (h4 & 0xFF000000);
+ h2 += t >>> 24 | t << 8;
+ t = (h7 & 0xFF000000) | (h6 & 0x00FF0000) | (h5 & 0x0000FF00)
+ | (h4 & 0x000000FF);
+ h3 += t;
+ break;
+ case HAVAL_160_BIT:
+ t = (h7 & 0x3F) | (h6 & (0x7F << 25)) | (h5 & (0x3F << 19));
+ h0 += t >>> 19 | t << 13;
+ t = (h7 & (0x3F << 6)) | (h6 & 0x3F) | (h5 & (0x7F << 25));
+ h1 += t >>> 25 | t << 7;
+ t = (h7 & (0x7F << 12)) | (h6 & (0x3F << 6)) | (h5 & 0x3F);
+ h2 += t;
+ t = (h7 & (0x3F << 19)) | (h6 & (0x7F << 12)) | (h5 & (0x3F << 6));
+ h3 += (t >>> 6);
+ t = (h7 & (0x7F << 25)) | (h6 & (0x3F << 19)) | (h5 & (0x7F << 12));
+ h4 += (t >>> 12);
+ break;
+ case HAVAL_192_BIT:
+ t = (h7 & 0x1F) | (h6 & (0x3F << 26));
+ h0 += t >>> 26 | t << 6;
+ t = (h7 & (0x1F << 5)) | (h6 & 0x1F);
+ h1 += t;
+ t = (h7 & (0x3F << 10)) | (h6 & (0x1F << 5));
+ h2 += (t >>> 5);
+ t = (h7 & (0x1F << 16)) | (h6 & (0x3F << 10));
+ h3 += (t >>> 10);
+ t = (h7 & (0x1F << 21)) | (h6 & (0x1F << 16));
+ h4 += (t >>> 16);
+ t = (h7 & (0x3F << 26)) | (h6 & (0x1F << 21));
+ h5 += (t >>> 21);
+ break;
+ case HAVAL_224_BIT:
+ h0 += ((h7 >>> 27) & 0x1F);
+ h1 += ((h7 >>> 22) & 0x1F);
+ h2 += ((h7 >>> 18) & 0x0F);
+ h3 += ((h7 >>> 13) & 0x1F);
+ h4 += ((h7 >>> 9) & 0x0F);
+ h5 += ((h7 >>> 4) & 0x1F);
+ h6 += (h7 & 0x0F);
+ }
+ }
+
+ /**
+ * Permutations phi_{i,j}, i=3,4,5, j=1,...,i.
+ *
+ * rounds = 3: 6 5 4 3 2 1 0
+ * | | | | | | | (replaced by)
+ * phi_{3,1}: 1 0 3 5 6 2 4
+ * phi_{3,2}: 4 2 1 0 5 3 6
+ * phi_{3,3}: 6 1 2 3 4 5 0
+ *
+ * rounds = 4: 6 5 4 3 2 1 0
+ * | | | | | | | (replaced by)
+ * phi_{4,1}: 2 6 1 4 5 3 0
+ * phi_{4,2}: 3 5 2 0 1 6 4
+ * phi_{4,3}: 1 4 3 6 0 2 5
+ * phi_{4,4}: 6 4 0 5 2 1 3
+ *
+ * rounds = 5: 6 5 4 3 2 1 0
+ * | | | | | | | (replaced by)
+ * phi_{5,1}: 3 4 1 0 5 2 6
+ * phi_{5,2}: 6 2 1 0 3 4 5
+ * phi_{5,3}: 2 6 0 4 3 1 5
+ * phi_{5,4}: 1 5 3 2 0 4 6
+ * phi_{5,5}: 2 5 0 6 4 3 1
+ */
+ private int FF1(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w)
+ {
+ int t;
+ switch (rounds)
+ {
+ case 3:
+ t = f1(x1, x0, x3, x5, x6, x2, x4);
+ break;
+ case 4:
+ t = f1(x2, x6, x1, x4, x5, x3, x0);
+ break;
+ default:
+ t = f1(x3, x4, x1, x0, x5, x2, x6);
+ }
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w;
+ }
+
+ private int FF2(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w, int c)
+ {
+ int t;
+ switch (rounds)
+ {
+ case 3:
+ t = f2(x4, x2, x1, x0, x5, x3, x6);
+ break;
+ case 4:
+ t = f2(x3, x5, x2, x0, x1, x6, x4);
+ break;
+ default:
+ t = f2(x6, x2, x1, x0, x3, x4, x5);
+ }
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w + c;
+ }
+
+ private int FF3(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w, int c)
+ {
+ int t;
+ switch (rounds)
+ {
+ case 3:
+ t = f3(x6, x1, x2, x3, x4, x5, x0);
+ break;
+ case 4:
+ t = f3(x1, x4, x3, x6, x0, x2, x5);
+ break;
+ default:
+ t = f3(x2, x6, x0, x4, x3, x1, x5);
+ }
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w + c;
+ }
+
+ private int FF4(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w, int c)
+ {
+ int t;
+ switch (rounds)
+ {
+ case 4:
+ t = f4(x6, x4, x0, x5, x2, x1, x3);
+ break;
+ default:
+ t = f4(x1, x5, x3, x2, x0, x4, x6);
+ }
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w + c;
+ }
+
+ private int FF5(int x7, int x6, int x5, int x4, int x3, int x2, int x1,
+ int x0, int w, int c)
+ {
+ int t = f5(x2, x5, x0, x6, x4, x3, x1);
+ return (t >>> 7 | t << 25) + (x7 >>> 11 | x7 << 21) + w + c;
+ }
+
+ private int f1(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x1 & (x0 ^ x4) ^ x2 & x5 ^ x3 & x6 ^ x0;
+ }
+
+ private int f2(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x2 & (x1 & ~x3 ^ x4 & x5 ^ x6 ^ x0) ^ x4 & (x1 ^ x5) ^ x3 & x5 ^ x0;
+ }
+
+ private int f3(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x3 & (x1 & x2 ^ x6 ^ x0) ^ x1 & x4 ^ x2 & x5 ^ x0;
+ }
+
+ private int f4(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x4 & (x5 & ~x2 ^ x3 & ~x6 ^ x1 ^ x6 ^ x0) ^ x3 & (x1 & x2 ^ x5 ^ x6)
+ ^ x2 & x6 ^ x0;
+ }
+
+ private int f5(int x6, int x5, int x4, int x3, int x2, int x1, int x0)
+ {
+ return x0 & (x1 & x2 & x3 ^ ~x5) ^ x1 & x4 ^ x2 & x5 ^ x3 & x6;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/IMessageDigest.java b/libjava/classpath/gnu/java/security/hash/IMessageDigest.java
new file mode 100644
index 00000000000..b3d7f69ca2e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/IMessageDigest.java
@@ -0,0 +1,135 @@
+/* IMessageDigest.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+/**
+ * <p>The basic visible methods of any hash algorithm.</p>
+ *
+ * <p>A hash (or message digest) algorithm produces its output by iterating a
+ * basic compression function on blocks of data.</p>
+ */
+public interface IMessageDigest extends Cloneable
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of this algorithm.</p>
+ *
+ * @return the canonical name of this instance.
+ */
+ String name();
+
+ /**
+ * <p>Returns the output length in bytes of this message digest algorithm.</p>
+ *
+ * @return the output length in bytes of this message digest algorithm.
+ */
+ int hashSize();
+
+ /**
+ * <p>Returns the algorithm's (inner) block size in bytes.</p>
+ *
+ * @return the algorithm's inner block size in bytes.
+ */
+ int blockSize();
+
+ /**
+ * <p>Continues a message digest operation using the input byte.</p>
+ *
+ * @param b the input byte to digest.
+ */
+ void update(byte b);
+
+ /**
+ * <p>Continues a message digest operation, by filling the buffer, processing
+ * data in the algorithm's HASH_SIZE-bit block(s), updating the context and
+ * count, and buffering the remaining bytes in buffer for the next
+ * operation.</p>
+ *
+ * @param in the input block.
+ */
+ void update(byte[] in);
+
+ /**
+ * <p>Continues a message digest operation, by filling the buffer, processing
+ * data in the algorithm's HASH_SIZE-bit block(s), updating the context and
+ * count, and buffering the remaining bytes in buffer for the next
+ * operation.</p>
+ *
+ * @param in the input block.
+ * @param offset start of meaningful bytes in input block.
+ * @param length number of bytes, in input block, to consider.
+ */
+ void update(byte[] in, int offset, int length);
+
+ /**
+ * <p>Completes the message digest by performing final operations such as
+ * padding and resetting the instance.</p>
+ *
+ * @return the array of bytes representing the hash value.
+ */
+ byte[] digest();
+
+ /**
+ * <p>Resets the current context of this instance clearing any eventually cached
+ * intermediary values.</p>
+ */
+ void reset();
+
+ /**
+ * <p>A basic test. Ensures that the digest of a pre-determined message is equal
+ * to a known pre-computed value.</p>
+ *
+ * @return <tt>true</tt> if the implementation passes a basic self-test.
+ * Returns <tt>false</tt> otherwise.
+ */
+ boolean selfTest();
+
+ /**
+ * <p>Returns a clone copy of this instance.</p>
+ *
+ * @return a clone copy of this instance.
+ */
+ Object clone();
+}
diff --git a/libjava/classpath/gnu/java/security/hash/MD2.java b/libjava/classpath/gnu/java/security/hash/MD2.java
new file mode 100644
index 00000000000..41e876983bd
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/MD2.java
@@ -0,0 +1,301 @@
+/* MD2.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>An implementation of the MD2 message digest algorithm.</p>
+ *
+ * <p>MD2 is not widely used. Unless it is needed for compatibility with
+ * existing systems, it is not recommended for use in new applications.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>The <a href="http://www.ietf.org/rfc/rfc1319.txt">MD2</a>
+ * Message-Digest Algorithm.<br>
+ * B. Kaliski.</li>
+ * <li>The <a href="http://www.rfc-editor.org/errata.html">RFC ERRATA PAGE</a>
+ * under section RFC 1319.</li>
+ * </ol>
+ */
+public class MD2 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** An MD2 message digest is always 128-bits long, or 16 bytes. */
+ private static final int DIGEST_LENGTH = 16;
+
+ /** The MD2 algorithm operates on 128-bit blocks, or 16 bytes. */
+ private static final int BLOCK_LENGTH = 16;
+
+ /** 256 byte "random" permutation of the digits of pi. */
+ private static final byte[] PI = { 41, 46, 67, -55, -94, -40, 124, 1, 61, 54,
+ 84, -95, -20, -16, 6, 19, 98, -89, 5, -13,
+ -64, -57, 115, -116, -104, -109, 43, -39,
+ -68, 76, -126, -54, 30, -101, 87, 60, -3,
+ -44, -32, 22, 103, 66, 111, 24, -118, 23,
+ -27, 18, -66, 78, -60, -42, -38, -98, -34,
+ 73, -96, -5, -11, -114, -69, 47, -18, 122,
+ -87, 104, 121, -111, 21, -78, 7, 63, -108,
+ -62, 16, -119, 11, 34, 95, 33, -128, 127,
+ 93, -102, 90, -112, 50, 39, 53, 62, -52,
+ -25, -65, -9, -105, 3, -1, 25, 48, -77, 72,
+ -91, -75, -47, -41, 94, -110, 42, -84, 86,
+ -86, -58, 79, -72, 56, -46, -106, -92, 125,
+ -74, 118, -4, 107, -30, -100, 116, 4, -15,
+ 69, -99, 112, 89, 100, 113, -121, 32, -122,
+ 91, -49, 101, -26, 45, -88, 2, 27, 96, 37,
+ -83, -82, -80, -71, -10, 28, 70, 97, 105,
+ 52, 64, 126, 15, 85, 71, -93, 35, -35, 81,
+ -81, 58, -61, 92, -7, -50, -70, -59, -22,
+ 38, 44, 83, 13, 110, -123, 40, -124, 9,
+ -45, -33, -51, -12, 65, -127, 77, 82, 106,
+ -36, 55, -56, 108, -63, -85, -6, 36, -31,
+ 123, 8, 12, -67, -79, 74, 120, -120, -107,
+ -117, -29, 99, -24, 109, -23, -53, -43, -2,
+ 59, 0, 29, 57, -14, -17, -73, 14, 102, 88,
+ -48, -28, -90, 119, 114, -8, -21, 117, 75,
+ 10, 49, 68, 80, -76, -113, -19, 31, 26,
+ -37, -103, -115, 51, -97, 17, -125, 20 };
+
+ /** The output of this message digest when no data has been input. */
+ private static final String DIGEST0 = "8350E5A3E24C153DF2275C9F80692773";
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** The checksum computed so far. */
+ private byte[] checksum;
+
+ /**
+ * Work array needed by encrypt method. First <code>BLOCK_LENGTH</code> bytes
+ * are also used to store the running digest.
+ */
+ private byte[] work;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Creates a new MD2 digest ready for use. */
+ public MD2()
+ {
+ super(Registry.MD2_HASH, DIGEST_LENGTH, BLOCK_LENGTH);
+ }
+
+ /**
+ * <p>Private constructor used for cloning.</p>
+ *
+ * @param md2 the instance to clone.
+ */
+ private MD2(MD2 md2)
+ {
+ this();
+
+ // superclass field
+ this.count = md2.count;
+ this.buffer = (byte[]) md2.buffer.clone();
+
+ // private field
+ this.checksum = (byte[]) md2.checksum.clone();
+ this.work = (byte[]) md2.work.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new MD2(this);
+ }
+
+ // Implementation of abstract methods in BaseHash --------------------------
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[DIGEST_LENGTH];
+
+ // Encrypt checksum as last block.
+ encryptBlock(checksum, 0);
+
+ for (int i = 0; i < BLOCK_LENGTH; i++)
+ {
+ result[i] = work[i];
+ }
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ checksum = new byte[BLOCK_LENGTH];
+ work = new byte[BLOCK_LENGTH * 3];
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new MD2().digest())));
+ }
+ return valid.booleanValue();
+ }
+
+ /**
+ * <p>Generates an array of padding bytes. The padding is defined as
+ * <code>i</code> bytes of value <code>i</code>, where <code>i</code> is the
+ * number of bytes to fill the last block of the message to
+ * <code>BLOCK_LENGTH</code> bytes (or <code>BLOCK_LENGTH</code> bytes when
+ * the last block was completely full).</p>
+ *
+ * @return the bytes to pad the remaining bytes in the buffer before
+ * completing a hash operation.
+ */
+ protected byte[] padBuffer()
+ {
+ int length = BLOCK_LENGTH - (int) (count % BLOCK_LENGTH);
+ if (length == 0)
+ {
+ length = BLOCK_LENGTH;
+ }
+ byte[] pad = new byte[length];
+ for (int i = 0; i < length; i++)
+ {
+ pad[i] = (byte) length;
+ }
+ return pad;
+ }
+
+ /**
+ * <p>Adds <code>BLOCK_LENGTH</code> bytes to the running digest.</p>
+ *
+ * @param in the byte array to take the <code>BLOCK_LENGTH</code> bytes from.
+ * @param off the offset to start from in the given byte array.
+ */
+ protected void transform(byte[] in, int off)
+ {
+ // encryptBlock(in, off);
+ // updateCheckSum(in, off);
+ updateCheckSumAndEncryptBlock(in, off);
+ }
+
+ // Private instance methods ------------------------------------------------
+
+ /**
+ * Updates the checksum with the <code>BLOCK_LENGTH</code> bytes from the
+ * given array starting at <code>off</code>.
+ */
+ /*
+ private void updateCheckSum(byte[] in, int off) {
+ byte l = checksum[BLOCK_LENGTH-1];
+ for (int i = 0; i < BLOCK_LENGTH; i++) {
+ byte b = in[off+i];
+ // l = (byte)((checksum[i] & 0xFF) ^ (PI[((b & 0xFF) ^ (l & 0xFF))] & 0xFF));
+ l = (byte)(checksum[i] ^ PI[(b ^ l) & 0xFF]);
+ checksum[i] = l;
+ }
+ }
+ */
+ /**
+ * Adds a new block (<code>BLOCK_LENGTH</code> bytes) to the running digest
+ * from the given byte array starting from the given offset.
+ */
+ private void encryptBlock(byte[] in, int off)
+ {
+ for (int i = 0; i < BLOCK_LENGTH; i++)
+ {
+ byte b = in[off + i];
+ work[BLOCK_LENGTH + i] = b;
+ work[BLOCK_LENGTH * 2 + i] = (byte) (work[i] ^ b);
+ }
+
+ byte t = 0;
+ for (int i = 0; i < 18; i++)
+ {
+ for (int j = 0; j < 3 * BLOCK_LENGTH; j++)
+ {
+ // t = (byte)((work[j] & 0xFF) ^ (PI[t & 0xFF] & 0xFF));
+ t = (byte) (work[j] ^ PI[t & 0xFF]);
+ work[j] = t;
+ }
+ // t = (byte)((t + i) & 0xFF);
+ t = (byte) (t + i);
+ }
+ }
+
+ /**
+ * Optimized method that combines a checksum update and encrypt of a block.
+ */
+ private void updateCheckSumAndEncryptBlock(byte[] in, int off)
+ {
+ byte l = checksum[BLOCK_LENGTH - 1];
+ for (int i = 0; i < BLOCK_LENGTH; i++)
+ {
+ byte b = in[off + i];
+ work[BLOCK_LENGTH + i] = b;
+ // work[BLOCK_LENGTH*2+i] = (byte)((work[i] & 0xFF) ^ (b & 0xFF));
+ work[BLOCK_LENGTH * 2 + i] = (byte) (work[i] ^ b);
+ // l = (byte)((checksum[i] & 0xFF) ^ (PI[((b & 0xFF) ^ (l & 0xFF))] & 0xFF));
+ l = (byte) (checksum[i] ^ PI[(b ^ l) & 0xFF]);
+ checksum[i] = l;
+ }
+
+ byte t = 0;
+ for (int i = 0; i < 18; i++)
+ {
+ for (int j = 0; j < 3 * BLOCK_LENGTH; j++)
+ {
+ // t = (byte)((work[j] & 0xFF) ^ (PI[t & 0xFF] & 0xFF));
+ t = (byte) (work[j] ^ PI[t & 0xFF]);
+ work[j] = t;
+ }
+ // t = (byte)((t + i) & 0xFF);
+ t = (byte) (t + i);
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/MD4.java b/libjava/classpath/gnu/java/security/hash/MD4.java
new file mode 100644
index 00000000000..54dda358b11
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/MD4.java
@@ -0,0 +1,328 @@
+/* MD4.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>An implementation of Ron Rivest's MD4 message digest algorithm.</p>
+ *
+ * <p>MD4 was the precursor to the stronger {@link gnu.crypto.hash.MD5}
+ * algorithm, and while not considered cryptograpically secure itself, MD4 is
+ * in use in various applications. It is slightly faster than MD5.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>The <a href="http://www.ietf.org/rfc/rfc1320.txt">MD4</a>
+ * Message-Digest Algorithm.<br>
+ * R. Rivest.</li>
+ * </ol>
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public class MD4 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** An MD4 message digest is always 128-bits long, or 16 bytes. */
+ private static final int DIGEST_LENGTH = 16;
+
+ /** The MD4 algorithm operates on 512-bit blocks, or 64 bytes. */
+ private static final int BLOCK_LENGTH = 64;
+
+ private static final int A = 0x67452301;
+
+ private static final int B = 0xefcdab89;
+
+ private static final int C = 0x98badcfe;
+
+ private static final int D = 0x10325476;
+
+ /** The output of this message digest when no data has been input. */
+ private static final String DIGEST0 = "31D6CFE0D16AE931B73C59D7E0C089C0";
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ private int a, b, c, d;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Public constructor. Initializes the chaining variables, sets the byte
+ * count to <code>0</code>, and creates a new block of <code>512</code> bits.
+ * </p>
+ */
+ public MD4()
+ {
+ super(Registry.MD4_HASH, DIGEST_LENGTH, BLOCK_LENGTH);
+ }
+
+ /**
+ * <p>Trivial private constructor for cloning purposes.</p>
+ *
+ * @param that the instance to clone.
+ */
+ private MD4(MD4 that)
+ {
+ this();
+
+ this.a = that.a;
+ this.b = that.b;
+ this.c = that.c;
+ this.d = that.d;
+ this.count = that.count;
+ this.buffer = (byte[]) that.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new MD4(this);
+ }
+
+ // Implementation of abstract methods in BashHash --------------------------
+
+ protected byte[] getResult()
+ {
+ byte[] digest = { (byte) a, (byte) (a >>> 8), (byte) (a >>> 16),
+ (byte) (a >>> 24), (byte) b, (byte) (b >>> 8),
+ (byte) (b >>> 16), (byte) (b >>> 24), (byte) c,
+ (byte) (c >>> 8), (byte) (c >>> 16), (byte) (c >>> 24),
+ (byte) d, (byte) (d >>> 8), (byte) (d >>> 16),
+ (byte) (d >>> 24) };
+ return digest;
+ }
+
+ protected void resetContext()
+ {
+ a = A;
+ b = B;
+ c = C;
+ d = D;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new MD4().digest())));
+ }
+ return valid.booleanValue();
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_LENGTH);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] pad = new byte[padding + 8];
+
+ pad[0] = (byte) 0x80;
+ long bits = count << 3;
+ pad[padding++] = (byte) bits;
+ pad[padding++] = (byte) (bits >>> 8);
+ pad[padding++] = (byte) (bits >>> 16);
+ pad[padding++] = (byte) (bits >>> 24);
+ pad[padding++] = (byte) (bits >>> 32);
+ pad[padding++] = (byte) (bits >>> 40);
+ pad[padding++] = (byte) (bits >>> 48);
+ pad[padding] = (byte) (bits >>> 56);
+
+ return pad;
+ }
+
+ protected void transform(byte[] in, int i)
+ {
+ int X0 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X1 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X2 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X3 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X4 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X5 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X6 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X7 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X8 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X9 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X10 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X11 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X12 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X13 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X14 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X15 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i] << 24;
+
+ int aa, bb, cc, dd;
+
+ aa = a;
+ bb = b;
+ cc = c;
+ dd = d;
+
+ aa += ((bb & cc) | ((~bb) & dd)) + X0;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & bb) | ((~aa) & cc)) + X1;
+ dd = dd << 7 | dd >>> -7;
+ cc += ((dd & aa) | ((~dd) & bb)) + X2;
+ cc = cc << 11 | cc >>> -11;
+ bb += ((cc & dd) | ((~cc) & aa)) + X3;
+ bb = bb << 19 | bb >>> -19;
+ aa += ((bb & cc) | ((~bb) & dd)) + X4;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & bb) | ((~aa) & cc)) + X5;
+ dd = dd << 7 | dd >>> -7;
+ cc += ((dd & aa) | ((~dd) & bb)) + X6;
+ cc = cc << 11 | cc >>> -11;
+ bb += ((cc & dd) | ((~cc) & aa)) + X7;
+ bb = bb << 19 | bb >>> -19;
+ aa += ((bb & cc) | ((~bb) & dd)) + X8;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & bb) | ((~aa) & cc)) + X9;
+ dd = dd << 7 | dd >>> -7;
+ cc += ((dd & aa) | ((~dd) & bb)) + X10;
+ cc = cc << 11 | cc >>> -11;
+ bb += ((cc & dd) | ((~cc) & aa)) + X11;
+ bb = bb << 19 | bb >>> -19;
+ aa += ((bb & cc) | ((~bb) & dd)) + X12;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & bb) | ((~aa) & cc)) + X13;
+ dd = dd << 7 | dd >>> -7;
+ cc += ((dd & aa) | ((~dd) & bb)) + X14;
+ cc = cc << 11 | cc >>> -11;
+ bb += ((cc & dd) | ((~cc) & aa)) + X15;
+ bb = bb << 19 | bb >>> -19;
+
+ aa += ((bb & (cc | dd)) | (cc & dd)) + X0 + 0x5a827999;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & (bb | cc)) | (bb & cc)) + X4 + 0x5a827999;
+ dd = dd << 5 | dd >>> -5;
+ cc += ((dd & (aa | bb)) | (aa & bb)) + X8 + 0x5a827999;
+ cc = cc << 9 | cc >>> -9;
+ bb += ((cc & (dd | aa)) | (dd & aa)) + X12 + 0x5a827999;
+ bb = bb << 13 | bb >>> -13;
+ aa += ((bb & (cc | dd)) | (cc & dd)) + X1 + 0x5a827999;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & (bb | cc)) | (bb & cc)) + X5 + 0x5a827999;
+ dd = dd << 5 | dd >>> -5;
+ cc += ((dd & (aa | bb)) | (aa & bb)) + X9 + 0x5a827999;
+ cc = cc << 9 | cc >>> -9;
+ bb += ((cc & (dd | aa)) | (dd & aa)) + X13 + 0x5a827999;
+ bb = bb << 13 | bb >>> -13;
+ aa += ((bb & (cc | dd)) | (cc & dd)) + X2 + 0x5a827999;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & (bb | cc)) | (bb & cc)) + X6 + 0x5a827999;
+ dd = dd << 5 | dd >>> -5;
+ cc += ((dd & (aa | bb)) | (aa & bb)) + X10 + 0x5a827999;
+ cc = cc << 9 | cc >>> -9;
+ bb += ((cc & (dd | aa)) | (dd & aa)) + X14 + 0x5a827999;
+ bb = bb << 13 | bb >>> -13;
+ aa += ((bb & (cc | dd)) | (cc & dd)) + X3 + 0x5a827999;
+ aa = aa << 3 | aa >>> -3;
+ dd += ((aa & (bb | cc)) | (bb & cc)) + X7 + 0x5a827999;
+ dd = dd << 5 | dd >>> -5;
+ cc += ((dd & (aa | bb)) | (aa & bb)) + X11 + 0x5a827999;
+ cc = cc << 9 | cc >>> -9;
+ bb += ((cc & (dd | aa)) | (dd & aa)) + X15 + 0x5a827999;
+ bb = bb << 13 | bb >>> -13;
+
+ aa += (bb ^ cc ^ dd) + X0 + 0x6ed9eba1;
+ aa = aa << 3 | aa >>> -3;
+ dd += (aa ^ bb ^ cc) + X8 + 0x6ed9eba1;
+ dd = dd << 9 | dd >>> -9;
+ cc += (dd ^ aa ^ bb) + X4 + 0x6ed9eba1;
+ cc = cc << 11 | cc >>> -11;
+ bb += (cc ^ dd ^ aa) + X12 + 0x6ed9eba1;
+ bb = bb << 15 | bb >>> -15;
+ aa += (bb ^ cc ^ dd) + X2 + 0x6ed9eba1;
+ aa = aa << 3 | aa >>> -3;
+ dd += (aa ^ bb ^ cc) + X10 + 0x6ed9eba1;
+ dd = dd << 9 | dd >>> -9;
+ cc += (dd ^ aa ^ bb) + X6 + 0x6ed9eba1;
+ cc = cc << 11 | cc >>> -11;
+ bb += (cc ^ dd ^ aa) + X14 + 0x6ed9eba1;
+ bb = bb << 15 | bb >>> -15;
+ aa += (bb ^ cc ^ dd) + X1 + 0x6ed9eba1;
+ aa = aa << 3 | aa >>> -3;
+ dd += (aa ^ bb ^ cc) + X9 + 0x6ed9eba1;
+ dd = dd << 9 | dd >>> -9;
+ cc += (dd ^ aa ^ bb) + X5 + 0x6ed9eba1;
+ cc = cc << 11 | cc >>> -11;
+ bb += (cc ^ dd ^ aa) + X13 + 0x6ed9eba1;
+ bb = bb << 15 | bb >>> -15;
+ aa += (bb ^ cc ^ dd) + X3 + 0x6ed9eba1;
+ aa = aa << 3 | aa >>> -3;
+ dd += (aa ^ bb ^ cc) + X11 + 0x6ed9eba1;
+ dd = dd << 9 | dd >>> -9;
+ cc += (dd ^ aa ^ bb) + X7 + 0x6ed9eba1;
+ cc = cc << 11 | cc >>> -11;
+ bb += (cc ^ dd ^ aa) + X15 + 0x6ed9eba1;
+ bb = bb << 15 | bb >>> -15;
+
+ a += aa;
+ b += bb;
+ c += cc;
+ d += dd;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/MD5.java b/libjava/classpath/gnu/java/security/hash/MD5.java
new file mode 100644
index 00000000000..463292984dd
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/MD5.java
@@ -0,0 +1,365 @@
+/* MD5.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>The MD5 message-digest algorithm takes as input a message of arbitrary
+ * length and produces as output a 128-bit "fingerprint" or "message digest" of
+ * the input. It is conjectured that it is computationally infeasible to
+ * produce two messages having the same message digest, or to produce any
+ * message having a given prespecified target message digest.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li>The <a href="http://www.ietf.org/rfc/rfc1321.txt">MD5</a> Message-
+ * Digest Algorithm.<br>
+ * R. Rivest.</li>
+ * </ol>
+ */
+public class MD5 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "D41D8CD98F00B204E9800998ECF8427E";
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 128-bit interim result. */
+ private int h0, h1, h2, h3;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public MD5()
+ {
+ super(Registry.MD5_HASH, 16, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private MD5(MD5 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new MD5(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected synchronized void transform(byte[] in, int i)
+ {
+ int X0 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X1 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X2 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X3 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X4 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X5 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X6 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X7 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X8 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X9 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X10 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X11 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X12 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X13 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X14 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i++] << 24;
+ int X15 = (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16
+ | in[i] << 24;
+
+ int A = h0;
+ int B = h1;
+ int C = h2;
+ int D = h3;
+
+ // hex constants are from md5.c in FSF Gnu Privacy Guard 0.9.2
+ // round 1
+ A += ((B & C) | (~B & D)) + X0 + 0xD76AA478;
+ A = B + (A << 7 | A >>> -7);
+ D += ((A & B) | (~A & C)) + X1 + 0xE8C7B756;
+ D = A + (D << 12 | D >>> -12);
+ C += ((D & A) | (~D & B)) + X2 + 0x242070DB;
+ C = D + (C << 17 | C >>> -17);
+ B += ((C & D) | (~C & A)) + X3 + 0xC1BDCEEE;
+ B = C + (B << 22 | B >>> -22);
+
+ A += ((B & C) | (~B & D)) + X4 + 0xF57C0FAF;
+ A = B + (A << 7 | A >>> -7);
+ D += ((A & B) | (~A & C)) + X5 + 0x4787C62A;
+ D = A + (D << 12 | D >>> -12);
+ C += ((D & A) | (~D & B)) + X6 + 0xA8304613;
+ C = D + (C << 17 | C >>> -17);
+ B += ((C & D) | (~C & A)) + X7 + 0xFD469501;
+ B = C + (B << 22 | B >>> -22);
+
+ A += ((B & C) | (~B & D)) + X8 + 0x698098D8;
+ A = B + (A << 7 | A >>> -7);
+ D += ((A & B) | (~A & C)) + X9 + 0x8B44F7AF;
+ D = A + (D << 12 | D >>> -12);
+ C += ((D & A) | (~D & B)) + X10 + 0xFFFF5BB1;
+ C = D + (C << 17 | C >>> -17);
+ B += ((C & D) | (~C & A)) + X11 + 0x895CD7BE;
+ B = C + (B << 22 | B >>> -22);
+
+ A += ((B & C) | (~B & D)) + X12 + 0x6B901122;
+ A = B + (A << 7 | A >>> -7);
+ D += ((A & B) | (~A & C)) + X13 + 0xFD987193;
+ D = A + (D << 12 | D >>> -12);
+ C += ((D & A) | (~D & B)) + X14 + 0xA679438E;
+ C = D + (C << 17 | C >>> -17);
+ B += ((C & D) | (~C & A)) + X15 + 0x49B40821;
+ B = C + (B << 22 | B >>> -22);
+
+ // round 2
+ A += ((B & D) | (C & ~D)) + X1 + 0xF61E2562;
+ A = B + (A << 5 | A >>> -5);
+ D += ((A & C) | (B & ~C)) + X6 + 0xC040B340;
+ D = A + (D << 9 | D >>> -9);
+ C += ((D & B) | (A & ~B)) + X11 + 0x265E5A51;
+ C = D + (C << 14 | C >>> -14);
+ B += ((C & A) | (D & ~A)) + X0 + 0xE9B6C7AA;
+ B = C + (B << 20 | B >>> -20);
+
+ A += ((B & D) | (C & ~D)) + X5 + 0xD62F105D;
+ A = B + (A << 5 | A >>> -5);
+ D += ((A & C) | (B & ~C)) + X10 + 0x02441453;
+ D = A + (D << 9 | D >>> -9);
+ C += ((D & B) | (A & ~B)) + X15 + 0xD8A1E681;
+ C = D + (C << 14 | C >>> -14);
+ B += ((C & A) | (D & ~A)) + X4 + 0xE7D3FBC8;
+ B = C + (B << 20 | B >>> -20);
+
+ A += ((B & D) | (C & ~D)) + X9 + 0x21E1CDE6;
+ A = B + (A << 5 | A >>> -5);
+ D += ((A & C) | (B & ~C)) + X14 + 0xC33707D6;
+ D = A + (D << 9 | D >>> -9);
+ C += ((D & B) | (A & ~B)) + X3 + 0xF4D50D87;
+ C = D + (C << 14 | C >>> -14);
+ B += ((C & A) | (D & ~A)) + X8 + 0x455A14ED;
+ B = C + (B << 20 | B >>> -20);
+
+ A += ((B & D) | (C & ~D)) + X13 + 0xA9E3E905;
+ A = B + (A << 5 | A >>> -5);
+ D += ((A & C) | (B & ~C)) + X2 + 0xFCEFA3F8;
+ D = A + (D << 9 | D >>> -9);
+ C += ((D & B) | (A & ~B)) + X7 + 0x676F02D9;
+ C = D + (C << 14 | C >>> -14);
+ B += ((C & A) | (D & ~A)) + X12 + 0x8D2A4C8A;
+ B = C + (B << 20 | B >>> -20);
+
+ // round 3
+ A += (B ^ C ^ D) + X5 + 0xFFFA3942;
+ A = B + (A << 4 | A >>> -4);
+ D += (A ^ B ^ C) + X8 + 0x8771F681;
+ D = A + (D << 11 | D >>> -11);
+ C += (D ^ A ^ B) + X11 + 0x6D9D6122;
+ C = D + (C << 16 | C >>> -16);
+ B += (C ^ D ^ A) + X14 + 0xFDE5380C;
+ B = C + (B << 23 | B >>> -23);
+
+ A += (B ^ C ^ D) + X1 + 0xA4BEEA44;
+ A = B + (A << 4 | A >>> -4);
+ D += (A ^ B ^ C) + X4 + 0x4BDECFA9;
+ D = A + (D << 11 | D >>> -11);
+ C += (D ^ A ^ B) + X7 + 0xF6BB4B60;
+ C = D + (C << 16 | C >>> -16);
+ B += (C ^ D ^ A) + X10 + 0xBEBFBC70;
+ B = C + (B << 23 | B >>> -23);
+
+ A += (B ^ C ^ D) + X13 + 0x289B7EC6;
+ A = B + (A << 4 | A >>> -4);
+ D += (A ^ B ^ C) + X0 + 0xEAA127FA;
+ D = A + (D << 11 | D >>> -11);
+ C += (D ^ A ^ B) + X3 + 0xD4EF3085;
+ C = D + (C << 16 | C >>> -16);
+ B += (C ^ D ^ A) + X6 + 0x04881D05;
+ B = C + (B << 23 | B >>> -23);
+
+ A += (B ^ C ^ D) + X9 + 0xD9D4D039;
+ A = B + (A << 4 | A >>> -4);
+ D += (A ^ B ^ C) + X12 + 0xE6DB99E5;
+ D = A + (D << 11 | D >>> -11);
+ C += (D ^ A ^ B) + X15 + 0x1FA27CF8;
+ C = D + (C << 16 | C >>> -16);
+ B += (C ^ D ^ A) + X2 + 0xC4AC5665;
+ B = C + (B << 23 | B >>> -23);
+
+ // round 4
+ A += (C ^ (B | ~D)) + X0 + 0xF4292244;
+ A = B + (A << 6 | A >>> -6);
+ D += (B ^ (A | ~C)) + X7 + 0x432AFF97;
+ D = A + (D << 10 | D >>> -10);
+ C += (A ^ (D | ~B)) + X14 + 0xAB9423A7;
+ C = D + (C << 15 | C >>> -15);
+ B += (D ^ (C | ~A)) + X5 + 0xFC93A039;
+ B = C + (B << 21 | B >>> -21);
+
+ A += (C ^ (B | ~D)) + X12 + 0x655B59C3;
+ A = B + (A << 6 | A >>> -6);
+ D += (B ^ (A | ~C)) + X3 + 0x8F0CCC92;
+ D = A + (D << 10 | D >>> -10);
+ C += (A ^ (D | ~B)) + X10 + 0xFFEFF47D;
+ C = D + (C << 15 | C >>> -15);
+ B += (D ^ (C | ~A)) + X1 + 0x85845dd1;
+ B = C + (B << 21 | B >>> -21);
+
+ A += (C ^ (B | ~D)) + X8 + 0x6FA87E4F;
+ A = B + (A << 6 | A >>> -6);
+ D += (B ^ (A | ~C)) + X15 + 0xFE2CE6E0;
+ D = A + (D << 10 | D >>> -10);
+ C += (A ^ (D | ~B)) + X6 + 0xA3014314;
+ C = D + (C << 15 | C >>> -15);
+ B += (D ^ (C | ~A)) + X13 + 0x4E0811A1;
+ B = C + (B << 21 | B >>> -21);
+
+ A += (C ^ (B | ~D)) + X4 + 0xF7537E82;
+ A = B + (A << 6 | A >>> -6);
+ D += (B ^ (A | ~C)) + X11 + 0xBD3AF235;
+ D = A + (D << 10 | D >>> -10);
+ C += (A ^ (D | ~B)) + X2 + 0x2AD7D2BB;
+ C = D + (C << 15 | C >>> -15);
+ B += (D ^ (C | ~A)) + X9 + 0xEB86D391;
+ B = C + (B << 21 | B >>> -21);
+
+ h0 += A;
+ h1 += B;
+ h2 += C;
+ h3 += D;
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) bits;
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding] = (byte) (bits >>> 56);
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[] { (byte) h0, (byte) (h0 >>> 8),
+ (byte) (h0 >>> 16), (byte) (h0 >>> 24),
+ (byte) h1, (byte) (h1 >>> 8),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 24),
+ (byte) h2, (byte) (h2 >>> 8),
+ (byte) (h2 >>> 16), (byte) (h2 >>> 24),
+ (byte) h3, (byte) (h3 >>> 8),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 24) };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ // magic MD5/RIPEMD128 initialisation constants
+ h0 = 0x67452301;
+ h1 = 0xEFCDAB89;
+ h2 = 0x98BADCFE;
+ h3 = 0x10325476;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new MD5().digest())));
+ }
+ return valid.booleanValue();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/RipeMD128.java b/libjava/classpath/gnu/java/security/hash/RipeMD128.java
new file mode 100644
index 00000000000..83e8f25044d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/RipeMD128.java
@@ -0,0 +1,291 @@
+/* RipeMD128.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>RIPEMD-128 is a 128-bit message digest.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html">
+ * RIPEMD160</a>: A Strengthened Version of RIPEMD.<br>
+ * Hans Dobbertin, Antoon Bosselaers and Bart Preneel.</li>
+ * </ol>
+ */
+public class RipeMD128 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "CDF26213A150DC3ECB610F18F6B38B46";
+
+ /** Constants for the transform method. */
+ // selection of message word
+ private static final int[] R = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0,
+ 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8,
+ 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10,
+ 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 };
+
+ private static final int[] Rp = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1,
+ 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14,
+ 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14,
+ 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4,
+ 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 };
+
+ // amount for rotate left (rol)
+ private static final int[] S = { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15,
+ 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12,
+ 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9,
+ 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12,
+ 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5,
+ 12 };
+
+ private static final int[] Sp = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11,
+ 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11,
+ 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8,
+ 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15,
+ 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5,
+ 15, 8 };
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 128-bit h0, h1, h2, h3 (interim result) */
+ private int h0, h1, h2, h3;
+
+ /** 512 bits work buffer = 16 x 32-bit words */
+ private int[] X = new int[16];
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public RipeMD128()
+ {
+ super(Registry.RIPEMD128_HASH, 16, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private RipeMD128(RipeMD128 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new RipeMD128(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ int A, B, C, D, Ap, Bp, Cp, Dp, T, s, i;
+
+ // encode 64 bytes from input block into an array of 16 unsigned
+ // integers.
+ for (i = 0; i < 16; i++)
+ {
+ X[i] = (in[offset++] & 0xFF) | (in[offset++] & 0xFF) << 8
+ | (in[offset++] & 0xFF) << 16 | in[offset++] << 24;
+ }
+
+ A = Ap = h0;
+ B = Bp = h1;
+ C = Cp = h2;
+ D = Dp = h3;
+
+ for (i = 0; i < 16; i++)
+ { // rounds 0...15
+ s = S[i];
+ T = A + (B ^ C ^ D) + X[i];
+ A = D;
+ D = C;
+ C = B;
+ B = T << s | T >>> (32 - s);
+
+ s = Sp[i];
+ T = Ap + ((Bp & Dp) | (Cp & ~Dp)) + X[Rp[i]] + 0x50A28BE6;
+ Ap = Dp;
+ Dp = Cp;
+ Cp = Bp;
+ Bp = T << s | T >>> (32 - s);
+ }
+
+ for (; i < 32; i++)
+ { // rounds 16...31
+ s = S[i];
+ T = A + ((B & C) | (~B & D)) + X[R[i]] + 0x5A827999;
+ A = D;
+ D = C;
+ C = B;
+ B = T << s | T >>> (32 - s);
+
+ s = Sp[i];
+ T = Ap + ((Bp | ~Cp) ^ Dp) + X[Rp[i]] + 0x5C4DD124;
+ Ap = Dp;
+ Dp = Cp;
+ Cp = Bp;
+ Bp = T << s | T >>> (32 - s);
+ }
+
+ for (; i < 48; i++)
+ { // rounds 32...47
+ s = S[i];
+ T = A + ((B | ~C) ^ D) + X[R[i]] + 0x6ED9EBA1;
+ A = D;
+ D = C;
+ C = B;
+ B = T << s | T >>> (32 - s);
+
+ s = Sp[i];
+ T = Ap + ((Bp & Cp) | (~Bp & Dp)) + X[Rp[i]] + 0x6D703EF3;
+ Ap = Dp;
+ Dp = Cp;
+ Cp = Bp;
+ Bp = T << s | T >>> (32 - s);
+ }
+
+ for (; i < 64; i++)
+ { // rounds 48...63
+ s = S[i];
+ T = A + ((B & D) | (C & ~D)) + X[R[i]] + 0x8F1BBCDC;
+ A = D;
+ D = C;
+ C = B;
+ B = T << s | T >>> (32 - s);
+
+ s = Sp[i];
+ T = Ap + (Bp ^ Cp ^ Dp) + X[Rp[i]];
+ Ap = Dp;
+ Dp = Cp;
+ Cp = Bp;
+ Bp = T << s | T >>> (32 - s);
+ }
+
+ T = h1 + C + Dp;
+ h1 = h2 + D + Ap;
+ h2 = h3 + A + Bp;
+ h3 = h0 + B + Cp;
+ h0 = T;
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) bits;
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding] = (byte) (bits >>> 56);
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[] { (byte) h0, (byte) (h0 >>> 8),
+ (byte) (h0 >>> 16), (byte) (h0 >>> 24),
+ (byte) h1, (byte) (h1 >>> 8),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 24),
+ (byte) h2, (byte) (h2 >>> 8),
+ (byte) (h2 >>> 16), (byte) (h2 >>> 24),
+ (byte) h3, (byte) (h3 >>> 8),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 24) };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ // magic RIPEMD128 initialisation constants
+ h0 = 0x67452301;
+ h1 = 0xEFCDAB89;
+ h2 = 0x98BADCFE;
+ h3 = 0x10325476;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean
+ (DIGEST0.equals(Util.toString(new RipeMD128().digest())));
+ }
+ return valid.booleanValue();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/RipeMD160.java b/libjava/classpath/gnu/java/security/hash/RipeMD160.java
new file mode 100644
index 00000000000..73ecc5161d7
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/RipeMD160.java
@@ -0,0 +1,328 @@
+/* RipeMD160.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>RIPEMD-160 is a 160-bit message digest.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html">
+ * RIPEMD160</a>: A Strengthened Version of RIPEMD.<br>
+ * Hans Dobbertin, Antoon Bosselaers and Bart Preneel.</li>
+ * </ol>
+ */
+public class RipeMD160 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "9C1185A5C5E9FC54612808977EE8F548B2258D31";
+
+ // selection of message word
+ private static final int[] R = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0,
+ 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8,
+ 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10,
+ 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0,
+ 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15,
+ 13 };
+
+ private static final int[] Rp = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1,
+ 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14,
+ 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14,
+ 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4,
+ 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
+ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0,
+ 3, 9, 11 };
+
+ // amount for rotate left (rol)
+ private static final int[] S = { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15,
+ 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12,
+ 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9,
+ 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12,
+ 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5,
+ 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13,
+ 14, 11, 8, 5, 6 };
+
+ private static final int[] Sp = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11,
+ 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11,
+ 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8,
+ 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15,
+ 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5,
+ 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6,
+ 5, 15, 13, 11, 11 };
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 160-bit h0, h1, h2, h3, h4 (interim result) */
+ private int h0, h1, h2, h3, h4;
+
+ /** 512 bits work buffer = 16 x 32-bit words */
+ private int[] X = new int[16];
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public RipeMD160()
+ {
+ super(Registry.RIPEMD160_HASH, 20, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private RipeMD160(RipeMD160 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return (new RipeMD160(this));
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ int A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, T, s, i;
+
+ // encode 64 bytes from input block into an array of 16 unsigned integers
+ for (i = 0; i < 16; i++)
+ {
+ X[i] = (in[offset++] & 0xFF) | (in[offset++] & 0xFF) << 8
+ | (in[offset++] & 0xFF) << 16 | in[offset++] << 24;
+ }
+
+ A = Ap = h0;
+ B = Bp = h1;
+ C = Cp = h2;
+ D = Dp = h3;
+ E = Ep = h4;
+
+ for (i = 0; i < 16; i++)
+ { // rounds 0...15
+ s = S[i];
+ T = A + (B ^ C ^ D) + X[i];
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + (Bp ^ (Cp | ~Dp)) + X[Rp[i]] + 0x50A28BE6;
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ for (; i < 32; i++)
+ { // rounds 16...31
+ s = S[i];
+ T = A + ((B & C) | (~B & D)) + X[R[i]] + 0x5A827999;
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + ((Bp & Dp) | (Cp & ~Dp)) + X[Rp[i]] + 0x5C4DD124;
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ for (; i < 48; i++)
+ { // rounds 32...47
+ s = S[i];
+ T = A + ((B | ~C) ^ D) + X[R[i]] + 0x6ED9EBA1;
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + ((Bp | ~Cp) ^ Dp) + X[Rp[i]] + 0x6D703EF3;
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ for (; i < 64; i++)
+ { // rounds 48...63
+ s = S[i];
+ T = A + ((B & D) | (C & ~D)) + X[R[i]] + 0x8F1BBCDC;
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + ((Bp & Cp) | (~Bp & Dp)) + X[Rp[i]] + 0x7A6D76E9;
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ for (; i < 80; i++)
+ { // rounds 64...79
+ s = S[i];
+ T = A + (B ^ (C | ~D)) + X[R[i]] + 0xA953FD4E;
+ A = E;
+ E = D;
+ D = C << 10 | C >>> 22;
+ C = B;
+ B = (T << s | T >>> (32 - s)) + A;
+
+ s = Sp[i];
+ T = Ap + (Bp ^ Cp ^ Dp) + X[Rp[i]];
+ Ap = Ep;
+ Ep = Dp;
+ Dp = Cp << 10 | Cp >>> 22;
+ Cp = Bp;
+ Bp = (T << s | T >>> (32 - s)) + Ap;
+ }
+
+ T = h1 + C + Dp;
+ h1 = h2 + D + Ep;
+ h2 = h3 + E + Ap;
+ h3 = h4 + A + Bp;
+ h4 = h0 + B + Cp;
+ h0 = T;
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) bits;
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding] = (byte) (bits >>> 56);
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[] { (byte) h0, (byte) (h0 >>> 8),
+ (byte) (h0 >>> 16), (byte) (h0 >>> 24),
+ (byte) h1, (byte) (h1 >>> 8),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 24),
+ (byte) h2, (byte) (h2 >>> 8),
+ (byte) (h2 >>> 16), (byte) (h2 >>> 24),
+ (byte) h3, (byte) (h3 >>> 8),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 24),
+ (byte) h4, (byte) (h4 >>> 8),
+ (byte) (h4 >>> 16), (byte) (h4 >>> 24) };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ // magic RIPEMD160 initialisation constants
+ h0 = 0x67452301;
+ h1 = 0xEFCDAB89;
+ h2 = 0x98BADCFE;
+ h3 = 0x10325476;
+ h4 = 0xC3D2E1F0;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean
+ (DIGEST0.equals(Util.toString(new RipeMD160().digest())));
+ }
+ return valid.booleanValue();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/Sha160.java b/libjava/classpath/gnu/java/security/hash/Sha160.java
new file mode 100644
index 00000000000..bf5f45652a1
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/Sha160.java
@@ -0,0 +1,308 @@
+/* Sha160.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>The Secure Hash Algorithm (SHA-1) is required for use with the Digital
+ * Signature Algorithm (DSA) as specified in the Digital Signature Standard
+ * (DSS) and whenever a secure hash algorithm is required for federal
+ * applications. For a message of length less than 2^64 bits, the SHA-1
+ * produces a 160-bit condensed representation of the message called a message
+ * digest. The message digest is used during generation of a signature for the
+ * message. The SHA-1 is also used to compute a message digest for the received
+ * version of the message during the process of verifying the signature. Any
+ * change to the message in transit will, with very high probability, result in
+ * a different message digest, and the signature will fail to verify.</p>
+ *
+ * <p>The SHA-1 is designed to have the following properties: it is
+ * computationally infeasible to find a message which corresponds to a given
+ * message digest, or to find two different messages which produce the same
+ * message digest.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.itl.nist.gov/fipspubs/fip180-1.htm">SECURE HASH
+ * STANDARD</a><br>
+ * Federal Information, Processing Standards Publication 180-1, 1995 April 17.
+ * </li>
+ * </ol>
+ */
+public class Sha160 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "A9993E364706816ABA3E25717850C26C9CD0D89D";
+
+ private static final int[] w = new int[80];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 160-bit interim result. */
+ private int h0, h1, h2, h3, h4;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Sha160()
+ {
+ super(Registry.SHA160_HASH, 20, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Sha160(Sha160 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final int[] G(int hh0, int hh1, int hh2, int hh3, int hh4,
+ byte[] in, int offset)
+ {
+ // int[] w = new int[80];
+ // int i, T;
+ // for (i = 0; i < 16; i++) {
+ // w[i] = in[offset++] << 24 |
+ // (in[offset++] & 0xFF) << 16 |
+ // (in[offset++] & 0xFF) << 8 |
+ // (in[offset++] & 0xFF);
+ // }
+ // for (i = 16; i < 80; i++) {
+ // T = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
+ // w[i] = T << 1 | T >>> 31;
+ // }
+
+ // return sha(hh0, hh1, hh2, hh3, hh4, in, offset, w);
+ return sha(hh0, hh1, hh2, hh3, hh4, in, offset);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Sha160(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ // int i, T;
+ // for (i = 0; i < 16; i++) {
+ // W[i] = in[offset++] << 24 |
+ // (in[offset++] & 0xFF) << 16 |
+ // (in[offset++] & 0xFF) << 8 |
+ // (in[offset++] & 0xFF);
+ // }
+ // for (i = 16; i < 80; i++) {
+ // T = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+ // W[i] = T << 1 | T >>> 31;
+ // }
+
+ // int[] result = sha(h0, h1, h2, h3, h4, in, offset, W);
+ int[] result = sha(h0, h1, h2, h3, h4, in, offset);
+
+ h0 = result[0];
+ h1 = result[1];
+ h2 = result[2];
+ h3 = result[3];
+ h4 = result[4];
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) (bits >>> 56);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ byte[] result = new byte[] { (byte) (h0 >>> 24), (byte) (h0 >>> 16),
+ (byte) (h0 >>> 8), (byte) h0,
+ (byte) (h1 >>> 24), (byte) (h1 >>> 16),
+ (byte) (h1 >>> 8), (byte) h1,
+ (byte) (h2 >>> 24), (byte) (h2 >>> 16),
+ (byte) (h2 >>> 8), (byte) h2,
+ (byte) (h3 >>> 24), (byte) (h3 >>> 16),
+ (byte) (h3 >>> 8), (byte) h3,
+ (byte) (h4 >>> 24), (byte) (h4 >>> 16),
+ (byte) (h4 >>> 8), (byte) h4 };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ // magic SHA-1/RIPEMD160 initialisation constants
+ h0 = 0x67452301;
+ h1 = 0xEFCDAB89;
+ h2 = 0x98BADCFE;
+ h3 = 0x10325476;
+ h4 = 0xC3D2E1F0;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ Sha160 md = new Sha160();
+ md.update((byte) 0x61); // a
+ md.update((byte) 0x62); // b
+ md.update((byte) 0x63); // c
+ String result = Util.toString(md.digest());
+ valid = new Boolean(DIGEST0.equals(result));
+ }
+ return valid.booleanValue();
+ }
+
+ // SHA specific methods ----------------------------------------------------
+
+ private static final synchronized int[]
+ // sha(int hh0, int hh1, int hh2, int hh3, int hh4, byte[] in, int offset, int[] w) {
+ sha(int hh0, int hh1, int hh2, int hh3, int hh4, byte[] in, int offset)
+ {
+ int A = hh0;
+ int B = hh1;
+ int C = hh2;
+ int D = hh3;
+ int E = hh4;
+ int r, T;
+
+ for (r = 0; r < 16; r++)
+ {
+ w[r] = in[offset++] << 24 | (in[offset++] & 0xFF) << 16
+ | (in[offset++] & 0xFF) << 8 | (in[offset++] & 0xFF);
+ }
+ for (r = 16; r < 80; r++)
+ {
+ T = w[r - 3] ^ w[r - 8] ^ w[r - 14] ^ w[r - 16];
+ w[r] = T << 1 | T >>> 31;
+ }
+
+ // rounds 0-19
+ for (r = 0; r < 20; r++)
+ {
+ T = (A << 5 | A >>> 27) + ((B & C) | (~B & D)) + E + w[r] + 0x5A827999;
+ E = D;
+ D = C;
+ C = B << 30 | B >>> 2;
+ B = A;
+ A = T;
+ }
+
+ // rounds 20-39
+ for (r = 20; r < 40; r++)
+ {
+ T = (A << 5 | A >>> 27) + (B ^ C ^ D) + E + w[r] + 0x6ED9EBA1;
+ E = D;
+ D = C;
+ C = B << 30 | B >>> 2;
+ B = A;
+ A = T;
+ }
+
+ // rounds 40-59
+ for (r = 40; r < 60; r++)
+ {
+ T = (A << 5 | A >>> 27) + (B & C | B & D | C & D) + E + w[r]
+ + 0x8F1BBCDC;
+ E = D;
+ D = C;
+ C = B << 30 | B >>> 2;
+ B = A;
+ A = T;
+ }
+
+ // rounds 60-79
+ for (r = 60; r < 80; r++)
+ {
+ T = (A << 5 | A >>> 27) + (B ^ C ^ D) + E + w[r] + 0xCA62C1D6;
+ E = D;
+ D = C;
+ C = B << 30 | B >>> 2;
+ B = A;
+ A = T;
+ }
+
+ return new int[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E };
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/Sha256.java b/libjava/classpath/gnu/java/security/hash/Sha256.java
new file mode 100644
index 00000000000..9ef70a1a6a3
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/Sha256.java
@@ -0,0 +1,278 @@
+/* Sha256.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>Implementation of SHA2-1 [SHA-256] per the IETF Draft Specification.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://ftp.ipv4.heanet.ie/pub/ietf/internet-drafts/draft-ietf-ipsec-ciph-aes-cbc-03.txt">
+ * Descriptions of SHA-256, SHA-384, and SHA-512</a>,</li>
+ * <li>http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf</li>
+ * </ol>
+ */
+public class Sha256 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+ private static final int[] k = { 0x428a2f98, 0x71374491, 0xb5c0fbcf,
+ 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98,
+ 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
+ 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
+ 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8,
+ 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85,
+ 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e,
+ 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819,
+ 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c,
+ 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee,
+ 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
+ 0xc67178f2 };
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ private static final String DIGEST0 = "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD";
+
+ private static final int[] w = new int[64];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 256-bit interim result. */
+ private int h0, h1, h2, h3, h4, h5, h6, h7;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Sha256()
+ {
+ super(Registry.SHA256_HASH, 32, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Sha256(Sha256 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.h5 = md.h5;
+ this.h6 = md.h6;
+ this.h7 = md.h7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final int[] G(int hh0, int hh1, int hh2, int hh3, int hh4,
+ int hh5, int hh6, int hh7, byte[] in, int offset)
+ {
+ return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Sha256(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ int[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
+
+ h0 = result[0];
+ h1 = result[1];
+ h2 = result[2];
+ h3 = result[3];
+ h4 = result[4];
+ h5 = result[5];
+ h6 = result[6];
+ h7 = result[7];
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] result = new byte[padding + 8];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ long bits = count << 3;
+ result[padding++] = (byte) (bits >>> 56);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ return new byte[] { (byte) (h0 >>> 24), (byte) (h0 >>> 16),
+ (byte) (h0 >>> 8), (byte) h0, (byte) (h1 >>> 24),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 8), (byte) h1,
+ (byte) (h2 >>> 24), (byte) (h2 >>> 16),
+ (byte) (h2 >>> 8), (byte) h2, (byte) (h3 >>> 24),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 8), (byte) h3,
+ (byte) (h4 >>> 24), (byte) (h4 >>> 16),
+ (byte) (h4 >>> 8), (byte) h4, (byte) (h5 >>> 24),
+ (byte) (h5 >>> 16), (byte) (h5 >>> 8), (byte) h5,
+ (byte) (h6 >>> 24), (byte) (h6 >>> 16),
+ (byte) (h6 >>> 8), (byte) h6, (byte) (h7 >>> 24),
+ (byte) (h7 >>> 16), (byte) (h7 >>> 8), (byte) h7 };
+ }
+
+ protected void resetContext()
+ {
+ // magic SHA-256 initialisation constants
+ h0 = 0x6a09e667;
+ h1 = 0xbb67ae85;
+ h2 = 0x3c6ef372;
+ h3 = 0xa54ff53a;
+ h4 = 0x510e527f;
+ h5 = 0x9b05688c;
+ h6 = 0x1f83d9ab;
+ h7 = 0x5be0cd19;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ Sha256 md = new Sha256();
+ md.update((byte) 0x61); // a
+ md.update((byte) 0x62); // b
+ md.update((byte) 0x63); // c
+ String result = Util.toString(md.digest());
+ valid = new Boolean(DIGEST0.equals(result));
+ }
+
+ return valid.booleanValue();
+ }
+
+ // SHA specific methods ----------------------------------------------------
+
+ private static final synchronized int[] sha(int hh0, int hh1, int hh2,
+ int hh3, int hh4, int hh5,
+ int hh6, int hh7, byte[] in,
+ int offset)
+ {
+ int A = hh0;
+ int B = hh1;
+ int C = hh2;
+ int D = hh3;
+ int E = hh4;
+ int F = hh5;
+ int G = hh6;
+ int H = hh7;
+ int r, T, T2;
+
+ for (r = 0; r < 16; r++)
+ {
+ w[r] = (in[offset++] << 24 | (in[offset++] & 0xFF) << 16
+ | (in[offset++] & 0xFF) << 8 | (in[offset++] & 0xFF));
+ }
+ for (r = 16; r < 64; r++)
+ {
+ T = w[r - 2];
+ T2 = w[r - 15];
+ w[r] = ((((T >>> 17) | (T << 15)) ^ ((T >>> 19) | (T << 13)) ^ (T >>> 10))
+ + w[r - 7]
+ + (((T2 >>> 7) | (T2 << 25)) ^ ((T2 >>> 18) | (T2 << 14)) ^ (T2 >>> 3))
+ + w[r - 16]);
+ }
+
+ for (r = 0; r < 64; r++)
+ {
+ T = (H
+ + (((E >>> 6) | (E << 26)) ^ ((E >>> 11) | (E << 21)) ^ ((E >>> 25) | (E << 7)))
+ + ((E & F) ^ (~E & G)) + k[r] + w[r]);
+ T2 = ((((A >>> 2) | (A << 30)) ^ ((A >>> 13) | (A << 19)) ^ ((A >>> 22) | (A << 10)))
+ + ((A & B) ^ (A & C) ^ (B & C)));
+ H = G;
+ G = F;
+ F = E;
+ E = D + T;
+ D = C;
+ C = B;
+ B = A;
+ A = T + T2;
+ }
+
+ return new int[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E, hh5 + F,
+ hh6 + G, hh7 + H };
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/Sha384.java b/libjava/classpath/gnu/java/security/hash/Sha384.java
new file mode 100644
index 00000000000..2f619dc984d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/Sha384.java
@@ -0,0 +1,322 @@
+/* Sha384.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>Implementation of SHA2-2 [SHA-384] per the IETF Draft Specification.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://ftp.ipv4.heanet.ie/pub/ietf/internet-drafts/draft-ietf-ipsec-ciph-aes-cbc-03.txt">
+ * Descriptions of SHA-256, SHA-384, and SHA-512</a>,</li>
+ * <li>http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf</li>
+ * </ol>
+ */
+public class Sha384 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final long[] k = { 0x428a2f98d728ae22L, 0x7137449123ef65cdL,
+ 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
+ 0x3956c25bf348b538L, 0x59f111f1b605d019L,
+ 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
+ 0xd807aa98a3030242L, 0x12835b0145706fbeL,
+ 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
+ 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L,
+ 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
+ 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L,
+ 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
+ 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L,
+ 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
+ 0x983e5152ee66dfabL, 0xa831c66d2db43210L,
+ 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
+ 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L,
+ 0x06ca6351e003826fL, 0x142929670a0e6e70L,
+ 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L,
+ 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
+ 0x650a73548baf63deL, 0x766a0abb3c77b2a8L,
+ 0x81c2c92e47edaee6L, 0x92722c851482353bL,
+ 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L,
+ 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
+ 0xd192e819d6ef5218L, 0xd69906245565a910L,
+ 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
+ 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L,
+ 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
+ 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL,
+ 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
+ 0x748f82ee5defb2fcL, 0x78a5636f43172f60L,
+ 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
+ 0x90befffa23631e28L, 0xa4506cebde82bde9L,
+ 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
+ 0xca273eceea26619cL, 0xd186b8c721c0c207L,
+ 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
+ 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L,
+ 0x113f9804bef90daeL, 0x1b710b35131c471bL,
+ 0x28db77f523047d84L, 0x32caab7b40c72493L,
+ 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
+ 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL,
+ 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L };
+
+ private static final int BLOCK_SIZE = 128; // inner block size in bytes
+
+ private static final String DIGEST0 = "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED"
+ + "8086072BA1E7CC2358BAECA134C825A7";
+
+ private static final long[] w = new long[80];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 512-bit interim result. */
+ private long h0, h1, h2, h3, h4, h5, h6, h7;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Sha384()
+ {
+ super(Registry.SHA384_HASH, 48, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Sha384(Sha384 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.h5 = md.h5;
+ this.h6 = md.h6;
+ this.h7 = md.h7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final long[] G(long hh0, long hh1, long hh2, long hh3,
+ long hh4, long hh5, long hh6, long hh7,
+ byte[] in, int offset)
+ {
+ return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Sha384(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ long[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
+
+ h0 = result[0];
+ h1 = result[1];
+ h2 = result[2];
+ h3 = result[3];
+ h4 = result[4];
+ h5 = result[5];
+ h6 = result[6];
+ h7 = result[7];
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 112) ? (112 - n) : (240 - n);
+ byte[] result = new byte[padding + 16];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ // TODO: FIX Only ~35 bits of 128 bit counter usable this way
+ long bits = count << 3;
+ padding += 8;
+ result[padding++] = (byte) (bits >>> 56);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ return new byte[] { (byte) (h0 >>> 56), (byte) (h0 >>> 48),
+ (byte) (h0 >>> 40), (byte) (h0 >>> 32),
+ (byte) (h0 >>> 24), (byte) (h0 >>> 16),
+ (byte) (h0 >>> 8), (byte) h0, (byte) (h1 >>> 56),
+ (byte) (h1 >>> 48), (byte) (h1 >>> 40),
+ (byte) (h1 >>> 32), (byte) (h1 >>> 24),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 8), (byte) h1,
+ (byte) (h2 >>> 56), (byte) (h2 >>> 48),
+ (byte) (h2 >>> 40), (byte) (h2 >>> 32),
+ (byte) (h2 >>> 24), (byte) (h2 >>> 16),
+ (byte) (h2 >>> 8), (byte) h2, (byte) (h3 >>> 56),
+ (byte) (h3 >>> 48), (byte) (h3 >>> 40),
+ (byte) (h3 >>> 32), (byte) (h3 >>> 24),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 8), (byte) h3,
+ (byte) (h4 >>> 56), (byte) (h4 >>> 48),
+ (byte) (h4 >>> 40), (byte) (h4 >>> 32),
+ (byte) (h4 >>> 24), (byte) (h4 >>> 16),
+ (byte) (h4 >>> 8), (byte) h4, (byte) (h5 >>> 56),
+ (byte) (h5 >>> 48), (byte) (h5 >>> 40),
+ (byte) (h5 >>> 32), (byte) (h5 >>> 24),
+ (byte) (h5 >>> 16), (byte) (h5 >>> 8), (byte) h5
+ // (byte)(h6 >>> 56), (byte)(h6 >>> 48), (byte)(h6 >>> 40), (byte)(h6 >>> 32),
+ // (byte)(h6 >>> 24), (byte)(h6 >>> 16), (byte)(h6 >>> 8), (byte) h6,
+ // (byte)(h7 >>> 56), (byte)(h7 >>> 48), (byte)(h7 >>> 40), (byte)(h7 >>> 32),
+ // (byte)(h7 >>> 24), (byte)(h7 >>> 16), (byte)(h7 >>> 8), (byte) h7
+ };
+ }
+
+ protected void resetContext()
+ {
+ // magic SHA-384 initialisation constants
+ h0 = 0xcbbb9d5dc1059ed8L;
+ h1 = 0x629a292a367cd507L;
+ h2 = 0x9159015a3070dd17L;
+ h3 = 0x152fecd8f70e5939L;
+ h4 = 0x67332667ffc00b31L;
+ h5 = 0x8eb44a8768581511L;
+ h6 = 0xdb0c2e0d64f98fa7L;
+ h7 = 0x47b5481dbefa4fa4L;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ Sha384 md = new Sha384();
+ md.update((byte) 0x61); // a
+ md.update((byte) 0x62); // b
+ md.update((byte) 0x63); // c
+ String result = Util.toString(md.digest());
+ valid = new Boolean(DIGEST0.equals(result));
+ }
+ return valid.booleanValue();
+ }
+
+ // SHA specific methods ----------------------------------------------------
+
+ private static final synchronized long[] sha(long hh0, long hh1, long hh2,
+ long hh3, long hh4, long hh5,
+ long hh6, long hh7, byte[] in,
+ int offset)
+ {
+ long A = hh0;
+ long B = hh1;
+ long C = hh2;
+ long D = hh3;
+ long E = hh4;
+ long F = hh5;
+ long G = hh6;
+ long H = hh7;
+ long T, T2;
+ int r;
+
+ for (r = 0; r < 16; r++)
+ {
+ w[r] = (long) in[offset++] << 56 | ((long) in[offset++] & 0xFF) << 48
+ | ((long) in[offset++] & 0xFF) << 40
+ | ((long) in[offset++] & 0xFF) << 32
+ | ((long) in[offset++] & 0xFF) << 24
+ | ((long) in[offset++] & 0xFF) << 16
+ | ((long) in[offset++] & 0xFF) << 8
+ | ((long) in[offset++] & 0xFF);
+ }
+ for (r = 16; r < 80; r++)
+ {
+ T = w[r - 2];
+ T2 = w[r - 15];
+ w[r] = (((T >>> 19) | (T << 45)) ^ ((T >>> 61) | (T << 3)) ^ (T >>> 6))
+ + w[r - 7]
+ + (((T2 >>> 1) | (T2 << 63)) ^ ((T2 >>> 8) | (T2 << 56)) ^ (T2 >>> 7))
+ + w[r - 16];
+ }
+
+ for (r = 0; r < 80; r++)
+ {
+
+ T = H
+ + (((E >>> 14) | (E << 50)) ^ ((E >>> 18) | (E << 46)) ^ ((E >>> 41) | (E << 23)))
+ + ((E & F) ^ ((~E) & G)) + k[r] + w[r];
+ // T IS INCORRECT SOMEHOW
+ T2 = (((A >>> 28) | (A << 36)) ^ ((A >>> 34) | (A << 30)) ^ ((A >>> 39) | (A << 25)))
+ + ((A & B) ^ (A & C) ^ (B & C));
+ H = G;
+ G = F;
+ F = E;
+ E = D + T;
+ D = C;
+ C = B;
+ B = A;
+ A = T + T2;
+ }
+
+ return new long[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E, hh5 + F,
+ hh6 + G, hh7 + H };
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/Sha512.java b/libjava/classpath/gnu/java/security/hash/Sha512.java
new file mode 100644
index 00000000000..798b34dfc1d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/Sha512.java
@@ -0,0 +1,322 @@
+/* Sha512.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>Implementation of SHA2-3 [SHA-512] per the IETF Draft Specification.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://ftp.ipv4.heanet.ie/pub/ietf/internet-drafts/draft-ietf-ipsec-ciph-aes-cbc-03.txt">
+ * Descriptions of SHA-256, SHA-384, and SHA-512</a>,</li>
+ * <li>http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf</li>
+ * </ol>
+ */
+public class Sha512 extends BaseHash
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final long[] k = { 0x428a2f98d728ae22L, 0x7137449123ef65cdL,
+ 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
+ 0x3956c25bf348b538L, 0x59f111f1b605d019L,
+ 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
+ 0xd807aa98a3030242L, 0x12835b0145706fbeL,
+ 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
+ 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L,
+ 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
+ 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L,
+ 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
+ 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L,
+ 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
+ 0x983e5152ee66dfabL, 0xa831c66d2db43210L,
+ 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
+ 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L,
+ 0x06ca6351e003826fL, 0x142929670a0e6e70L,
+ 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L,
+ 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
+ 0x650a73548baf63deL, 0x766a0abb3c77b2a8L,
+ 0x81c2c92e47edaee6L, 0x92722c851482353bL,
+ 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L,
+ 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
+ 0xd192e819d6ef5218L, 0xd69906245565a910L,
+ 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
+ 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L,
+ 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
+ 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL,
+ 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
+ 0x748f82ee5defb2fcL, 0x78a5636f43172f60L,
+ 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
+ 0x90befffa23631e28L, 0xa4506cebde82bde9L,
+ 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
+ 0xca273eceea26619cL, 0xd186b8c721c0c207L,
+ 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
+ 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L,
+ 0x113f9804bef90daeL, 0x1b710b35131c471bL,
+ 0x28db77f523047d84L, 0x32caab7b40c72493L,
+ 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
+ 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL,
+ 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L };
+
+ private static final int BLOCK_SIZE = 128; // inner block size in bytes
+
+ private static final String DIGEST0 = "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A"
+ + "2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F";
+
+ private static final long[] w = new long[80];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** 512-bit interim result. */
+ private long h0, h1, h2, h3, h4, h5, h6, h7;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Sha512()
+ {
+ super(Registry.SHA512_HASH, 64, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Sha512(Sha512 md)
+ {
+ this();
+
+ this.h0 = md.h0;
+ this.h1 = md.h1;
+ this.h2 = md.h2;
+ this.h3 = md.h3;
+ this.h4 = md.h4;
+ this.h5 = md.h5;
+ this.h6 = md.h6;
+ this.h7 = md.h7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final long[] G(long hh0, long hh1, long hh2, long hh3,
+ long hh4, long hh5, long hh6, long hh7,
+ byte[] in, int offset)
+ {
+ return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return new Sha512(this);
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ long[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset);
+
+ h0 = result[0];
+ h1 = result[1];
+ h2 = result[2];
+ h3 = result[3];
+ h4 = result[4];
+ h5 = result[5];
+ h6 = result[6];
+ h7 = result[7];
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 112) ? (112 - n) : (240 - n);
+ byte[] result = new byte[padding + 16];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save number of bits, casting the long to an array of 8 bytes
+ // TODO: FIX Only ~35 bits of 128 bit counter usable this way
+ long bits = count << 3;
+ padding += 8;
+ result[padding++] = (byte) (bits >>> 56);
+ result[padding++] = (byte) (bits >>> 48);
+ result[padding++] = (byte) (bits >>> 40);
+ result[padding++] = (byte) (bits >>> 32);
+ result[padding++] = (byte) (bits >>> 24);
+ result[padding++] = (byte) (bits >>> 16);
+ result[padding++] = (byte) (bits >>> 8);
+ result[padding] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ return new byte[] { (byte) (h0 >>> 56), (byte) (h0 >>> 48),
+ (byte) (h0 >>> 40), (byte) (h0 >>> 32),
+ (byte) (h0 >>> 24), (byte) (h0 >>> 16),
+ (byte) (h0 >>> 8), (byte) h0, (byte) (h1 >>> 56),
+ (byte) (h1 >>> 48), (byte) (h1 >>> 40),
+ (byte) (h1 >>> 32), (byte) (h1 >>> 24),
+ (byte) (h1 >>> 16), (byte) (h1 >>> 8), (byte) h1,
+ (byte) (h2 >>> 56), (byte) (h2 >>> 48),
+ (byte) (h2 >>> 40), (byte) (h2 >>> 32),
+ (byte) (h2 >>> 24), (byte) (h2 >>> 16),
+ (byte) (h2 >>> 8), (byte) h2, (byte) (h3 >>> 56),
+ (byte) (h3 >>> 48), (byte) (h3 >>> 40),
+ (byte) (h3 >>> 32), (byte) (h3 >>> 24),
+ (byte) (h3 >>> 16), (byte) (h3 >>> 8), (byte) h3,
+ (byte) (h4 >>> 56), (byte) (h4 >>> 48),
+ (byte) (h4 >>> 40), (byte) (h4 >>> 32),
+ (byte) (h4 >>> 24), (byte) (h4 >>> 16),
+ (byte) (h4 >>> 8), (byte) h4, (byte) (h5 >>> 56),
+ (byte) (h5 >>> 48), (byte) (h5 >>> 40),
+ (byte) (h5 >>> 32), (byte) (h5 >>> 24),
+ (byte) (h5 >>> 16), (byte) (h5 >>> 8), (byte) h5,
+ (byte) (h6 >>> 56), (byte) (h6 >>> 48),
+ (byte) (h6 >>> 40), (byte) (h6 >>> 32),
+ (byte) (h6 >>> 24), (byte) (h6 >>> 16),
+ (byte) (h6 >>> 8), (byte) h6, (byte) (h7 >>> 56),
+ (byte) (h7 >>> 48), (byte) (h7 >>> 40),
+ (byte) (h7 >>> 32), (byte) (h7 >>> 24),
+ (byte) (h7 >>> 16), (byte) (h7 >>> 8), (byte) h7 };
+ }
+
+ protected void resetContext()
+ {
+ // magic SHA-512 initialisation constants
+ h0 = 0x6a09e667f3bcc908L;
+ h1 = 0xbb67ae8584caa73bL;
+ h2 = 0x3c6ef372fe94f82bL;
+ h3 = 0xa54ff53a5f1d36f1L;
+ h4 = 0x510e527fade682d1L;
+ h5 = 0x9b05688c2b3e6c1fL;
+ h6 = 0x1f83d9abfb41bd6bL;
+ h7 = 0x5be0cd19137e2179L;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ Sha512 md = new Sha512();
+ md.update((byte) 0x61); // a
+ md.update((byte) 0x62); // b
+ md.update((byte) 0x63); // c
+ String result = Util.toString(md.digest());
+ valid = new Boolean(DIGEST0.equals(result));
+ }
+ return valid.booleanValue();
+ }
+
+ // SHA specific methods ----------------------------------------------------
+
+ private static final synchronized long[] sha(long hh0, long hh1, long hh2,
+ long hh3, long hh4, long hh5,
+ long hh6, long hh7, byte[] in,
+ int offset)
+ {
+ long A = hh0;
+ long B = hh1;
+ long C = hh2;
+ long D = hh3;
+ long E = hh4;
+ long F = hh5;
+ long G = hh6;
+ long H = hh7;
+ long T, T2;
+ int r;
+
+ for (r = 0; r < 16; r++)
+ {
+ w[r] = (long) in[offset++] << 56 | ((long) in[offset++] & 0xFF) << 48
+ | ((long) in[offset++] & 0xFF) << 40
+ | ((long) in[offset++] & 0xFF) << 32
+ | ((long) in[offset++] & 0xFF) << 24
+ | ((long) in[offset++] & 0xFF) << 16
+ | ((long) in[offset++] & 0xFF) << 8
+ | ((long) in[offset++] & 0xFF);
+ }
+ for (r = 16; r < 80; r++)
+ {
+ T = w[r - 2];
+ T2 = w[r - 15];
+ w[r] = (((T >>> 19) | (T << 45)) ^ ((T >>> 61) | (T << 3)) ^ (T >>> 6))
+ + w[r - 7]
+ + (((T2 >>> 1) | (T2 << 63)) ^ ((T2 >>> 8) | (T2 << 56)) ^ (T2 >>> 7))
+ + w[r - 16];
+ }
+
+ for (r = 0; r < 80; r++)
+ {
+ T = H
+ + (((E >>> 14) | (E << 50)) ^ ((E >>> 18) | (E << 46)) ^ ((E >>> 41) | (E << 23)))
+ + ((E & F) ^ ((~E) & G)) + k[r] + w[r];
+ T2 = (((A >>> 28) | (A << 36)) ^ ((A >>> 34) | (A << 30)) ^ ((A >>> 39) | (A << 25)))
+ + ((A & B) ^ (A & C) ^ (B & C));
+ H = G;
+ G = F;
+ F = E;
+ E = D + T;
+ D = C;
+ C = B;
+ B = A;
+ A = T + T2;
+ }
+
+ return new long[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E, hh5 + F,
+ hh6 + G, hh7 + H };
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/Tiger.java b/libjava/classpath/gnu/java/security/hash/Tiger.java
new file mode 100644
index 00000000000..f39fed30d62
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/Tiger.java
@@ -0,0 +1,943 @@
+/* Tiger.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * The Tiger message digest. Tiger was designed by Ross Anderson and Eli
+ * Biham, with the goal of producing a secure, fast hash function that
+ * performs especially well on next-generation 64-bit architectures, but
+ * is still efficient on 32- and 16-bit architectures.
+ *
+ * <p>Tiger processes data in 512-bit blocks and produces a 192-bit
+ * digest.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a
+ * href="http://www.cs.technion.ac.il/~biham/Reports/Tiger/">Tiger: A
+ * Fast New Hash Function</a>, Ross Anderson and Eli Biham.</a></li>
+ * </ol>
+ */
+public class Tiger extends BaseHash
+{
+
+ // Constants and variables.
+ // -----------------------------------------------------------------------
+
+ private static final int HASH_SIZE = 24;
+
+ private static final int BLOCK_SIZE = 64;
+
+ /** Result when no data has been input. */
+ private static final String DIGEST0 = "3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3";
+
+ private static final long A = 0x0123456789ABCDEFL;
+
+ private static final long B = 0xFEDCBA9876543210L;
+
+ private static final long C = 0xF096A5B4C3B2E187L;
+
+ /** S-Box T1. */
+ private static final long[] T1 = { 0x02AAB17CF7E90C5EL, 0xAC424B03E243A8ECL,
+ 0x72CD5BE30DD5FCD3L, 0x6D019B93F6F97F3AL,
+ 0xCD9978FFD21F9193L, 0x7573A1C9708029E2L,
+ 0xB164326B922A83C3L, 0x46883EEE04915870L,
+ 0xEAACE3057103ECE6L, 0xC54169B808A3535CL,
+ 0x4CE754918DDEC47CL, 0x0AA2F4DFDC0DF40CL,
+ 0x10B76F18A74DBEFAL, 0xC6CCB6235AD1AB6AL,
+ 0x13726121572FE2FFL, 0x1A488C6F199D921EL,
+ 0x4BC9F9F4DA0007CAL, 0x26F5E6F6E85241C7L,
+ 0x859079DBEA5947B6L, 0x4F1885C5C99E8C92L,
+ 0xD78E761EA96F864BL, 0x8E36428C52B5C17DL,
+ 0x69CF6827373063C1L, 0xB607C93D9BB4C56EL,
+ 0x7D820E760E76B5EAL, 0x645C9CC6F07FDC42L,
+ 0xBF38A078243342E0L, 0x5F6B343C9D2E7D04L,
+ 0xF2C28AEB600B0EC6L, 0x6C0ED85F7254BCACL,
+ 0x71592281A4DB4FE5L, 0x1967FA69CE0FED9FL,
+ 0xFD5293F8B96545DBL, 0xC879E9D7F2A7600BL,
+ 0x860248920193194EL, 0xA4F9533B2D9CC0B3L,
+ 0x9053836C15957613L, 0xDB6DCF8AFC357BF1L,
+ 0x18BEEA7A7A370F57L, 0x037117CA50B99066L,
+ 0x6AB30A9774424A35L, 0xF4E92F02E325249BL,
+ 0x7739DB07061CCAE1L, 0xD8F3B49CECA42A05L,
+ 0xBD56BE3F51382F73L, 0x45FAED5843B0BB28L,
+ 0x1C813D5C11BF1F83L, 0x8AF0E4B6D75FA169L,
+ 0x33EE18A487AD9999L, 0x3C26E8EAB1C94410L,
+ 0xB510102BC0A822F9L, 0x141EEF310CE6123BL,
+ 0xFC65B90059DDB154L, 0xE0158640C5E0E607L,
+ 0x884E079826C3A3CFL, 0x930D0D9523C535FDL,
+ 0x35638D754E9A2B00L, 0x4085FCCF40469DD5L,
+ 0xC4B17AD28BE23A4CL, 0xCAB2F0FC6A3E6A2EL,
+ 0x2860971A6B943FCDL, 0x3DDE6EE212E30446L,
+ 0x6222F32AE01765AEL, 0x5D550BB5478308FEL,
+ 0xA9EFA98DA0EDA22AL, 0xC351A71686C40DA7L,
+ 0x1105586D9C867C84L, 0xDCFFEE85FDA22853L,
+ 0xCCFBD0262C5EEF76L, 0xBAF294CB8990D201L,
+ 0xE69464F52AFAD975L, 0x94B013AFDF133E14L,
+ 0x06A7D1A32823C958L, 0x6F95FE5130F61119L,
+ 0xD92AB34E462C06C0L, 0xED7BDE33887C71D2L,
+ 0x79746D6E6518393EL, 0x5BA419385D713329L,
+ 0x7C1BA6B948A97564L, 0x31987C197BFDAC67L,
+ 0xDE6C23C44B053D02L, 0x581C49FED002D64DL,
+ 0xDD474D6338261571L, 0xAA4546C3E473D062L,
+ 0x928FCE349455F860L, 0x48161BBACAAB94D9L,
+ 0x63912430770E6F68L, 0x6EC8A5E602C6641CL,
+ 0x87282515337DDD2BL, 0x2CDA6B42034B701BL,
+ 0xB03D37C181CB096DL, 0xE108438266C71C6FL,
+ 0x2B3180C7EB51B255L, 0xDF92B82F96C08BBCL,
+ 0x5C68C8C0A632F3BAL, 0x5504CC861C3D0556L,
+ 0xABBFA4E55FB26B8FL, 0x41848B0AB3BACEB4L,
+ 0xB334A273AA445D32L, 0xBCA696F0A85AD881L,
+ 0x24F6EC65B528D56CL, 0x0CE1512E90F4524AL,
+ 0x4E9DD79D5506D35AL, 0x258905FAC6CE9779L,
+ 0x2019295B3E109B33L, 0xF8A9478B73A054CCL,
+ 0x2924F2F934417EB0L, 0x3993357D536D1BC4L,
+ 0x38A81AC21DB6FF8BL, 0x47C4FBF17D6016BFL,
+ 0x1E0FAADD7667E3F5L, 0x7ABCFF62938BEB96L,
+ 0xA78DAD948FC179C9L, 0x8F1F98B72911E50DL,
+ 0x61E48EAE27121A91L, 0x4D62F7AD31859808L,
+ 0xECEBA345EF5CEAEBL, 0xF5CEB25EBC9684CEL,
+ 0xF633E20CB7F76221L, 0xA32CDF06AB8293E4L,
+ 0x985A202CA5EE2CA4L, 0xCF0B8447CC8A8FB1L,
+ 0x9F765244979859A3L, 0xA8D516B1A1240017L,
+ 0x0BD7BA3EBB5DC726L, 0xE54BCA55B86ADB39L,
+ 0x1D7A3AFD6C478063L, 0x519EC608E7669EDDL,
+ 0x0E5715A2D149AA23L, 0x177D4571848FF194L,
+ 0xEEB55F3241014C22L, 0x0F5E5CA13A6E2EC2L,
+ 0x8029927B75F5C361L, 0xAD139FABC3D6E436L,
+ 0x0D5DF1A94CCF402FL, 0x3E8BD948BEA5DFC8L,
+ 0xA5A0D357BD3FF77EL, 0xA2D12E251F74F645L,
+ 0x66FD9E525E81A082L, 0x2E0C90CE7F687A49L,
+ 0xC2E8BCBEBA973BC5L, 0x000001BCE509745FL,
+ 0x423777BBE6DAB3D6L, 0xD1661C7EAEF06EB5L,
+ 0xA1781F354DAACFD8L, 0x2D11284A2B16AFFCL,
+ 0xF1FC4F67FA891D1FL, 0x73ECC25DCB920ADAL,
+ 0xAE610C22C2A12651L, 0x96E0A810D356B78AL,
+ 0x5A9A381F2FE7870FL, 0xD5AD62EDE94E5530L,
+ 0xD225E5E8368D1427L, 0x65977B70C7AF4631L,
+ 0x99F889B2DE39D74FL, 0x233F30BF54E1D143L,
+ 0x9A9675D3D9A63C97L, 0x5470554FF334F9A8L,
+ 0x166ACB744A4F5688L, 0x70C74CAAB2E4AEADL,
+ 0xF0D091646F294D12L, 0x57B82A89684031D1L,
+ 0xEFD95A5A61BE0B6BL, 0x2FBD12E969F2F29AL,
+ 0x9BD37013FEFF9FE8L, 0x3F9B0404D6085A06L,
+ 0x4940C1F3166CFE15L, 0x09542C4DCDF3DEFBL,
+ 0xB4C5218385CD5CE3L, 0xC935B7DC4462A641L,
+ 0x3417F8A68ED3B63FL, 0xB80959295B215B40L,
+ 0xF99CDAEF3B8C8572L, 0x018C0614F8FCB95DL,
+ 0x1B14ACCD1A3ACDF3L, 0x84D471F200BB732DL,
+ 0xC1A3110E95E8DA16L, 0x430A7220BF1A82B8L,
+ 0xB77E090D39DF210EL, 0x5EF4BD9F3CD05E9DL,
+ 0x9D4FF6DA7E57A444L, 0xDA1D60E183D4A5F8L,
+ 0xB287C38417998E47L, 0xFE3EDC121BB31886L,
+ 0xC7FE3CCC980CCBEFL, 0xE46FB590189BFD03L,
+ 0x3732FD469A4C57DCL, 0x7EF700A07CF1AD65L,
+ 0x59C64468A31D8859L, 0x762FB0B4D45B61F6L,
+ 0x155BAED099047718L, 0x68755E4C3D50BAA6L,
+ 0xE9214E7F22D8B4DFL, 0x2ADDBF532EAC95F4L,
+ 0x32AE3909B4BD0109L, 0x834DF537B08E3450L,
+ 0xFA209DA84220728DL, 0x9E691D9B9EFE23F7L,
+ 0x0446D288C4AE8D7FL, 0x7B4CC524E169785BL,
+ 0x21D87F0135CA1385L, 0xCEBB400F137B8AA5L,
+ 0x272E2B66580796BEL, 0x3612264125C2B0DEL,
+ 0x057702BDAD1EFBB2L, 0xD4BABB8EACF84BE9L,
+ 0x91583139641BC67BL, 0x8BDC2DE08036E024L,
+ 0x603C8156F49F68EDL, 0xF7D236F7DBEF5111L,
+ 0x9727C4598AD21E80L, 0xA08A0896670A5FD7L,
+ 0xCB4A8F4309EBA9CBL, 0x81AF564B0F7036A1L,
+ 0xC0B99AA778199ABDL, 0x959F1EC83FC8E952L,
+ 0x8C505077794A81B9L, 0x3ACAAF8F056338F0L,
+ 0x07B43F50627A6778L, 0x4A44AB49F5ECCC77L,
+ 0x3BC3D6E4B679EE98L, 0x9CC0D4D1CF14108CL,
+ 0x4406C00B206BC8A0L, 0x82A18854C8D72D89L,
+ 0x67E366B35C3C432CL, 0xB923DD61102B37F2L,
+ 0x56AB2779D884271DL, 0xBE83E1B0FF1525AFL,
+ 0xFB7C65D4217E49A9L, 0x6BDBE0E76D48E7D4L,
+ 0x08DF828745D9179EL, 0x22EA6A9ADD53BD34L,
+ 0xE36E141C5622200AL, 0x7F805D1B8CB750EEL,
+ 0xAFE5C7A59F58E837L, 0xE27F996A4FB1C23CL,
+ 0xD3867DFB0775F0D0L, 0xD0E673DE6E88891AL,
+ 0x123AEB9EAFB86C25L, 0x30F1D5D5C145B895L,
+ 0xBB434A2DEE7269E7L, 0x78CB67ECF931FA38L,
+ 0xF33B0372323BBF9CL, 0x52D66336FB279C74L,
+ 0x505F33AC0AFB4EAAL, 0xE8A5CD99A2CCE187L,
+ 0x534974801E2D30BBL, 0x8D2D5711D5876D90L,
+ 0x1F1A412891BC038EL, 0xD6E2E71D82E56648L,
+ 0x74036C3A497732B7L, 0x89B67ED96361F5ABL,
+ 0xFFED95D8F1EA02A2L, 0xE72B3BD61464D43DL,
+ 0xA6300F170BDC4820L, 0xEBC18760ED78A77AL };
+
+ /** S-Box T2. */
+ private static final long[] T2 = { 0xE6A6BE5A05A12138L, 0xB5A122A5B4F87C98L,
+ 0x563C6089140B6990L, 0x4C46CB2E391F5DD5L,
+ 0xD932ADDBC9B79434L, 0x08EA70E42015AFF5L,
+ 0xD765A6673E478CF1L, 0xC4FB757EAB278D99L,
+ 0xDF11C6862D6E0692L, 0xDDEB84F10D7F3B16L,
+ 0x6F2EF604A665EA04L, 0x4A8E0F0FF0E0DFB3L,
+ 0xA5EDEEF83DBCBA51L, 0xFC4F0A2A0EA4371EL,
+ 0xE83E1DA85CB38429L, 0xDC8FF882BA1B1CE2L,
+ 0xCD45505E8353E80DL, 0x18D19A00D4DB0717L,
+ 0x34A0CFEDA5F38101L, 0x0BE77E518887CAF2L,
+ 0x1E341438B3C45136L, 0xE05797F49089CCF9L,
+ 0xFFD23F9DF2591D14L, 0x543DDA228595C5CDL,
+ 0x661F81FD99052A33L, 0x8736E641DB0F7B76L,
+ 0x15227725418E5307L, 0xE25F7F46162EB2FAL,
+ 0x48A8B2126C13D9FEL, 0xAFDC541792E76EEAL,
+ 0x03D912BFC6D1898FL, 0x31B1AAFA1B83F51BL,
+ 0xF1AC2796E42AB7D9L, 0x40A3A7D7FCD2EBACL,
+ 0x1056136D0AFBBCC5L, 0x7889E1DD9A6D0C85L,
+ 0xD33525782A7974AAL, 0xA7E25D09078AC09BL,
+ 0xBD4138B3EAC6EDD0L, 0x920ABFBE71EB9E70L,
+ 0xA2A5D0F54FC2625CL, 0xC054E36B0B1290A3L,
+ 0xF6DD59FF62FE932BL, 0x3537354511A8AC7DL,
+ 0xCA845E9172FADCD4L, 0x84F82B60329D20DCL,
+ 0x79C62CE1CD672F18L, 0x8B09A2ADD124642CL,
+ 0xD0C1E96A19D9E726L, 0x5A786A9B4BA9500CL,
+ 0x0E020336634C43F3L, 0xC17B474AEB66D822L,
+ 0x6A731AE3EC9BAAC2L, 0x8226667AE0840258L,
+ 0x67D4567691CAECA5L, 0x1D94155C4875ADB5L,
+ 0x6D00FD985B813FDFL, 0x51286EFCB774CD06L,
+ 0x5E8834471FA744AFL, 0xF72CA0AEE761AE2EL,
+ 0xBE40E4CDAEE8E09AL, 0xE9970BBB5118F665L,
+ 0x726E4BEB33DF1964L, 0x703B000729199762L,
+ 0x4631D816F5EF30A7L, 0xB880B5B51504A6BEL,
+ 0x641793C37ED84B6CL, 0x7B21ED77F6E97D96L,
+ 0x776306312EF96B73L, 0xAE528948E86FF3F4L,
+ 0x53DBD7F286A3F8F8L, 0x16CADCE74CFC1063L,
+ 0x005C19BDFA52C6DDL, 0x68868F5D64D46AD3L,
+ 0x3A9D512CCF1E186AL, 0x367E62C2385660AEL,
+ 0xE359E7EA77DCB1D7L, 0x526C0773749ABE6EL,
+ 0x735AE5F9D09F734BL, 0x493FC7CC8A558BA8L,
+ 0xB0B9C1533041AB45L, 0x321958BA470A59BDL,
+ 0x852DB00B5F46C393L, 0x91209B2BD336B0E5L,
+ 0x6E604F7D659EF19FL, 0xB99A8AE2782CCB24L,
+ 0xCCF52AB6C814C4C7L, 0x4727D9AFBE11727BL,
+ 0x7E950D0C0121B34DL, 0x756F435670AD471FL,
+ 0xF5ADD442615A6849L, 0x4E87E09980B9957AL,
+ 0x2ACFA1DF50AEE355L, 0xD898263AFD2FD556L,
+ 0xC8F4924DD80C8FD6L, 0xCF99CA3D754A173AL,
+ 0xFE477BACAF91BF3CL, 0xED5371F6D690C12DL,
+ 0x831A5C285E687094L, 0xC5D3C90A3708A0A4L,
+ 0x0F7F903717D06580L, 0x19F9BB13B8FDF27FL,
+ 0xB1BD6F1B4D502843L, 0x1C761BA38FFF4012L,
+ 0x0D1530C4E2E21F3BL, 0x8943CE69A7372C8AL,
+ 0xE5184E11FEB5CE66L, 0x618BDB80BD736621L,
+ 0x7D29BAD68B574D0BL, 0x81BB613E25E6FE5BL,
+ 0x071C9C10BC07913FL, 0xC7BEEB7909AC2D97L,
+ 0xC3E58D353BC5D757L, 0xEB017892F38F61E8L,
+ 0xD4EFFB9C9B1CC21AL, 0x99727D26F494F7ABL,
+ 0xA3E063A2956B3E03L, 0x9D4A8B9A4AA09C30L,
+ 0x3F6AB7D500090FB4L, 0x9CC0F2A057268AC0L,
+ 0x3DEE9D2DEDBF42D1L, 0x330F49C87960A972L,
+ 0xC6B2720287421B41L, 0x0AC59EC07C00369CL,
+ 0xEF4EAC49CB353425L, 0xF450244EEF0129D8L,
+ 0x8ACC46E5CAF4DEB6L, 0x2FFEAB63989263F7L,
+ 0x8F7CB9FE5D7A4578L, 0x5BD8F7644E634635L,
+ 0x427A7315BF2DC900L, 0x17D0C4AA2125261CL,
+ 0x3992486C93518E50L, 0xB4CBFEE0A2D7D4C3L,
+ 0x7C75D6202C5DDD8DL, 0xDBC295D8E35B6C61L,
+ 0x60B369D302032B19L, 0xCE42685FDCE44132L,
+ 0x06F3DDB9DDF65610L, 0x8EA4D21DB5E148F0L,
+ 0x20B0FCE62FCD496FL, 0x2C1B912358B0EE31L,
+ 0xB28317B818F5A308L, 0xA89C1E189CA6D2CFL,
+ 0x0C6B18576AAADBC8L, 0xB65DEAA91299FAE3L,
+ 0xFB2B794B7F1027E7L, 0x04E4317F443B5BEBL,
+ 0x4B852D325939D0A6L, 0xD5AE6BEEFB207FFCL,
+ 0x309682B281C7D374L, 0xBAE309A194C3B475L,
+ 0x8CC3F97B13B49F05L, 0x98A9422FF8293967L,
+ 0x244B16B01076FF7CL, 0xF8BF571C663D67EEL,
+ 0x1F0D6758EEE30DA1L, 0xC9B611D97ADEB9B7L,
+ 0xB7AFD5887B6C57A2L, 0x6290AE846B984FE1L,
+ 0x94DF4CDEACC1A5FDL, 0x058A5BD1C5483AFFL,
+ 0x63166CC142BA3C37L, 0x8DB8526EB2F76F40L,
+ 0xE10880036F0D6D4EL, 0x9E0523C9971D311DL,
+ 0x45EC2824CC7CD691L, 0x575B8359E62382C9L,
+ 0xFA9E400DC4889995L, 0xD1823ECB45721568L,
+ 0xDAFD983B8206082FL, 0xAA7D29082386A8CBL,
+ 0x269FCD4403B87588L, 0x1B91F5F728BDD1E0L,
+ 0xE4669F39040201F6L, 0x7A1D7C218CF04ADEL,
+ 0x65623C29D79CE5CEL, 0x2368449096C00BB1L,
+ 0xAB9BF1879DA503BAL, 0xBC23ECB1A458058EL,
+ 0x9A58DF01BB401ECCL, 0xA070E868A85F143DL,
+ 0x4FF188307DF2239EL, 0x14D565B41A641183L,
+ 0xEE13337452701602L, 0x950E3DCF3F285E09L,
+ 0x59930254B9C80953L, 0x3BF299408930DA6DL,
+ 0xA955943F53691387L, 0xA15EDECAA9CB8784L,
+ 0x29142127352BE9A0L, 0x76F0371FFF4E7AFBL,
+ 0x0239F450274F2228L, 0xBB073AF01D5E868BL,
+ 0xBFC80571C10E96C1L, 0xD267088568222E23L,
+ 0x9671A3D48E80B5B0L, 0x55B5D38AE193BB81L,
+ 0x693AE2D0A18B04B8L, 0x5C48B4ECADD5335FL,
+ 0xFD743B194916A1CAL, 0x2577018134BE98C4L,
+ 0xE77987E83C54A4ADL, 0x28E11014DA33E1B9L,
+ 0x270CC59E226AA213L, 0x71495F756D1A5F60L,
+ 0x9BE853FB60AFEF77L, 0xADC786A7F7443DBFL,
+ 0x0904456173B29A82L, 0x58BC7A66C232BD5EL,
+ 0xF306558C673AC8B2L, 0x41F639C6B6C9772AL,
+ 0x216DEFE99FDA35DAL, 0x11640CC71C7BE615L,
+ 0x93C43694565C5527L, 0xEA038E6246777839L,
+ 0xF9ABF3CE5A3E2469L, 0x741E768D0FD312D2L,
+ 0x0144B883CED652C6L, 0xC20B5A5BA33F8552L,
+ 0x1AE69633C3435A9DL, 0x97A28CA4088CFDECL,
+ 0x8824A43C1E96F420L, 0x37612FA66EEEA746L,
+ 0x6B4CB165F9CF0E5AL, 0x43AA1C06A0ABFB4AL,
+ 0x7F4DC26FF162796BL, 0x6CBACC8E54ED9B0FL,
+ 0xA6B7FFEFD2BB253EL, 0x2E25BC95B0A29D4FL,
+ 0x86D6A58BDEF1388CL, 0xDED74AC576B6F054L,
+ 0x8030BDBC2B45805DL, 0x3C81AF70E94D9289L,
+ 0x3EFF6DDA9E3100DBL, 0xB38DC39FDFCC8847L,
+ 0x123885528D17B87EL, 0xF2DA0ED240B1B642L,
+ 0x44CEFADCD54BF9A9L, 0x1312200E433C7EE6L,
+ 0x9FFCC84F3A78C748L, 0xF0CD1F72248576BBL,
+ 0xEC6974053638CFE4L, 0x2BA7B67C0CEC4E4CL,
+ 0xAC2F4DF3E5CE32EDL, 0xCB33D14326EA4C11L,
+ 0xA4E9044CC77E58BCL, 0x5F513293D934FCEFL,
+ 0x5DC9645506E55444L, 0x50DE418F317DE40AL,
+ 0x388CB31A69DDE259L, 0x2DB4A83455820A86L,
+ 0x9010A91E84711AE9L, 0x4DF7F0B7B1498371L,
+ 0xD62A2EABC0977179L, 0x22FAC097AA8D5C0EL };
+
+ /** S-Box T3. */
+ private static final long[] T3 = { 0xF49FCC2FF1DAF39BL, 0x487FD5C66FF29281L,
+ 0xE8A30667FCDCA83FL, 0x2C9B4BE3D2FCCE63L,
+ 0xDA3FF74B93FBBBC2L, 0x2FA165D2FE70BA66L,
+ 0xA103E279970E93D4L, 0xBECDEC77B0E45E71L,
+ 0xCFB41E723985E497L, 0xB70AAA025EF75017L,
+ 0xD42309F03840B8E0L, 0x8EFC1AD035898579L,
+ 0x96C6920BE2B2ABC5L, 0x66AF4163375A9172L,
+ 0x2174ABDCCA7127FBL, 0xB33CCEA64A72FF41L,
+ 0xF04A4933083066A5L, 0x8D970ACDD7289AF5L,
+ 0x8F96E8E031C8C25EL, 0xF3FEC02276875D47L,
+ 0xEC7BF310056190DDL, 0xF5ADB0AEBB0F1491L,
+ 0x9B50F8850FD58892L, 0x4975488358B74DE8L,
+ 0xA3354FF691531C61L, 0x0702BBE481D2C6EEL,
+ 0x89FB24057DEDED98L, 0xAC3075138596E902L,
+ 0x1D2D3580172772EDL, 0xEB738FC28E6BC30DL,
+ 0x5854EF8F63044326L, 0x9E5C52325ADD3BBEL,
+ 0x90AA53CF325C4623L, 0xC1D24D51349DD067L,
+ 0x2051CFEEA69EA624L, 0x13220F0A862E7E4FL,
+ 0xCE39399404E04864L, 0xD9C42CA47086FCB7L,
+ 0x685AD2238A03E7CCL, 0x066484B2AB2FF1DBL,
+ 0xFE9D5D70EFBF79ECL, 0x5B13B9DD9C481854L,
+ 0x15F0D475ED1509ADL, 0x0BEBCD060EC79851L,
+ 0xD58C6791183AB7F8L, 0xD1187C5052F3EEE4L,
+ 0xC95D1192E54E82FFL, 0x86EEA14CB9AC6CA2L,
+ 0x3485BEB153677D5DL, 0xDD191D781F8C492AL,
+ 0xF60866BAA784EBF9L, 0x518F643BA2D08C74L,
+ 0x8852E956E1087C22L, 0xA768CB8DC410AE8DL,
+ 0x38047726BFEC8E1AL, 0xA67738B4CD3B45AAL,
+ 0xAD16691CEC0DDE19L, 0xC6D4319380462E07L,
+ 0xC5A5876D0BA61938L, 0x16B9FA1FA58FD840L,
+ 0x188AB1173CA74F18L, 0xABDA2F98C99C021FL,
+ 0x3E0580AB134AE816L, 0x5F3B05B773645ABBL,
+ 0x2501A2BE5575F2F6L, 0x1B2F74004E7E8BA9L,
+ 0x1CD7580371E8D953L, 0x7F6ED89562764E30L,
+ 0xB15926FF596F003DL, 0x9F65293DA8C5D6B9L,
+ 0x6ECEF04DD690F84CL, 0x4782275FFF33AF88L,
+ 0xE41433083F820801L, 0xFD0DFE409A1AF9B5L,
+ 0x4325A3342CDB396BL, 0x8AE77E62B301B252L,
+ 0xC36F9E9F6655615AL, 0x85455A2D92D32C09L,
+ 0xF2C7DEA949477485L, 0x63CFB4C133A39EBAL,
+ 0x83B040CC6EBC5462L, 0x3B9454C8FDB326B0L,
+ 0x56F56A9E87FFD78CL, 0x2DC2940D99F42BC6L,
+ 0x98F7DF096B096E2DL, 0x19A6E01E3AD852BFL,
+ 0x42A99CCBDBD4B40BL, 0xA59998AF45E9C559L,
+ 0x366295E807D93186L, 0x6B48181BFAA1F773L,
+ 0x1FEC57E2157A0A1DL, 0x4667446AF6201AD5L,
+ 0xE615EBCACFB0F075L, 0xB8F31F4F68290778L,
+ 0x22713ED6CE22D11EL, 0x3057C1A72EC3C93BL,
+ 0xCB46ACC37C3F1F2FL, 0xDBB893FD02AAF50EL,
+ 0x331FD92E600B9FCFL, 0xA498F96148EA3AD6L,
+ 0xA8D8426E8B6A83EAL, 0xA089B274B7735CDCL,
+ 0x87F6B3731E524A11L, 0x118808E5CBC96749L,
+ 0x9906E4C7B19BD394L, 0xAFED7F7E9B24A20CL,
+ 0x6509EADEEB3644A7L, 0x6C1EF1D3E8EF0EDEL,
+ 0xB9C97D43E9798FB4L, 0xA2F2D784740C28A3L,
+ 0x7B8496476197566FL, 0x7A5BE3E6B65F069DL,
+ 0xF96330ED78BE6F10L, 0xEEE60DE77A076A15L,
+ 0x2B4BEE4AA08B9BD0L, 0x6A56A63EC7B8894EL,
+ 0x02121359BA34FEF4L, 0x4CBF99F8283703FCL,
+ 0x398071350CAF30C8L, 0xD0A77A89F017687AL,
+ 0xF1C1A9EB9E423569L, 0x8C7976282DEE8199L,
+ 0x5D1737A5DD1F7ABDL, 0x4F53433C09A9FA80L,
+ 0xFA8B0C53DF7CA1D9L, 0x3FD9DCBC886CCB77L,
+ 0xC040917CA91B4720L, 0x7DD00142F9D1DCDFL,
+ 0x8476FC1D4F387B58L, 0x23F8E7C5F3316503L,
+ 0x032A2244E7E37339L, 0x5C87A5D750F5A74BL,
+ 0x082B4CC43698992EL, 0xDF917BECB858F63CL,
+ 0x3270B8FC5BF86DDAL, 0x10AE72BB29B5DD76L,
+ 0x576AC94E7700362BL, 0x1AD112DAC61EFB8FL,
+ 0x691BC30EC5FAA427L, 0xFF246311CC327143L,
+ 0x3142368E30E53206L, 0x71380E31E02CA396L,
+ 0x958D5C960AAD76F1L, 0xF8D6F430C16DA536L,
+ 0xC8FFD13F1BE7E1D2L, 0x7578AE66004DDBE1L,
+ 0x05833F01067BE646L, 0xBB34B5AD3BFE586DL,
+ 0x095F34C9A12B97F0L, 0x247AB64525D60CA8L,
+ 0xDCDBC6F3017477D1L, 0x4A2E14D4DECAD24DL,
+ 0xBDB5E6D9BE0A1EEBL, 0x2A7E70F7794301ABL,
+ 0xDEF42D8A270540FDL, 0x01078EC0A34C22C1L,
+ 0xE5DE511AF4C16387L, 0x7EBB3A52BD9A330AL,
+ 0x77697857AA7D6435L, 0x004E831603AE4C32L,
+ 0xE7A21020AD78E312L, 0x9D41A70C6AB420F2L,
+ 0x28E06C18EA1141E6L, 0xD2B28CBD984F6B28L,
+ 0x26B75F6C446E9D83L, 0xBA47568C4D418D7FL,
+ 0xD80BADBFE6183D8EL, 0x0E206D7F5F166044L,
+ 0xE258A43911CBCA3EL, 0x723A1746B21DC0BCL,
+ 0xC7CAA854F5D7CDD3L, 0x7CAC32883D261D9CL,
+ 0x7690C26423BA942CL, 0x17E55524478042B8L,
+ 0xE0BE477656A2389FL, 0x4D289B5E67AB2DA0L,
+ 0x44862B9C8FBBFD31L, 0xB47CC8049D141365L,
+ 0x822C1B362B91C793L, 0x4EB14655FB13DFD8L,
+ 0x1ECBBA0714E2A97BL, 0x6143459D5CDE5F14L,
+ 0x53A8FBF1D5F0AC89L, 0x97EA04D81C5E5B00L,
+ 0x622181A8D4FDB3F3L, 0xE9BCD341572A1208L,
+ 0x1411258643CCE58AL, 0x9144C5FEA4C6E0A4L,
+ 0x0D33D06565CF620FL, 0x54A48D489F219CA1L,
+ 0xC43E5EAC6D63C821L, 0xA9728B3A72770DAFL,
+ 0xD7934E7B20DF87EFL, 0xE35503B61A3E86E5L,
+ 0xCAE321FBC819D504L, 0x129A50B3AC60BFA6L,
+ 0xCD5E68EA7E9FB6C3L, 0xB01C90199483B1C7L,
+ 0x3DE93CD5C295376CL, 0xAED52EDF2AB9AD13L,
+ 0x2E60F512C0A07884L, 0xBC3D86A3E36210C9L,
+ 0x35269D9B163951CEL, 0x0C7D6E2AD0CDB5FAL,
+ 0x59E86297D87F5733L, 0x298EF221898DB0E7L,
+ 0x55000029D1A5AA7EL, 0x8BC08AE1B5061B45L,
+ 0xC2C31C2B6C92703AL, 0x94CC596BAF25EF42L,
+ 0x0A1D73DB22540456L, 0x04B6A0F9D9C4179AL,
+ 0xEFFDAFA2AE3D3C60L, 0xF7C8075BB49496C4L,
+ 0x9CC5C7141D1CD4E3L, 0x78BD1638218E5534L,
+ 0xB2F11568F850246AL, 0xEDFABCFA9502BC29L,
+ 0x796CE5F2DA23051BL, 0xAAE128B0DC93537CL,
+ 0x3A493DA0EE4B29AEL, 0xB5DF6B2C416895D7L,
+ 0xFCABBD25122D7F37L, 0x70810B58105DC4B1L,
+ 0xE10FDD37F7882A90L, 0x524DCAB5518A3F5CL,
+ 0x3C9E85878451255BL, 0x4029828119BD34E2L,
+ 0x74A05B6F5D3CECCBL, 0xB610021542E13ECAL,
+ 0x0FF979D12F59E2ACL, 0x6037DA27E4F9CC50L,
+ 0x5E92975A0DF1847DL, 0xD66DE190D3E623FEL,
+ 0x5032D6B87B568048L, 0x9A36B7CE8235216EL,
+ 0x80272A7A24F64B4AL, 0x93EFED8B8C6916F7L,
+ 0x37DDBFF44CCE1555L, 0x4B95DB5D4B99BD25L,
+ 0x92D3FDA169812FC0L, 0xFB1A4A9A90660BB6L,
+ 0x730C196946A4B9B2L, 0x81E289AA7F49DA68L,
+ 0x64669A0F83B1A05FL, 0x27B3FF7D9644F48BL,
+ 0xCC6B615C8DB675B3L, 0x674F20B9BCEBBE95L,
+ 0x6F31238275655982L, 0x5AE488713E45CF05L,
+ 0xBF619F9954C21157L, 0xEABAC46040A8EAE9L,
+ 0x454C6FE9F2C0C1CDL, 0x419CF6496412691CL,
+ 0xD3DC3BEF265B0F70L, 0x6D0E60F5C3578A9EL };
+
+ /** S-Box T4. */
+ private static final long[] T4 = { 0x5B0E608526323C55L, 0x1A46C1A9FA1B59F5L,
+ 0xA9E245A17C4C8FFAL, 0x65CA5159DB2955D7L,
+ 0x05DB0A76CE35AFC2L, 0x81EAC77EA9113D45L,
+ 0x528EF88AB6AC0A0DL, 0xA09EA253597BE3FFL,
+ 0x430DDFB3AC48CD56L, 0xC4B3A67AF45CE46FL,
+ 0x4ECECFD8FBE2D05EL, 0x3EF56F10B39935F0L,
+ 0x0B22D6829CD619C6L, 0x17FD460A74DF2069L,
+ 0x6CF8CC8E8510ED40L, 0xD6C824BF3A6ECAA7L,
+ 0x61243D581A817049L, 0x048BACB6BBC163A2L,
+ 0xD9A38AC27D44CC32L, 0x7FDDFF5BAAF410ABL,
+ 0xAD6D495AA804824BL, 0xE1A6A74F2D8C9F94L,
+ 0xD4F7851235DEE8E3L, 0xFD4B7F886540D893L,
+ 0x247C20042AA4BFDAL, 0x096EA1C517D1327CL,
+ 0xD56966B4361A6685L, 0x277DA5C31221057DL,
+ 0x94D59893A43ACFF7L, 0x64F0C51CCDC02281L,
+ 0x3D33BCC4FF6189DBL, 0xE005CB184CE66AF1L,
+ 0xFF5CCD1D1DB99BEAL, 0xB0B854A7FE42980FL,
+ 0x7BD46A6A718D4B9FL, 0xD10FA8CC22A5FD8CL,
+ 0xD31484952BE4BD31L, 0xC7FA975FCB243847L,
+ 0x4886ED1E5846C407L, 0x28CDDB791EB70B04L,
+ 0xC2B00BE2F573417FL, 0x5C9590452180F877L,
+ 0x7A6BDDFFF370EB00L, 0xCE509E38D6D9D6A4L,
+ 0xEBEB0F00647FA702L, 0x1DCC06CF76606F06L,
+ 0xE4D9F28BA286FF0AL, 0xD85A305DC918C262L,
+ 0x475B1D8732225F54L, 0x2D4FB51668CCB5FEL,
+ 0xA679B9D9D72BBA20L, 0x53841C0D912D43A5L,
+ 0x3B7EAA48BF12A4E8L, 0x781E0E47F22F1DDFL,
+ 0xEFF20CE60AB50973L, 0x20D261D19DFFB742L,
+ 0x16A12B03062A2E39L, 0x1960EB2239650495L,
+ 0x251C16FED50EB8B8L, 0x9AC0C330F826016EL,
+ 0xED152665953E7671L, 0x02D63194A6369570L,
+ 0x5074F08394B1C987L, 0x70BA598C90B25CE1L,
+ 0x794A15810B9742F6L, 0x0D5925E9FCAF8C6CL,
+ 0x3067716CD868744EL, 0x910AB077E8D7731BL,
+ 0x6A61BBDB5AC42F61L, 0x93513EFBF0851567L,
+ 0xF494724B9E83E9D5L, 0xE887E1985C09648DL,
+ 0x34B1D3C675370CFDL, 0xDC35E433BC0D255DL,
+ 0xD0AAB84234131BE0L, 0x08042A50B48B7EAFL,
+ 0x9997C4EE44A3AB35L, 0x829A7B49201799D0L,
+ 0x263B8307B7C54441L, 0x752F95F4FD6A6CA6L,
+ 0x927217402C08C6E5L, 0x2A8AB754A795D9EEL,
+ 0xA442F7552F72943DL, 0x2C31334E19781208L,
+ 0x4FA98D7CEAEE6291L, 0x55C3862F665DB309L,
+ 0xBD0610175D53B1F3L, 0x46FE6CB840413F27L,
+ 0x3FE03792DF0CFA59L, 0xCFE700372EB85E8FL,
+ 0xA7BE29E7ADBCE118L, 0xE544EE5CDE8431DDL,
+ 0x8A781B1B41F1873EL, 0xA5C94C78A0D2F0E7L,
+ 0x39412E2877B60728L, 0xA1265EF3AFC9A62CL,
+ 0xBCC2770C6A2506C5L, 0x3AB66DD5DCE1CE12L,
+ 0xE65499D04A675B37L, 0x7D8F523481BFD216L,
+ 0x0F6F64FCEC15F389L, 0x74EFBE618B5B13C8L,
+ 0xACDC82B714273E1DL, 0xDD40BFE003199D17L,
+ 0x37E99257E7E061F8L, 0xFA52626904775AAAL,
+ 0x8BBBF63A463D56F9L, 0xF0013F1543A26E64L,
+ 0xA8307E9F879EC898L, 0xCC4C27A4150177CCL,
+ 0x1B432F2CCA1D3348L, 0xDE1D1F8F9F6FA013L,
+ 0x606602A047A7DDD6L, 0xD237AB64CC1CB2C7L,
+ 0x9B938E7225FCD1D3L, 0xEC4E03708E0FF476L,
+ 0xFEB2FBDA3D03C12DL, 0xAE0BCED2EE43889AL,
+ 0x22CB8923EBFB4F43L, 0x69360D013CF7396DL,
+ 0x855E3602D2D4E022L, 0x073805BAD01F784CL,
+ 0x33E17A133852F546L, 0xDF4874058AC7B638L,
+ 0xBA92B29C678AA14AL, 0x0CE89FC76CFAADCDL,
+ 0x5F9D4E0908339E34L, 0xF1AFE9291F5923B9L,
+ 0x6E3480F60F4A265FL, 0xEEBF3A2AB29B841CL,
+ 0xE21938A88F91B4ADL, 0x57DFEFF845C6D3C3L,
+ 0x2F006B0BF62CAAF2L, 0x62F479EF6F75EE78L,
+ 0x11A55AD41C8916A9L, 0xF229D29084FED453L,
+ 0x42F1C27B16B000E6L, 0x2B1F76749823C074L,
+ 0x4B76ECA3C2745360L, 0x8C98F463B91691BDL,
+ 0x14BCC93CF1ADE66AL, 0x8885213E6D458397L,
+ 0x8E177DF0274D4711L, 0xB49B73B5503F2951L,
+ 0x10168168C3F96B6BL, 0x0E3D963B63CAB0AEL,
+ 0x8DFC4B5655A1DB14L, 0xF789F1356E14DE5CL,
+ 0x683E68AF4E51DAC1L, 0xC9A84F9D8D4B0FD9L,
+ 0x3691E03F52A0F9D1L, 0x5ED86E46E1878E80L,
+ 0x3C711A0E99D07150L, 0x5A0865B20C4E9310L,
+ 0x56FBFC1FE4F0682EL, 0xEA8D5DE3105EDF9BL,
+ 0x71ABFDB12379187AL, 0x2EB99DE1BEE77B9CL,
+ 0x21ECC0EA33CF4523L, 0x59A4D7521805C7A1L,
+ 0x3896F5EB56AE7C72L, 0xAA638F3DB18F75DCL,
+ 0x9F39358DABE9808EL, 0xB7DEFA91C00B72ACL,
+ 0x6B5541FD62492D92L, 0x6DC6DEE8F92E4D5BL,
+ 0x353F57ABC4BEEA7EL, 0x735769D6DA5690CEL,
+ 0x0A234AA642391484L, 0xF6F9508028F80D9DL,
+ 0xB8E319A27AB3F215L, 0x31AD9C1151341A4DL,
+ 0x773C22A57BEF5805L, 0x45C7561A07968633L,
+ 0xF913DA9E249DBE36L, 0xDA652D9B78A64C68L,
+ 0x4C27A97F3BC334EFL, 0x76621220E66B17F4L,
+ 0x967743899ACD7D0BL, 0xF3EE5BCAE0ED6782L,
+ 0x409F753600C879FCL, 0x06D09A39B5926DB6L,
+ 0x6F83AEB0317AC588L, 0x01E6CA4A86381F21L,
+ 0x66FF3462D19F3025L, 0x72207C24DDFD3BFBL,
+ 0x4AF6B6D3E2ECE2EBL, 0x9C994DBEC7EA08DEL,
+ 0x49ACE597B09A8BC4L, 0xB38C4766CF0797BAL,
+ 0x131B9373C57C2A75L, 0xB1822CCE61931E58L,
+ 0x9D7555B909BA1C0CL, 0x127FAFDD937D11D2L,
+ 0x29DA3BADC66D92E4L, 0xA2C1D57154C2ECBCL,
+ 0x58C5134D82F6FE24L, 0x1C3AE3515B62274FL,
+ 0xE907C82E01CB8126L, 0xF8ED091913E37FCBL,
+ 0x3249D8F9C80046C9L, 0x80CF9BEDE388FB63L,
+ 0x1881539A116CF19EL, 0x5103F3F76BD52457L,
+ 0x15B7E6F5AE47F7A8L, 0xDBD7C6DED47E9CCFL,
+ 0x44E55C410228BB1AL, 0xB647D4255EDB4E99L,
+ 0x5D11882BB8AAFC30L, 0xF5098BBB29D3212AL,
+ 0x8FB5EA14E90296B3L, 0x677B942157DD025AL,
+ 0xFB58E7C0A390ACB5L, 0x89D3674C83BD4A01L,
+ 0x9E2DA4DF4BF3B93BL, 0xFCC41E328CAB4829L,
+ 0x03F38C96BA582C52L, 0xCAD1BDBD7FD85DB2L,
+ 0xBBB442C16082AE83L, 0xB95FE86BA5DA9AB0L,
+ 0xB22E04673771A93FL, 0x845358C9493152D8L,
+ 0xBE2A488697B4541EL, 0x95A2DC2DD38E6966L,
+ 0xC02C11AC923C852BL, 0x2388B1990DF2A87BL,
+ 0x7C8008FA1B4F37BEL, 0x1F70D0C84D54E503L,
+ 0x5490ADEC7ECE57D4L, 0x002B3C27D9063A3AL,
+ 0x7EAEA3848030A2BFL, 0xC602326DED2003C0L,
+ 0x83A7287D69A94086L, 0xC57A5FCB30F57A8AL,
+ 0xB56844E479EBE779L, 0xA373B40F05DCBCE9L,
+ 0xD71A786E88570EE2L, 0x879CBACDBDE8F6A0L,
+ 0x976AD1BCC164A32FL, 0xAB21E25E9666D78BL,
+ 0x901063AAE5E5C33CL, 0x9818B34448698D90L,
+ 0xE36487AE3E1E8ABBL, 0xAFBDF931893BDCB4L,
+ 0x6345A0DC5FBBD519L, 0x8628FE269B9465CAL,
+ 0x1E5D01603F9C51ECL, 0x4DE44006A15049B7L,
+ 0xBF6C70E5F776CBB1L, 0x411218F2EF552BEDL,
+ 0xCB0C0708705A36A3L, 0xE74D14754F986044L,
+ 0xCD56D9430EA8280EL, 0xC12591D7535F5065L,
+ 0xC83223F1720AEF96L, 0xC3A0396F7363A51FL };
+
+ // The cached self-test result.
+ private static Boolean valid;
+
+ // The context.
+ private long a, b, c;
+
+ // Constructors.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Trivial 0-arguments constructor.
+ */
+ public Tiger()
+ {
+ super(Registry.TIGER_HASH, HASH_SIZE, BLOCK_SIZE);
+ }
+
+ /**
+ * Private copying constructor for cloning.
+ *
+ * @param that The instance being cloned.
+ */
+ private Tiger(Tiger that)
+ {
+ this();
+ this.a = that.a;
+ this.b = that.b;
+ this.c = that.c;
+ this.count = that.count;
+ this.buffer = (that.buffer != null) ? (byte[]) that.buffer.clone() : null;
+ }
+
+ // Instance methods implementing BaseHash.
+ // -----------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new Tiger(this);
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(DIGEST0.equals(Util.toString(new Tiger().digest())));
+ }
+ return valid.booleanValue();
+ }
+
+ protected byte[] padBuffer()
+ {
+ int n = (int) (count % BLOCK_SIZE);
+ int padding = (n < 56) ? (56 - n) : (120 - n);
+ byte[] pad = new byte[padding + 8];
+
+ pad[0] = 1;
+ long bits = count << 3;
+
+ pad[padding++] = (byte) bits;
+ pad[padding++] = (byte) (bits >>> 8);
+ pad[padding++] = (byte) (bits >>> 16);
+ pad[padding++] = (byte) (bits >>> 24);
+ pad[padding++] = (byte) (bits >>> 32);
+ pad[padding++] = (byte) (bits >>> 40);
+ pad[padding++] = (byte) (bits >>> 48);
+ pad[padding] = (byte) (bits >>> 56);
+
+ return pad;
+ }
+
+ protected byte[] getResult()
+ {
+ return new byte[] { (byte) a, (byte) (a >>> 8), (byte) (a >>> 16),
+ (byte) (a >>> 24), (byte) (a >>> 32), (byte) (a >>> 40),
+ (byte) (a >>> 48), (byte) (a >>> 56), (byte) b,
+ (byte) (b >>> 8), (byte) (b >>> 16), (byte) (b >>> 24),
+ (byte) (b >>> 32), (byte) (b >>> 40), (byte) (b >>> 48),
+ (byte) (b >>> 56), (byte) c, (byte) (c >>> 8),
+ (byte) (c >>> 16), (byte) (c >>> 24), (byte) (c >>> 32),
+ (byte) (c >>> 40), (byte) (c >>> 48), (byte) (c >>> 56) };
+ }
+
+ protected void resetContext()
+ {
+ a = A;
+ b = B;
+ c = C;
+ }
+
+ protected void transform(byte[] in, int offset)
+ {
+ long x0, x1, x2, x3, x4, x5, x6, x7;
+
+ x0 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x1 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x2 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x3 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x4 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x5 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x6 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset++] & 0xFF) << 56);
+ x7 = ((long) in[offset++] & 0xFF) | ((long) (in[offset++] & 0xFF) << 8)
+ | ((long) (in[offset++] & 0xFF) << 16)
+ | ((long) (in[offset++] & 0xFF) << 24)
+ | ((long) (in[offset++] & 0xFF) << 32)
+ | ((long) (in[offset++] & 0xFF) << 40)
+ | ((long) (in[offset++] & 0xFF) << 48)
+ | ((long) (in[offset] & 0xFF) << 56);
+
+ // save_abc ::=
+ long aa = a, bb = b, cc = c;
+
+ // pass(aa, bb, cc, 5) ::=
+ cc ^= x0;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 5;
+ aa ^= x1;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 5;
+ bb ^= x2;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 5;
+ cc ^= x3;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 5;
+ aa ^= x4;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 5;
+ bb ^= x5;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 5;
+ cc ^= x6;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 5;
+ aa ^= x7;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 5;
+
+ // key_schedule ::=
+ x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5L;
+ x1 ^= x0;
+ x2 += x1;
+ x3 -= x2 ^ ((~x1) << 19);
+ x4 ^= x3;
+ x5 += x4;
+ x6 -= x5 ^ ((~x4) >>> 23);
+ x7 ^= x6;
+ x0 += x7;
+ x1 -= x0 ^ ((~x7) << 19);
+ x2 ^= x1;
+ x3 += x2;
+ x4 -= x3 ^ ((~x2) >>> 23);
+ x5 ^= x4;
+ x6 += x5;
+ x7 -= x6 ^ 0x0123456789ABCDEFL;
+
+ // pass(cc, aa, bb, 7) ::=
+ bb ^= x0;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 7;
+ cc ^= x1;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 7;
+ aa ^= x2;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 7;
+ bb ^= x3;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 7;
+ cc ^= x4;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 7;
+ aa ^= x5;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 7;
+ bb ^= x6;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 7;
+ cc ^= x7;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 7;
+
+ // key_schedule ::=
+ x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5L;
+ x1 ^= x0;
+ x2 += x1;
+ x3 -= x2 ^ ((~x1) << 19);
+ x4 ^= x3;
+ x5 += x4;
+ x6 -= x5 ^ ((~x4) >>> 23);
+ x7 ^= x6;
+ x0 += x7;
+ x1 -= x0 ^ ((~x7) << 19);
+ x2 ^= x1;
+ x3 += x2;
+ x4 -= x3 ^ ((~x2) >>> 23);
+ x5 ^= x4;
+ x6 += x5;
+ x7 -= x6 ^ 0x0123456789ABCDEFL;
+
+ // pass(bb,cc,aa,9) ::=
+ aa ^= x0;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 9;
+ bb ^= x1;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 9;
+ cc ^= x2;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 9;
+ aa ^= x3;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 9;
+ bb ^= x4;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 9;
+ cc ^= x5;
+ aa -= T1[(int) cc & 0xff] ^ T2[(int) (cc >> 16) & 0xff]
+ ^ T3[(int) (cc >> 32) & 0xff] ^ T4[(int) (cc >> 48) & 0xff];
+ bb += T4[(int) (cc >> 8) & 0xff] ^ T3[(int) (cc >> 24) & 0xff]
+ ^ T2[(int) (cc >> 40) & 0xff] ^ T1[(int) (cc >> 56) & 0xff];
+ bb *= 9;
+ aa ^= x6;
+ bb -= T1[(int) aa & 0xff] ^ T2[(int) (aa >> 16) & 0xff]
+ ^ T3[(int) (aa >> 32) & 0xff] ^ T4[(int) (aa >> 48) & 0xff];
+ cc += T4[(int) (aa >> 8) & 0xff] ^ T3[(int) (aa >> 24) & 0xff]
+ ^ T2[(int) (aa >> 40) & 0xff] ^ T1[(int) (aa >> 56) & 0xff];
+ cc *= 9;
+ bb ^= x7;
+ cc -= T1[(int) bb & 0xff] ^ T2[(int) (bb >> 16) & 0xff]
+ ^ T3[(int) (bb >> 32) & 0xff] ^ T4[(int) (bb >> 48) & 0xff];
+ aa += T4[(int) (bb >> 8) & 0xff] ^ T3[(int) (bb >> 24) & 0xff]
+ ^ T2[(int) (bb >> 40) & 0xff] ^ T1[(int) (bb >> 56) & 0xff];
+ aa *= 9;
+
+ // feedforward ::=
+ a ^= aa;
+ b = bb - b;
+ c += cc;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/hash/Whirlpool.java b/libjava/classpath/gnu/java/security/hash/Whirlpool.java
new file mode 100644
index 00000000000..8c5d9f360d0
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/hash/Whirlpool.java
@@ -0,0 +1,626 @@
+/* Whirlpool.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.hash;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+/**
+ * <p>Whirlpool, a new 512-bit hashing function operating on messages less than
+ * 2 ** 256 bits in length. The function structure is designed according to the
+ * Wide Trail strategy and permits a wide variety of implementation trade-offs.
+ * </p>
+ *
+ * <p><b>IMPORTANT</b>: This implementation is not thread-safe.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html">
+ * The WHIRLPOOL Hashing Function</a>.<br>
+ * <a href="mailto:paulo.barreto@terra.com.br">Paulo S.L.M. Barreto</a> and
+ * <a href="mailto:vincent.rijmen@esat.kuleuven.ac.be">Vincent Rijmen</a>.</li>
+ * </ol>
+ */
+public final class Whirlpool extends BaseHash
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 3;
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int BLOCK_SIZE = 64; // inner block size in bytes
+
+ /** The digest of the 0-bit long message. */
+ private static final String DIGEST0 = "470F0409ABAA446E49667D4EBE12A14387CEDBD10DD17B8243CAD550A089DC0F"
+ + "EEA7AA40F6C2AAAB71C6EBD076E43C7CFCA0AD32567897DCB5969861049A0F5A";
+
+ private static final int R = 10; // default number of rounds
+
+ private static final String Sd = // p. 19 [WHIRLPOOL]
+ "\u1823\uc6E8\u87B8\u014F\u36A6\ud2F5\u796F\u9152"
+ + "\u60Bc\u9B8E\uA30c\u7B35\u1dE0\ud7c2\u2E4B\uFE57"
+ + "\u1577\u37E5\u9FF0\u4AdA\u58c9\u290A\uB1A0\u6B85"
+ + "\uBd5d\u10F4\ucB3E\u0567\uE427\u418B\uA77d\u95d8"
+ + "\uFBEE\u7c66\udd17\u479E\ucA2d\uBF07\uAd5A\u8333"
+ + "\u6302\uAA71\uc819\u49d9\uF2E3\u5B88\u9A26\u32B0"
+ + "\uE90F\ud580\uBEcd\u3448\uFF7A\u905F\u2068\u1AAE"
+ + "\uB454\u9322\u64F1\u7312\u4008\uc3Ec\udBA1\u8d3d"
+ + "\u9700\ucF2B\u7682\ud61B\uB5AF\u6A50\u45F3\u30EF"
+ + "\u3F55\uA2EA\u65BA\u2Fc0\udE1c\uFd4d\u9275\u068A"
+ + "\uB2E6\u0E1F\u62d4\uA896\uF9c5\u2559\u8472\u394c"
+ + "\u5E78\u388c\ud1A5\uE261\uB321\u9c1E\u43c7\uFc04"
+ + "\u5199\u6d0d\uFAdF\u7E24\u3BAB\ucE11\u8F4E\uB7EB"
+ + "\u3c81\u94F7\uB913\u2cd3\uE76E\uc403\u5644\u7FA9"
+ + "\u2ABB\uc153\udc0B\u9d6c\u3174\uF646\uAc89\u14E1"
+ + "\u163A\u6909\u70B6\ud0Ed\ucc42\u98A4\u285c\uF886";
+
+ private static final long[] T0 = new long[256];
+
+ private static final long[] T1 = new long[256];
+
+ private static final long[] T2 = new long[256];
+
+ private static final long[] T3 = new long[256];
+
+ private static final long[] T4 = new long[256];
+
+ private static final long[] T5 = new long[256];
+
+ private static final long[] T6 = new long[256];
+
+ private static final long[] T7 = new long[256];
+
+ private static final long[] rc = new long[R];
+
+ /** caches the result of the correctness test, once executed. */
+ private static Boolean valid;
+
+ /** The 512-bit context as 8 longs. */
+ private long H0, H1, H2, H3, H4, H5, H6, H7;
+
+ /** Work area for computing the round key schedule. */
+ private long k00, k01, k02, k03, k04, k05, k06, k07;
+
+ private long Kr0, Kr1, Kr2, Kr3, Kr4, Kr5, Kr6, Kr7;
+
+ /** work area for transforming the 512-bit buffer. */
+ private long n0, n1, n2, n3, n4, n5, n6, n7;
+
+ private long nn0, nn1, nn2, nn3, nn4, nn5, nn6, nn7;
+
+ /** work area for holding block cipher's intermediate values. */
+ private long w0, w1, w2, w3, w4, w5, w6, w7;
+
+ // Static code - to intialise lookup tables --------------------------------
+
+ static
+ {
+ long time = System.currentTimeMillis();
+
+ int ROOT = 0x11d; // para. 2.1 [WHIRLPOOL]
+ int i, r, j;
+ long s, s2, s3, s4, s5, s8, s9, t;
+ char c;
+ final byte[] S = new byte[256];
+ for (i = 0; i < 256; i++)
+ {
+ c = Sd.charAt(i >>> 1);
+
+ s = ((i & 1) == 0 ? c >>> 8 : c) & 0xFFL;
+ s2 = s << 1;
+ if (s2 > 0xFFL)
+ {
+ s2 ^= ROOT;
+ }
+ s3 = s2 ^ s;
+ s4 = s2 << 1;
+ if (s4 > 0xFFL)
+ {
+ s4 ^= ROOT;
+ }
+ s5 = s4 ^ s;
+ s8 = s4 << 1;
+ if (s8 > 0xFFL)
+ {
+ s8 ^= ROOT;
+ }
+ s9 = s8 ^ s;
+
+ S[i] = (byte) s;
+ T0[i] = t = s << 56 | s << 48 | s3 << 40 | s << 32 | s5 << 24
+ | s8 << 16 | s9 << 8 | s5;
+ T1[i] = t >>> 8 | t << 56;
+ T2[i] = t >>> 16 | t << 48;
+ T3[i] = t >>> 24 | t << 40;
+ T4[i] = t >>> 32 | t << 32;
+ T5[i] = t >>> 40 | t << 24;
+ T6[i] = t >>> 48 | t << 16;
+ T7[i] = t >>> 56 | t << 8;
+ }
+
+ for (r = 1, i = 0, j = 0; r < R + 1; r++)
+ {
+ rc[i++] = (S[j++] & 0xFFL) << 56 | (S[j++] & 0xFFL) << 48
+ | (S[j++] & 0xFFL) << 40 | (S[j++] & 0xFFL) << 32
+ | (S[j++] & 0xFFL) << 24 | (S[j++] & 0xFFL) << 16
+ | (S[j++] & 0xFFL) << 8 | (S[j++] & 0xFFL);
+ }
+
+ time = System.currentTimeMillis() - time;
+
+ if (DEBUG && debuglevel > 8)
+ {
+ System.out.println("==========");
+ System.out.println();
+ System.out.println("Static data");
+ System.out.println();
+
+ System.out.println();
+ System.out.println("T0[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T0[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T1[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T1[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T2[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T2[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T3[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T3[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T4[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T4[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T5[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T5[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T6[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T5[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("T7[]:");
+ for (i = 0; i < 64; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ System.out.print("0x" + Util.toString(T5[i * 4 + j]) + ", ");
+ }
+ System.out.println();
+ }
+ System.out.println();
+ System.out.println("rc[]:");
+ for (i = 0; i < R; i++)
+ {
+ System.out.println("0x" + Util.toString(rc[i]));
+ }
+ System.out.println();
+
+ System.out.println();
+ System.out.println("Total initialization time: " + time + " ms.");
+ System.out.println();
+ }
+ }
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public Whirlpool()
+ {
+ super(Registry.WHIRLPOOL_HASH, 20, BLOCK_SIZE);
+ }
+
+ /**
+ * <p>Private constructor for cloning purposes.</p>
+ *
+ * @param md the instance to clone.
+ */
+ private Whirlpool(Whirlpool md)
+ {
+ this();
+
+ this.H0 = md.H0;
+ this.H1 = md.H1;
+ this.H2 = md.H2;
+ this.H3 = md.H3;
+ this.H4 = md.H4;
+ this.H5 = md.H5;
+ this.H6 = md.H6;
+ this.H7 = md.H7;
+ this.count = md.count;
+ this.buffer = (byte[]) md.buffer.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.lang.Cloneable interface implementation ----------------------------
+
+ public Object clone()
+ {
+ return (new Whirlpool(this));
+ }
+
+ // Implementation of concrete methods in BaseHash --------------------------
+
+ protected void transform(byte[] in, int offset)
+ {
+ // apply mu to the input
+ n0 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n1 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n2 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n3 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n4 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n5 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n6 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+ n7 = (in[offset++] & 0xFFL) << 56 | (in[offset++] & 0xFFL) << 48
+ | (in[offset++] & 0xFFL) << 40 | (in[offset++] & 0xFFL) << 32
+ | (in[offset++] & 0xFFL) << 24 | (in[offset++] & 0xFFL) << 16
+ | (in[offset++] & 0xFFL) << 8 | (in[offset++] & 0xFFL);
+
+ // transform K into the key schedule Kr; 0 <= r <= R
+ k00 = H0;
+ k01 = H1;
+ k02 = H2;
+ k03 = H3;
+ k04 = H4;
+ k05 = H5;
+ k06 = H6;
+ k07 = H7;
+
+ nn0 = n0 ^ k00;
+ nn1 = n1 ^ k01;
+ nn2 = n2 ^ k02;
+ nn3 = n3 ^ k03;
+ nn4 = n4 ^ k04;
+ nn5 = n5 ^ k05;
+ nn6 = n6 ^ k06;
+ nn7 = n7 ^ k07;
+
+ // intermediate cipher output
+ w0 = w1 = w2 = w3 = w4 = w5 = w6 = w7 = 0L;
+
+ for (int r = 0; r < R; r++)
+ {
+ // 1. compute intermediate round key schedule by applying ro[rc]
+ // to the previous round key schedule --rc being the round constant
+ Kr0 = T0[(int) ((k00 >> 56) & 0xFFL)] ^ T1[(int) ((k07 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k06 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k05 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k04 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k03 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k02 >> 8) & 0xFFL)] ^ T7[(int) (k01 & 0xFFL)]
+ ^ rc[r];
+
+ Kr1 = T0[(int) ((k01 >> 56) & 0xFFL)] ^ T1[(int) ((k00 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k07 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k06 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k05 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k04 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k03 >> 8) & 0xFFL)] ^ T7[(int) (k02 & 0xFFL)];
+
+ Kr2 = T0[(int) ((k02 >> 56) & 0xFFL)] ^ T1[(int) ((k01 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k00 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k07 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k06 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k05 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k04 >> 8) & 0xFFL)] ^ T7[(int) (k03 & 0xFFL)];
+
+ Kr3 = T0[(int) ((k03 >> 56) & 0xFFL)] ^ T1[(int) ((k02 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k01 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k00 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k07 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k06 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k05 >> 8) & 0xFFL)] ^ T7[(int) (k04 & 0xFFL)];
+
+ Kr4 = T0[(int) ((k04 >> 56) & 0xFFL)] ^ T1[(int) ((k03 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k02 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k01 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k00 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k07 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k06 >> 8) & 0xFFL)] ^ T7[(int) (k05 & 0xFFL)];
+
+ Kr5 = T0[(int) ((k05 >> 56) & 0xFFL)] ^ T1[(int) ((k04 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k03 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k02 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k01 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k00 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k07 >> 8) & 0xFFL)] ^ T7[(int) (k06 & 0xFFL)];
+
+ Kr6 = T0[(int) ((k06 >> 56) & 0xFFL)] ^ T1[(int) ((k05 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k04 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k03 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k02 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k01 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k00 >> 8) & 0xFFL)] ^ T7[(int) (k07 & 0xFFL)];
+
+ Kr7 = T0[(int) ((k07 >> 56) & 0xFFL)] ^ T1[(int) ((k06 >> 48) & 0xFFL)]
+ ^ T2[(int) ((k05 >> 40) & 0xFFL)]
+ ^ T3[(int) ((k04 >> 32) & 0xFFL)]
+ ^ T4[(int) ((k03 >> 24) & 0xFFL)]
+ ^ T5[(int) ((k02 >> 16) & 0xFFL)]
+ ^ T6[(int) ((k01 >> 8) & 0xFFL)] ^ T7[(int) (k00 & 0xFFL)];
+
+ k00 = Kr0;
+ k01 = Kr1;
+ k02 = Kr2;
+ k03 = Kr3;
+ k04 = Kr4;
+ k05 = Kr5;
+ k06 = Kr6;
+ k07 = Kr7;
+
+ // 2. incrementally compute the cipher output
+ w0 = T0[(int) ((nn0 >> 56) & 0xFFL)] ^ T1[(int) ((nn7 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn6 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn5 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn4 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn3 >> 16) & 0xFFL)] ^ T6[(int) ((nn2 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn1 & 0xFFL)] ^ Kr0;
+ w1 = T0[(int) ((nn1 >> 56) & 0xFFL)] ^ T1[(int) ((nn0 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn7 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn6 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn5 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn4 >> 16) & 0xFFL)] ^ T6[(int) ((nn3 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn2 & 0xFFL)] ^ Kr1;
+ w2 = T0[(int) ((nn2 >> 56) & 0xFFL)] ^ T1[(int) ((nn1 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn0 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn7 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn6 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn5 >> 16) & 0xFFL)] ^ T6[(int) ((nn4 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn3 & 0xFFL)] ^ Kr2;
+ w3 = T0[(int) ((nn3 >> 56) & 0xFFL)] ^ T1[(int) ((nn2 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn1 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn0 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn7 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn6 >> 16) & 0xFFL)] ^ T6[(int) ((nn5 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn4 & 0xFFL)] ^ Kr3;
+ w4 = T0[(int) ((nn4 >> 56) & 0xFFL)] ^ T1[(int) ((nn3 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn2 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn1 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn0 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn7 >> 16) & 0xFFL)] ^ T6[(int) ((nn6 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn5 & 0xFFL)] ^ Kr4;
+ w5 = T0[(int) ((nn5 >> 56) & 0xFFL)] ^ T1[(int) ((nn4 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn3 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn2 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn1 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn0 >> 16) & 0xFFL)] ^ T6[(int) ((nn7 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn6 & 0xFFL)] ^ Kr5;
+ w6 = T0[(int) ((nn6 >> 56) & 0xFFL)] ^ T1[(int) ((nn5 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn4 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn3 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn2 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn1 >> 16) & 0xFFL)] ^ T6[(int) ((nn0 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn7 & 0xFFL)] ^ Kr6;
+ w7 = T0[(int) ((nn7 >> 56) & 0xFFL)] ^ T1[(int) ((nn6 >> 48) & 0xFFL)]
+ ^ T2[(int) ((nn5 >> 40) & 0xFFL)]
+ ^ T3[(int) ((nn4 >> 32) & 0xFFL)]
+ ^ T4[(int) ((nn3 >> 24) & 0xFFL)]
+ ^ T5[(int) ((nn2 >> 16) & 0xFFL)] ^ T6[(int) ((nn1 >> 8) & 0xFFL)]
+ ^ T7[(int) (nn0 & 0xFFL)] ^ Kr7;
+
+ nn0 = w0;
+ nn1 = w1;
+ nn2 = w2;
+ nn3 = w3;
+ nn4 = w4;
+ nn5 = w5;
+ nn6 = w6;
+ nn7 = w7;
+ }
+
+ // apply the Miyaguchi-Preneel hash scheme
+ H0 ^= w0 ^ n0;
+ H1 ^= w1 ^ n1;
+ H2 ^= w2 ^ n2;
+ H3 ^= w3 ^ n3;
+ H4 ^= w4 ^ n4;
+ H5 ^= w5 ^ n5;
+ H6 ^= w6 ^ n6;
+ H7 ^= w7 ^ n7;
+ }
+
+ protected byte[] padBuffer()
+ {
+ // [WHIRLPOOL] p. 6:
+ // "...padded with a 1-bit, then with as few 0-bits as necessary to
+ // obtain a bit string whose length is an odd multiple of 256, and
+ // finally with the 256-bit right-justified binary representation of L."
+ // in this implementation we use 'count' as the number of bytes hashed
+ // so far. hence the minimal number of bytes added to the message proper
+ // are 33 (1 for the 1-bit followed by the 0-bits and the encoding of
+ // the count framed in a 256-bit block). our formula is then:
+ // count + 33 + padding = 0 (mod BLOCK_SIZE)
+ int n = (int) ((count + 33) % BLOCK_SIZE);
+ int padding = n == 0 ? 33 : BLOCK_SIZE - n + 33;
+
+ byte[] result = new byte[padding];
+
+ // padding is always binary 1 followed by binary 0s
+ result[0] = (byte) 0x80;
+
+ // save (right justified) the number of bits hashed
+ long bits = count * 8;
+ int i = padding - 8;
+ result[i++] = (byte) (bits >>> 56);
+ result[i++] = (byte) (bits >>> 48);
+ result[i++] = (byte) (bits >>> 40);
+ result[i++] = (byte) (bits >>> 32);
+ result[i++] = (byte) (bits >>> 24);
+ result[i++] = (byte) (bits >>> 16);
+ result[i++] = (byte) (bits >>> 8);
+ result[i] = (byte) bits;
+
+ return result;
+ }
+
+ protected byte[] getResult()
+ {
+ // apply inverse mu to the context
+ byte[] result = new byte[] { (byte) (H0 >>> 56), (byte) (H0 >>> 48),
+ (byte) (H0 >>> 40), (byte) (H0 >>> 32),
+ (byte) (H0 >>> 24), (byte) (H0 >>> 16),
+ (byte) (H0 >>> 8), (byte) H0,
+ (byte) (H1 >>> 56), (byte) (H1 >>> 48),
+ (byte) (H1 >>> 40), (byte) (H1 >>> 32),
+ (byte) (H1 >>> 24), (byte) (H1 >>> 16),
+ (byte) (H1 >>> 8), (byte) H1,
+ (byte) (H2 >>> 56), (byte) (H2 >>> 48),
+ (byte) (H2 >>> 40), (byte) (H2 >>> 32),
+ (byte) (H2 >>> 24), (byte) (H2 >>> 16),
+ (byte) (H2 >>> 8), (byte) H2,
+ (byte) (H3 >>> 56), (byte) (H3 >>> 48),
+ (byte) (H3 >>> 40), (byte) (H3 >>> 32),
+ (byte) (H3 >>> 24), (byte) (H3 >>> 16),
+ (byte) (H3 >>> 8), (byte) H3,
+ (byte) (H4 >>> 56), (byte) (H4 >>> 48),
+ (byte) (H4 >>> 40), (byte) (H4 >>> 32),
+ (byte) (H4 >>> 24), (byte) (H4 >>> 16),
+ (byte) (H4 >>> 8), (byte) H4,
+ (byte) (H5 >>> 56), (byte) (H5 >>> 48),
+ (byte) (H5 >>> 40), (byte) (H5 >>> 32),
+ (byte) (H5 >>> 24), (byte) (H5 >>> 16),
+ (byte) (H5 >>> 8), (byte) H5,
+ (byte) (H6 >>> 56), (byte) (H6 >>> 48),
+ (byte) (H6 >>> 40), (byte) (H6 >>> 32),
+ (byte) (H6 >>> 24), (byte) (H6 >>> 16),
+ (byte) (H6 >>> 8), (byte) H6,
+ (byte) (H7 >>> 56), (byte) (H7 >>> 48),
+ (byte) (H7 >>> 40), (byte) (H7 >>> 32),
+ (byte) (H7 >>> 24), (byte) (H7 >>> 16),
+ (byte) (H7 >>> 8), (byte) H7 };
+
+ return result;
+ }
+
+ protected void resetContext()
+ {
+ H0 = H1 = H2 = H3 = H4 = H5 = H6 = H7 = 0L;
+ }
+
+ public boolean selfTest()
+ {
+ if (valid == null)
+ {
+ valid = new Boolean(
+ DIGEST0.equals(Util.toString(new Whirlpool().digest())));
+ }
+ return valid.booleanValue();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/HavalSpi.java b/libjava/classpath/gnu/java/security/jce/hash/HavalSpi.java
new file mode 100644
index 00000000000..e127779efb4
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/HavalSpi.java
@@ -0,0 +1,68 @@
+/* HavalSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the <code>HAVAL</code> <i>Service Provider Interface</i>
+ * (<b>SPI</b>) Adapter.<p>
+ *
+ * @version Revision: $
+ */
+public class HavalSpi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public HavalSpi()
+ {
+ super(Registry.HAVAL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/MD2Spi.java b/libjava/classpath/gnu/java/security/jce/hash/MD2Spi.java
new file mode 100644
index 00000000000..5b6b0e1e1d7
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/MD2Spi.java
@@ -0,0 +1,69 @@
+/* MD2Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the MD2 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class MD2Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public MD2Spi()
+ {
+ super(Registry.MD2_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/MD4Spi.java b/libjava/classpath/gnu/java/security/jce/hash/MD4Spi.java
new file mode 100644
index 00000000000..8be44993400
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/MD4Spi.java
@@ -0,0 +1,69 @@
+/* MD4Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the MD4 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class MD4Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public MD4Spi()
+ {
+ super(Registry.MD4_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/MD5Spi.java b/libjava/classpath/gnu/java/security/jce/hash/MD5Spi.java
new file mode 100644
index 00000000000..92fb6ab3864
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/MD5Spi.java
@@ -0,0 +1,68 @@
+/* MD5Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the MD5 <i>Service Provider Interface</i> (<b>SPI</b>)
+ * adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class MD5Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public MD5Spi()
+ {
+ super(Registry.MD5_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/MessageDigestAdapter.java b/libjava/classpath/gnu/java/security/jce/hash/MessageDigestAdapter.java
new file mode 100644
index 00000000000..9b8a73d55fd
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/MessageDigestAdapter.java
@@ -0,0 +1,147 @@
+/* MessageDigestAdapter.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.hash.HashFactory;
+
+import java.security.DigestException;
+import java.security.MessageDigestSpi;
+
+/**
+ * The implementation of a generic {@link java.security.MessageDigest} adapter
+ * class to wrap gnu.crypto hash instances.<p>
+ *
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
+ * {@link java.security.MessageDigest} class, which provides the functionality
+ * of a message digest algorithm, such as MD5 or SHA. Message digests are secure
+ * one-way hash functions that take arbitrary-sized data and output a fixed-
+ * length hash value.<p>
+ *
+ * All the abstract methods in the {@link java.security.MessageDigestSpi} class
+ * are implemented by this class and all its sub-classes.<p>
+ *
+ * All the implementations which subclass this object, and which are serviced by
+ * the GNU Crypto provider implement the {@link java.lang.Cloneable} interface.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+class MessageDigestAdapter extends MessageDigestSpi implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying hash instance. */
+ private IMessageDigest adaptee;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial protected constructor.
+ *
+ * @param mdName the canonical name of the hash algorithm.
+ */
+ protected MessageDigestAdapter(String mdName)
+ {
+ this(HashFactory.getInstance(mdName));
+ }
+
+ /**
+ * Private constructor for cloning purposes.
+ *
+ * @param adaptee a clone of the underlying hash algorithm instance.
+ */
+ private MessageDigestAdapter(IMessageDigest adaptee)
+ {
+ super();
+
+ this.adaptee = adaptee;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // java.security.MessageDigestSpi interface implementation
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new MessageDigestAdapter((IMessageDigest) adaptee.clone());
+ }
+
+ public int engineGetDigestLength()
+ {
+ return adaptee.hashSize();
+ }
+
+ public void engineUpdate(byte input)
+ {
+ adaptee.update(input);
+ }
+
+ public void engineUpdate(byte[] input, int offset, int len)
+ {
+ adaptee.update(input, offset, len);
+ }
+
+ public byte[] engineDigest()
+ {
+ return adaptee.digest();
+ }
+
+ public int engineDigest(byte[] buf, int offset, int len)
+ throws DigestException
+ {
+ int result = adaptee.hashSize();
+ if (len < result)
+ {
+ throw new DigestException();
+ }
+ byte[] md = adaptee.digest();
+ System.arraycopy(md, 0, buf, offset, result);
+ return result;
+ }
+
+ public void engineReset()
+ {
+ adaptee.reset();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/RipeMD128Spi.java b/libjava/classpath/gnu/java/security/jce/hash/RipeMD128Spi.java
new file mode 100644
index 00000000000..b8e90d4bfb4
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/RipeMD128Spi.java
@@ -0,0 +1,68 @@
+/* RipeMD128Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the RIPEMD-128 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RipeMD128Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RipeMD128Spi()
+ {
+ super(Registry.RIPEMD128_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/RipeMD160Spi.java b/libjava/classpath/gnu/java/security/jce/hash/RipeMD160Spi.java
new file mode 100644
index 00000000000..49615e2fcc8
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/RipeMD160Spi.java
@@ -0,0 +1,68 @@
+/* RipeMD160Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the RIPEMD-160 <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RipeMD160Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RipeMD160Spi()
+ {
+ super(Registry.RIPEMD160_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/Sha160Spi.java b/libjava/classpath/gnu/java/security/jce/hash/Sha160Spi.java
new file mode 100644
index 00000000000..a9b72634d78
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/Sha160Spi.java
@@ -0,0 +1,68 @@
+/* Sha160Spi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the SHA-1 (160-bit) <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Sha160Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha160Spi()
+ {
+ super(Registry.SHA160_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/Sha256Spi.java b/libjava/classpath/gnu/java/security/jce/hash/Sha256Spi.java
new file mode 100644
index 00000000000..9eeaebdeaec
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/Sha256Spi.java
@@ -0,0 +1,68 @@
+/* Sha256Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-2-1 (256-bit) <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Sha256Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha256Spi()
+ {
+ super(Registry.SHA256_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/Sha384Spi.java b/libjava/classpath/gnu/java/security/jce/hash/Sha384Spi.java
new file mode 100644
index 00000000000..96e1e6eb0ab
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/Sha384Spi.java
@@ -0,0 +1,68 @@
+/* Sha384Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-2-2 (384-bit) <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Sha384Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha384Spi()
+ {
+ super(Registry.SHA384_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/Sha512Spi.java b/libjava/classpath/gnu/java/security/jce/hash/Sha512Spi.java
new file mode 100644
index 00000000000..75c617046fc
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/Sha512Spi.java
@@ -0,0 +1,68 @@
+/* Sha512Spi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-2-3 (512-bit) <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Sha512Spi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha512Spi()
+ {
+ super(Registry.SHA512_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/TigerSpi.java b/libjava/classpath/gnu/java/security/jce/hash/TigerSpi.java
new file mode 100644
index 00000000000..b355d78d05c
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/TigerSpi.java
@@ -0,0 +1,69 @@
+/* TigerSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the Tiger <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class TigerSpi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public TigerSpi()
+ {
+ super(Registry.TIGER_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/hash/WhirlpoolSpi.java b/libjava/classpath/gnu/java/security/jce/hash/WhirlpoolSpi.java
new file mode 100644
index 00000000000..e42e74ddb36
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/hash/WhirlpoolSpi.java
@@ -0,0 +1,68 @@
+/* WhirlpoolSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.hash;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Whirlpool <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class WhirlpoolSpi extends MessageDigestAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public WhirlpoolSpi()
+ {
+ super(Registry.WHIRLPOOL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/HavalRandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/HavalRandomSpi.java
new file mode 100644
index 00000000000..0c39a37fd1b
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/HavalRandomSpi.java
@@ -0,0 +1,66 @@
+/* HavalRandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the HAVAL-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) Adapter.<p>
+ */
+public class HavalRandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public HavalRandomSpi()
+ {
+ super(Registry.HAVAL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/MD2RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/MD2RandomSpi.java
new file mode 100644
index 00000000000..72a7f4873e4
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/MD2RandomSpi.java
@@ -0,0 +1,66 @@
+/* MD2RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the MD2-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class MD2RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public MD2RandomSpi()
+ {
+ super(Registry.MD2_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/MD4RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/MD4RandomSpi.java
new file mode 100644
index 00000000000..f5f98f8f39b
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/MD4RandomSpi.java
@@ -0,0 +1,66 @@
+/* MD4RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the MD4-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class MD4RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public MD4RandomSpi()
+ {
+ super(Registry.MD4_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/MD5RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/MD5RandomSpi.java
new file mode 100644
index 00000000000..0181247bc5e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/MD5RandomSpi.java
@@ -0,0 +1,66 @@
+/* MD5RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the MD5-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class MD5RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public MD5RandomSpi()
+ {
+ super(Registry.MD5_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/RipeMD128RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/RipeMD128RandomSpi.java
new file mode 100644
index 00000000000..5580716a491
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/RipeMD128RandomSpi.java
@@ -0,0 +1,66 @@
+/* RipeMD128RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the RIPEMD128-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class RipeMD128RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RipeMD128RandomSpi()
+ {
+ super(Registry.RIPEMD128_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/RipeMD160RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/RipeMD160RandomSpi.java
new file mode 100644
index 00000000000..734fe824a4c
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/RipeMD160RandomSpi.java
@@ -0,0 +1,66 @@
+/* RipeMD160RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the RIPEMD160-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class RipeMD160RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RipeMD160RandomSpi()
+ {
+ super(Registry.RIPEMD160_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/SecureRandomAdapter.java b/libjava/classpath/gnu/java/security/jce/prng/SecureRandomAdapter.java
new file mode 100644
index 00000000000..e7cb7209103
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/SecureRandomAdapter.java
@@ -0,0 +1,126 @@
+/* SecureRandomAdapter.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.prng.MDGenerator;
+
+import java.security.SecureRandomSpi;
+import java.util.HashMap;
+
+/**
+ * <p>The implementation of a generic {@link java.security.SecureRandom} adapter
+ * class to wrap gnu.crypto prng instances based on Message Digest algorithms.</p>
+ *
+ * <p>This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
+ * the {@link java.security.SecureRandom} class, which provides the
+ * functionality of a cryptographically strong pseudo-random number generator.</p>
+ *
+ * <p>All the abstract methods in the {@link SecureRandomSpi} class are
+ * implemented by this class and all its sub-classes.</p>
+ */
+abstract class SecureRandomAdapter extends SecureRandomSpi
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying prng instance. */
+ private MDGenerator adaptee = new MDGenerator();
+
+ /** The name of the message digest algorithm used by the adaptee. */
+ private String mdName;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial protected constructor.</p>
+ *
+ * @param mdName the canonical name of the underlying hash algorithm.
+ */
+ protected SecureRandomAdapter(String mdName)
+ {
+ super();
+
+ this.mdName = mdName;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.SecureRandomSpi interface implementation ------------------
+
+ public byte[] engineGenerateSeed(int numBytes)
+ {
+ if (numBytes < 1)
+ {
+ return new byte[0];
+ }
+ byte[] result = new byte[numBytes];
+ this.engineNextBytes(result);
+ return result;
+ }
+
+ public void engineNextBytes(byte[] bytes)
+ {
+ if (!adaptee.isInitialised())
+ {
+ this.engineSetSeed(new byte[0]);
+ }
+ try
+ {
+ adaptee.nextBytes(bytes, 0, bytes.length);
+ }
+ catch (LimitReachedException ignored)
+ {
+ }
+ }
+
+ public void engineSetSeed(byte[] seed)
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(MDGenerator.MD_NAME, mdName);
+ attributes.put(MDGenerator.SEEED, seed);
+ adaptee.init(attributes);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/Sha160RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/Sha160RandomSpi.java
new file mode 100644
index 00000000000..c93b02d3fb8
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/Sha160RandomSpi.java
@@ -0,0 +1,66 @@
+/* Sha160RandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the SHA1-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class Sha160RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha160RandomSpi()
+ {
+ super(Registry.SHA160_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/Sha256RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/Sha256RandomSpi.java
new file mode 100644
index 00000000000..736996430e1
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/Sha256RandomSpi.java
@@ -0,0 +1,66 @@
+/* Sha256RandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-256 based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.</p>
+ */
+public class Sha256RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha256RandomSpi()
+ {
+ super(Registry.SHA256_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/Sha384RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/Sha384RandomSpi.java
new file mode 100644
index 00000000000..afbf19303c8
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/Sha384RandomSpi.java
@@ -0,0 +1,66 @@
+/* Sha384RandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-384 based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.</p>
+ */
+public class Sha384RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha384RandomSpi()
+ {
+ super(Registry.SHA384_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/Sha512RandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/Sha512RandomSpi.java
new file mode 100644
index 00000000000..b2b33776008
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/Sha512RandomSpi.java
@@ -0,0 +1,66 @@
+/* Sha512RandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The implementation of the SHA-512 based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.</p>
+ */
+public class Sha512RandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public Sha512RandomSpi()
+ {
+ super(Registry.SHA512_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/TigerRandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/TigerRandomSpi.java
new file mode 100644
index 00000000000..b4795b98ecc
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/TigerRandomSpi.java
@@ -0,0 +1,66 @@
+/* TigerRandomSpi.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Tiger based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class TigerRandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public TigerRandomSpi()
+ {
+ super(Registry.TIGER_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/prng/WhirlpoolRandomSpi.java b/libjava/classpath/gnu/java/security/jce/prng/WhirlpoolRandomSpi.java
new file mode 100644
index 00000000000..f327f9df2c7
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/prng/WhirlpoolRandomSpi.java
@@ -0,0 +1,66 @@
+/* WhirlpoolRandomSpi.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.prng;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the Whirlpool-based SecureRandom <i>Service Provider
+ * Interface</i> (<b>SPI</b>) adapter.<p>
+ */
+public class WhirlpoolRandomSpi extends SecureRandomAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public WhirlpoolRandomSpi()
+ {
+ super(Registry.WHIRLPOOL_HASH);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/DSSKeyFactory.java b/libjava/classpath/gnu/java/security/jce/sig/DSSKeyFactory.java
new file mode 100644
index 00000000000..bb4d85c899d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/DSSKeyFactory.java
@@ -0,0 +1,238 @@
+/* DSSKeyFactory.java -- JCE DSA key factory 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSKeyPairPKCS8Codec;
+import gnu.java.security.key.dss.DSSKeyPairX509Codec;
+import gnu.java.security.key.dss.DSSPrivateKey;
+import gnu.java.security.key.dss.DSSPublicKey;
+
+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.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+/**
+ * DSA key factory.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public class DSSKeyFactory extends KeyFactorySpi
+{
+ // implicit 0-arguments constructor
+
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof DSAPublicKeySpec)
+ {
+ DSAPublicKeySpec spec = (DSAPublicKeySpec) keySpec;
+ BigInteger p = spec.getP();
+ BigInteger q = spec.getQ();
+ BigInteger g = spec.getG();
+ BigInteger y = spec.getY();
+ return new DSSPublicKey(Registry.X509_ENCODING_ID, p, q, g, y);
+ }
+
+ if (keySpec instanceof X509EncodedKeySpec)
+ {
+ X509EncodedKeySpec spec = (X509EncodedKeySpec) keySpec;
+ byte[] encoded = spec.getEncoded();
+ PublicKey result;
+ try
+ {
+ result = new DSSKeyPairX509Codec().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 DSAPrivateKeySpec)
+ {
+ DSAPrivateKeySpec spec = (DSAPrivateKeySpec) keySpec;
+ BigInteger p = spec.getP();
+ BigInteger q = spec.getQ();
+ BigInteger g = spec.getG();
+ BigInteger x = spec.getX();
+ return new DSSPrivateKey(Registry.PKCS8_ENCODING_ID, p, q, g, x);
+ }
+
+ if (keySpec instanceof PKCS8EncodedKeySpec)
+ {
+ PKCS8EncodedKeySpec spec = (PKCS8EncodedKeySpec) keySpec;
+ byte[] encoded = spec.getEncoded();
+ PrivateKey result;
+ try
+ {
+ result = new DSSKeyPairPKCS8Codec().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 DSAPublicKey)
+ {
+ if (keySpec.isAssignableFrom(DSAPublicKeySpec.class))
+ {
+ DSAPublicKey dsaKey = (DSAPublicKey) key;
+ BigInteger p = dsaKey.getParams().getP();
+ BigInteger q = dsaKey.getParams().getQ();
+ BigInteger g = dsaKey.getParams().getG();
+ BigInteger y = dsaKey.getY();
+ return new DSAPublicKeySpec(y, p, q, g);
+ }
+
+ if (keySpec.isAssignableFrom(X509EncodedKeySpec.class))
+ {
+ if (key instanceof DSSPublicKey)
+ {
+ DSSPublicKey dssKey = (DSSPublicKey) key;
+ byte[] encoded = dssKey.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 DSAPrivateKey)
+ {
+ if (keySpec.isAssignableFrom(DSAPrivateKeySpec.class))
+ {
+ DSAPrivateKey dsaKey = (DSAPrivateKey) key;
+ BigInteger p = dsaKey.getParams().getP();
+ BigInteger q = dsaKey.getParams().getQ();
+ BigInteger g = dsaKey.getParams().getG();
+ BigInteger x = dsaKey.getX();
+ return new DSAPrivateKeySpec(x, p, q, g);
+ }
+
+ if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class))
+ {
+ if (key instanceof DSSPrivateKey)
+ {
+ DSSPrivateKey dssKey = (DSSPrivateKey) key;
+ byte[] encoded = dssKey.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 DSSPublicKey) || (key instanceof DSSPrivateKey))
+ return key;
+
+ if (key instanceof DSAPublicKey)
+ {
+ DSAPublicKey dsaKey = (DSAPublicKey) key;
+ BigInteger p = dsaKey.getParams().getP();
+ BigInteger q = dsaKey.getParams().getQ();
+ BigInteger g = dsaKey.getParams().getG();
+ BigInteger y = dsaKey.getY();
+ return new DSSPublicKey(Registry.X509_ENCODING_ID, p, q, g, y);
+ }
+
+ if (key instanceof DSAPrivateKey)
+ {
+ DSAPrivateKey dsaKey = (DSAPrivateKey) key;
+ BigInteger p = dsaKey.getParams().getP();
+ BigInteger q = dsaKey.getParams().getQ();
+ BigInteger g = dsaKey.getParams().getG();
+ BigInteger x = dsaKey.getX();
+ return new DSSPrivateKey(Registry.PKCS8_ENCODING_ID, p, q, g, x);
+ }
+
+ throw new InvalidKeyException("Wrong key type");
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java b/libjava/classpath/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java
new file mode 100644
index 00000000000..97e9594f6a5
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java
@@ -0,0 +1,169 @@
+/* DSSKeyPairGeneratorSpi.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSKeyPairGenerator;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.SecureRandom;
+import java.security.interfaces.DSAKeyPairGenerator;
+import java.security.interfaces.DSAParams;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.DSAParameterSpec;
+import java.util.HashMap;
+
+/**
+ * The implementation of a {@link java.security.KeyPairGenerator} adapter class
+ * to wrap gnu.crypto DSS keypair generator instances.<p>
+ *
+ * In case the client does not explicitly initialize the KeyPairGenerator (via
+ * a call to an <code>initialize()</code> method), the GNU Crypto provider
+ * uses a default <i>modulus</i> size (keysize) of 1024 bits.<p>
+ *
+ * @version $Revision: 1.3 $
+ */
+public class DSSKeyPairGeneratorSpi extends KeyPairGeneratorAdapter implements
+ DSAKeyPairGenerator
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public DSSKeyPairGeneratorSpi()
+ {
+ super(Registry.DSS_KPG);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public void initialize(int keysize, SecureRandom random)
+ {
+ this.initialize(keysize, false, random);
+ }
+
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ HashMap attributes = new HashMap();
+ if (params != null)
+ {
+ if (!(params instanceof DSAParameterSpec))
+ throw new InvalidAlgorithmParameterException(
+ "Parameters argument is not a non-null instance, or " +
+ "sub-instance, of java.security.spec.DSAParameterSpec");
+
+ attributes.put(DSSKeyPairGenerator.DSS_PARAMETERS, params);
+ }
+
+ if (random != null)
+ {
+ attributes.put(DSSKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+ }
+
+ attributes.put(DSSKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
+ try
+ {
+ adaptee.setup(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ InvalidAlgorithmParameterException y =
+ new InvalidAlgorithmParameterException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ // java.security.interfaces.DSAKeyPairGenerator interface implementation -----
+
+ public void initialize(DSAParams params, SecureRandom random)
+ throws InvalidParameterException
+ {
+ if (params == null || !(params instanceof DSAParameterSpec))
+ throw new InvalidParameterException(
+ "Parameters argument is either null or is not an instance, or " +
+ "sub-instance, of java.security.spec.DSAParameterSpec");
+ DSAParameterSpec spec = (DSAParameterSpec) params;
+ try
+ {
+ this.initialize((AlgorithmParameterSpec) spec, random);
+ }
+ catch (InvalidAlgorithmParameterException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ public void initialize(int modlen, boolean genParams, SecureRandom random)
+ throws InvalidParameterException
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(DSSKeyPairGenerator.MODULUS_LENGTH, new Integer(modlen));
+ if (random != null)
+ attributes.put(DSSKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+
+ attributes.put(DSSKeyPairGenerator.USE_DEFAULTS,
+ Boolean.valueOf(!genParams));
+ attributes.put(DSSKeyPairGenerator.STRICT_DEFAULTS, Boolean.TRUE);
+ attributes.put(DSSKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
+ try
+ {
+ adaptee.setup(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/DSSParameters.java b/libjava/classpath/gnu/java/security/jce/sig/DSSParameters.java
new file mode 100644
index 00000000000..ba1f414faea
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/DSSParameters.java
@@ -0,0 +1,220 @@
+/* DSSParameters.java -- DSS 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.java.security.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.DSAParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.ArrayList;
+
+/**
+ * A JCE-specific Data Access Object (DAO) for DSS parameters.
+ */
+public class DSSParameters
+ extends AlgorithmParametersSpi
+{
+ /**
+ * A prime modulus, where <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup></code>
+ * for <code>512 &lt;= L &lt;= 1024</code> and <code>L</code> a multiple of
+ * <code>64</code>.
+ */
+ private BigInteger p;
+
+ /**
+ * A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup> &lt; q
+ * &lt; 2<sup>160</sup></code>.
+ */
+ private BigInteger q;
+
+ /**
+ * <code>g = h<sup>(p-1)</sup>/q mod p</code>, where <code>h</code> is any
+ * integer with <code>1 &lt; h &lt; p - 1</code> such that <code>h<sup>
+ * (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order <code>q mod p
+ * </code>).
+ */
+ private BigInteger g;
+
+ // default 0-arguments constructor
+
+ protected void engineInit(AlgorithmParameterSpec spec)
+ throws InvalidParameterSpecException
+ {
+ if (! (spec instanceof DSAParameterSpec))
+ throw new InvalidParameterSpecException("Wrong AlgorithmParameterSpec type: "
+ + spec.getClass().getName());
+ DSAParameterSpec dsaSpec = (DSAParameterSpec) spec;
+ p = dsaSpec.getP();
+ q = dsaSpec.getQ();
+ g = dsaSpec.getG();
+ }
+
+ /**
+ * Decodes the set of DSS parameters as per RFC-2459; i.e. the DER-encoded
+ * form of the following ASN.1 construct:
+ *
+ * <pre>
+ * DssParams ::= SEQUENCE {
+ * p INTEGER,
+ * q INTEGER,
+ * g INTEGER
+ * }
+ * </pre>
+ */
+ protected void engineInit(byte[] params) throws IOException
+ {
+ DERReader der = new DERReader(params);
+
+ 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 Q field");
+ q = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong G field");
+ g = (BigInteger) val.getValue();
+ }
+
+ 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(DSAParameterSpec.class))
+ throw new InvalidParameterSpecException("Wrong AlgorithmParameterSpec type: "
+ + paramSpec.getName());
+ return new DSAParameterSpec(p, q, g);
+ }
+
+ /**
+ * Encodes the set of DSS parameters as per RFC-2459; i.e. as the DER-encoded
+ * form of the following ASN.1 construct:
+ *
+ * <pre>
+ * DssParams ::= SEQUENCE {
+ * p INTEGER,
+ * q INTEGER,
+ * g INTEGER
+ * }
+ * </pre>
+ */
+ protected byte[] engineGetEncoded() throws IOException
+ {
+ DERValue derP = new DERValue(DER.INTEGER, p);
+ DERValue derQ = new DERValue(DER.INTEGER, q);
+ DERValue derG = new DERValue(DER.INTEGER, g);
+
+ ArrayList params = new ArrayList(3);
+ params.add(derP);
+ params.add(derQ);
+ params.add(derG);
+ 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(", q=");
+ if (q == null)
+ sb.append("???");
+ else
+ sb.append("0x").append(q.toString(16));
+
+ sb.append(", g=");
+ if (g == null)
+ sb.append("???");
+ else
+ sb.append("0x").append(g.toString(16));
+
+ return sb.toString();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/DSSParametersGenerator.java b/libjava/classpath/gnu/java/security/jce/sig/DSSParametersGenerator.java
new file mode 100644
index 00000000000..09c13861042
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/DSSParametersGenerator.java
@@ -0,0 +1,125 @@
+/* DSSParametersGenerator.java -- JCE Adapter for a generator of DSS 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSKeyPairGenerator;
+import gnu.java.security.key.dss.FIPS186;
+import gnu.java.security.provider.Gnu;
+
+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.DSAParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+/**
+ * A JCE Adapter for a generator of DSS parameters.
+ */
+public class DSSParametersGenerator
+ extends AlgorithmParameterGeneratorSpi
+{
+ private static final Provider GNU = new Gnu();
+
+ /** Size of the public modulus in bits. */
+ private int modulusLength = -1;
+
+ /** User specified source of randomness. */
+ private SecureRandom rnd;
+
+ /** Our concrete DSS parameters generator. */
+ private FIPS186 fips;
+
+ // default 0-arguments constructor
+
+ protected void engineInit(int size, SecureRandom random)
+ {
+ if ((size % 64) != 0 || size < 512 || size > 1024)
+ throw new InvalidParameterException("Modulus size/length (in bits) MUST "
+ + "be a multiple of 64, greater than "
+ + "or equal to 512, and less than or "
+ + "equal to 1024");
+ this.modulusLength = size;
+ this.rnd = random;
+ }
+
+ protected void engineInit(AlgorithmParameterSpec spec, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ if (! (spec instanceof DSAParameterSpec))
+ throw new InvalidAlgorithmParameterException("Wrong AlgorithmParameterSpec type: "
+ + spec.getClass().getName());
+ DSAParameterSpec dsaSpec = (DSAParameterSpec) spec;
+ BigInteger p = dsaSpec.getP();
+ int size = p.bitLength();
+ this.engineInit(size, random);
+ }
+
+ protected AlgorithmParameters engineGenerateParameters()
+ {
+ if (modulusLength < 1)
+ modulusLength = DSSKeyPairGenerator.DEFAULT_MODULUS_LENGTH;
+
+ fips = new FIPS186(modulusLength, rnd);
+ BigInteger[] params = fips.generateParameters();
+ BigInteger p = params[3];
+ BigInteger q = params[2];
+ BigInteger g = params[5];
+ DSAParameterSpec spec = new DSAParameterSpec(p, q, g);
+ AlgorithmParameters result = null;
+ try
+ {
+ result = AlgorithmParameters.getInstance(Registry.DSS_KPG, GNU);
+ result.init(spec);
+ }
+ catch (NoSuchAlgorithmException ignore)
+ {
+ }
+ catch (InvalidParameterSpecException ignore)
+ {
+ }
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/DSSRawSignatureSpi.java b/libjava/classpath/gnu/java/security/jce/sig/DSSRawSignatureSpi.java
new file mode 100644
index 00000000000..16e4ddd4edc
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/DSSRawSignatureSpi.java
@@ -0,0 +1,70 @@
+/* DSSRawSignatureSpi.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.dss.DSSSignatureRawCodec;
+
+/**
+ * The implementation of <i>Service Provider Interface</i> (<b>SPI</b>) adapter
+ * for the DSS (Digital Signature Standard) signature scheme, encoded and/or
+ * decoded in RAW format.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSRawSignatureSpi extends SignatureAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public DSSRawSignatureSpi()
+ {
+ super(Registry.DSS_SIG, new DSSSignatureRawCodec());
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/EncodedKeyFactory.java b/libjava/classpath/gnu/java/security/jce/sig/EncodedKeyFactory.java
new file mode 100644
index 00000000000..60152c279fa
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/EncodedKeyFactory.java
@@ -0,0 +1,453 @@
+/* EncodedKeyFactory.java -- JCE Encoded key factory 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSPrivateKey;
+import gnu.java.security.key.dss.DSSPublicKey;
+import gnu.java.security.key.rsa.GnuRSAPrivateKey;
+import gnu.java.security.key.rsa.GnuRSAPublicKey;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.Key;
+import java.security.KeyFactorySpi;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.DSAPrivateKeySpec;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHPrivateKeySpec;
+import javax.crypto.spec.DHPublicKeySpec;
+
+/**
+ * A factory for keys encoded in either the X.509 format (for public keys) or
+ * the PKCS#8 format (for private keys).
+ */
+public class EncodedKeyFactory
+ extends KeyFactorySpi
+{
+ private static final Logger log = Logger.getLogger(EncodedKeyFactory.class.getName());
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ private static Object invokeConstructor(String className, Object[] params)
+ throws InvalidKeySpecException
+ {
+ Class clazz = getConcreteClass(className);
+ try
+ {
+ Constructor ctor = getConcreteCtor(clazz);
+ Object result = ctor.newInstance(params);
+ return result;
+ }
+ catch (InstantiationException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ catch (IllegalAccessException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(y);
+ throw y;
+ }
+ catch (InvocationTargetException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ private static Class getConcreteClass(String className)
+ throws InvalidKeySpecException
+ {
+ try
+ {
+ Class result = Class.forName(className);
+ return result;
+ }
+ catch (ClassNotFoundException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ private static Constructor getConcreteCtor(Class clazz)
+ throws InvalidKeySpecException
+ {
+ try
+ {
+ Constructor result = clazz.getConstructor(new Class[] {int.class,
+ BigInteger.class,
+ BigInteger.class,
+ BigInteger.class,
+ BigInteger.class});
+ return result;
+ }
+ catch (NoSuchMethodException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ private static Object invokeValueOf(String className, byte[] encoded)
+ throws InvalidKeySpecException
+ {
+ Class clazz = getConcreteClass(className);
+ try
+ {
+ Method valueOf = getValueOfMethod(clazz);
+ Object result = valueOf.invoke(null, new Object[] { encoded });
+ return result;
+ }
+ catch (IllegalAccessException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ catch (InvocationTargetException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ private static Method getValueOfMethod(Class clazz)
+ throws InvalidKeySpecException
+ {
+ try
+ {
+ Method result = clazz.getMethod("valueOf", new Class[] {byte[].class});
+ return result;
+ }
+ catch (NoSuchMethodException x)
+ {
+ InvalidKeySpecException y = new InvalidKeySpecException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ log.entering(this.getClass().getName(), "engineGeneratePublic()", keySpec);
+
+ PublicKey result = null;
+ if (keySpec instanceof DSAPublicKeySpec)
+ result = decodeDSSPublicKey((DSAPublicKeySpec) keySpec);
+ else if (keySpec instanceof RSAPublicKeySpec)
+ result = decodeRSAPublicKey((RSAPublicKeySpec) keySpec);
+ else if (keySpec instanceof DHPublicKeySpec)
+ result = decodeDHPublicKey((DHPublicKeySpec) keySpec);
+ else
+ {
+ if (! (keySpec instanceof X509EncodedKeySpec))
+ throw new InvalidKeySpecException("Unsupported key specification");
+
+ byte[] input = ((X509EncodedKeySpec) keySpec).getEncoded();
+ boolean ok = false;
+ // try DSS
+ try
+ {
+ result = DSSPublicKey.valueOf(input);
+ ok = true;
+ }
+ catch (InvalidParameterException ignored)
+ {
+ log.log(Level.FINE, "Exception in DSSPublicKey.valueOf(). Ignore",
+ ignored);
+ }
+
+ if (! ok) // try RSA
+ try
+ {
+ result = GnuRSAPublicKey.valueOf(input);
+ ok = true;
+ }
+ catch (InvalidParameterException ignored)
+ {
+ log.log(Level.FINE,
+ "Exception in GnuRSAPublicKey.valueOf(). Ignore",
+ ignored);
+ }
+
+ if (! ok) // try DH
+ result = decodeDHPublicKey(input);
+ }
+
+ log.exiting(this.getClass().getName(), "engineGeneratePublic()", result);
+ return result;
+ }
+
+ protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ log.entering(this.getClass().getName(), "engineGeneratePrivate()", keySpec);
+
+ PrivateKey result = null;
+ if (keySpec instanceof DSAPrivateKeySpec)
+ result = decodeDSSPrivateKey((DSAPrivateKeySpec) keySpec);
+ else if (keySpec instanceof RSAPrivateCrtKeySpec)
+ result = decodeRSAPrivateKey((RSAPrivateCrtKeySpec) keySpec);
+ else if (keySpec instanceof DHPrivateKeySpec)
+ result = decodeDHPrivateKey((DHPrivateKeySpec) keySpec);
+ else
+ {
+ if (! (keySpec instanceof PKCS8EncodedKeySpec))
+ throw new InvalidKeySpecException("Unsupported key specification");
+
+ byte[] input = ((PKCS8EncodedKeySpec) keySpec).getEncoded();
+ boolean ok = false;
+ // try DSS
+ try
+ {
+ result = DSSPrivateKey.valueOf(input);
+ ok = true;
+ }
+ catch (InvalidParameterException ignored)
+ {
+ log.log(Level.FINE, "Exception in DSSPrivateKey.valueOf(). Ignore",
+ ignored);
+ }
+
+ if (! ok) // try RSA
+ try
+ {
+ result = GnuRSAPrivateKey.valueOf(input);
+ ok = true;
+ }
+ catch (InvalidParameterException ignored)
+ {
+ log.log(Level.FINE,
+ "Exception in GnuRSAPrivateKey.valueOf(). Ignore",
+ ignored);
+ }
+
+ if (! ok) // try DH
+ result = decodeDHPrivateKey(input);
+ }
+
+ log.exiting(this.getClass().getName(), "engineGeneratePrivate()", result);
+ return result;
+ }
+
+ protected KeySpec engineGetKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException
+ {
+ if (key instanceof PublicKey
+ && Registry.X509_ENCODING_SORT_NAME.equalsIgnoreCase(key.getFormat())
+ && keySpec.isAssignableFrom(X509EncodedKeySpec.class))
+ return new X509EncodedKeySpec(key.getEncoded());
+
+ if (key instanceof PrivateKey
+ && Registry.PKCS8_ENCODING_SHORT_NAME.equalsIgnoreCase(key.getFormat())
+ && keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class))
+ return new PKCS8EncodedKeySpec(key.getEncoded());
+
+ throw new InvalidKeySpecException("Unsupported format or invalid key spec class");
+ }
+
+ protected Key engineTranslateKey(Key key) throws InvalidKeyException
+ {
+ throw new InvalidKeyException("Key translation not supported");
+ }
+
+ /**
+ * @param spec an instance of {@link DSAPublicKeySpec} to decode.
+ * @return an instance of {@link DSSPublicKey} constructed from the
+ * information in the designated key-specification.
+ */
+ private DSSPublicKey decodeDSSPublicKey(DSAPublicKeySpec spec)
+ {
+ BigInteger p = spec.getP();
+ BigInteger q = spec.getQ();
+ BigInteger g = spec.getG();
+ BigInteger y = spec.getY();
+ return new DSSPublicKey(Registry.X509_ENCODING_ID, p, q, g, y);
+ }
+
+ /**
+ * @param spec an instance of {@link RSAPublicKeySpec} to decode.
+ * @return an instance of {@link GnuRSAPublicKey} constructed from the
+ * information in the designated key-specification.
+ */
+ private GnuRSAPublicKey decodeRSAPublicKey(RSAPublicKeySpec spec)
+ {
+ BigInteger n = spec.getModulus();
+ BigInteger e = spec.getPublicExponent();
+ return new GnuRSAPublicKey(Registry.X509_ENCODING_ID, n, e);
+ }
+
+ /**
+ * @param spec an instance of {@link DHPublicKeySpec} to decode.
+ * @return an instance of a {@link DHPublicKey} constructed from the
+ * information in the designated key-specification.
+ * @throws InvalidKeySpecException if no concrete implementation of the
+ * {@link DHPublicKey} interface exists at run-time, or if an
+ * exception occurs during its instantiation.
+ */
+ private DHPublicKey decodeDHPublicKey(DHPublicKeySpec spec)
+ throws InvalidKeySpecException
+ {
+ BigInteger p = spec.getP();
+ BigInteger g = spec.getG();
+ BigInteger y = spec.getY();
+ Object[] params = new Object[] {new Integer(Registry.X509_ENCODING_ID),
+ null, p, g, y};
+ Object obj = invokeConstructor("gnu.javax.crypto.key.dh.GnuDHPublicKey",
+ params);
+ return (DHPublicKey) obj;
+ }
+
+ /**
+ * @param encoded the bytes to decode.
+ * @return an instance of a {@link DHPublicKey} constructed from the
+ * information in the designated key-specification.
+ * @throws InvalidKeySpecException if no concrete implementation of the
+ * {@link DHPublicKey} interface exists at run-time, or if an
+ * exception occurs during its instantiation.
+ */
+ private DHPublicKey decodeDHPublicKey(byte[] encoded)
+ throws InvalidKeySpecException
+ {
+ Object obj = invokeValueOf("gnu.javax.crypto.key.dh.GnuDHPublicKey",
+ encoded);
+ return (DHPublicKey) obj;
+ }
+
+ /**
+ * @param spec an instance of {@link DSAPrivateKeySpec} to decode.
+ * @return an instance of {@link DSSPrivateKey} constructed from the
+ * information in the designated key-specification.
+ */
+ private PrivateKey decodeDSSPrivateKey(DSAPrivateKeySpec spec)
+ {
+ BigInteger p = spec.getP();
+ BigInteger q = spec.getQ();
+ BigInteger g = spec.getG();
+ BigInteger x = spec.getX();
+ return new DSSPrivateKey(Registry.PKCS8_ENCODING_ID, p, q, g, x);
+ }
+
+ /**
+ * @param spec an instance of {@link RSAPrivateCrtKeySpec} to decode.
+ * @return an instance of {@link GnuRSAPrivateKey} constructed from the
+ * information in the designated key-specification.
+ */
+ private PrivateKey decodeRSAPrivateKey(RSAPrivateCrtKeySpec spec)
+ {
+ BigInteger n = spec.getModulus();
+ BigInteger e = spec.getPublicExponent();
+ BigInteger d = spec.getPrivateExponent();
+ BigInteger p = spec.getPrimeP();
+ BigInteger q = spec.getPrimeQ();
+ BigInteger dP = spec.getPrimeExponentP();
+ BigInteger dQ = spec.getPrimeExponentQ();
+ BigInteger qInv = spec.getCrtCoefficient();
+ return new GnuRSAPrivateKey(Registry.PKCS8_ENCODING_ID,
+ n, e, d, p, q, dP, dQ, qInv);
+ }
+
+ /**
+ * @param spec an instance of {@link DHPrivateKeySpec} to decode.
+ * @return an instance of a {@link DHPrivateKey} constructed from the
+ * information in the designated key-specification.
+ * @throws InvalidKeySpecException if no concrete implementation of the
+ * {@link DHPrivateKey} interface exists at run-time, or if an
+ * exception occurs during its instantiation.
+ */
+ private DHPrivateKey decodeDHPrivateKey(DHPrivateKeySpec spec)
+ throws InvalidKeySpecException
+ {
+ BigInteger p = spec.getP();
+ BigInteger g = spec.getG();
+ BigInteger x = spec.getX();
+ Object[] params = new Object[] {new Integer(Registry.PKCS8_ENCODING_ID),
+ null, p, g, x};
+ Object obj = invokeConstructor("gnu.javax.crypto.key.dh.GnuDHPrivateKey",
+ params);
+ return (DHPrivateKey) obj;
+ }
+
+ /**
+ * @param encoded the bytes to decode.
+ * @return an instance of a {@link DHPrivateKey} constructed from the
+ * information in the designated key-specification.
+ * @throws InvalidKeySpecException if no concrete implementation of the
+ * {@link DHPrivateKey} interface exists at run-time, or if an
+ * exception occurs during its instantiation.
+ */
+ private DHPrivateKey decodeDHPrivateKey(byte[] encoded)
+ throws InvalidKeySpecException
+ {
+ Object obj = invokeValueOf("gnu.javax.crypto.key.dh.GnuDHPrivateKey",
+ encoded);
+ return (DHPrivateKey) obj;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java b/libjava/classpath/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java
new file mode 100644
index 00000000000..60268299188
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java
@@ -0,0 +1,109 @@
+/* KeyPairGeneratorAdapter.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.key.IKeyPairGenerator;
+import gnu.java.security.key.KeyPairGeneratorFactory;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * The implementation of a generic {@link java.security.KeyPairGenerator}
+ * adapter class to wrap gnu.crypto keypair generator instances.<p>
+ *
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
+ * {@link java.security.KeyPairGenerator} class, which is used to generate pairs
+ * of public and private keys.<p>
+ *
+ * All the abstract methods in the {@link java.security.KeyPairGeneratorSpi}
+ * class are implemented by this class and all its sub-classes.<p>
+ *
+ * In case the client does not explicitly initialize the KeyPairGenerator (via
+ * a call to an <code>initialize()</code> method), the GNU Crypto provider
+ * supplies (and document) default values to be used. For example, the GNU
+ * Crypto provider uses a default <i>modulus</i> size (keysize) of 1024 bits for
+ * the DSS (Digital Signature Standard) a.k.a <i>DSA</i>.<p>
+ *
+ * @version $Revision: 1.3 $
+ */
+public abstract class KeyPairGeneratorAdapter extends KeyPairGenerator
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying keypair instance. */
+ protected IKeyPairGenerator adaptee;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial protected constructor.
+ *
+ * @param kpgName the canonical name of the keypair generator algorithm.
+ */
+ protected KeyPairGeneratorAdapter(String kpgName)
+ {
+ super(kpgName);
+
+ this.adaptee = KeyPairGeneratorFactory.getInstance(kpgName);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // java.security.KeyPairGeneratorSpi interface implementation
+ // -------------------------------------------------------------------------
+
+ public abstract void initialize(int keysize, SecureRandom random);
+
+ public abstract void initialize(AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException;
+
+ public KeyPair generateKeyPair()
+ {
+ return adaptee.generate();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/MD2withRSA.java b/libjava/classpath/gnu/java/security/jce/sig/MD2withRSA.java
new file mode 100644
index 00000000000..353be218555
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/MD2withRSA.java
@@ -0,0 +1,56 @@
+/* MD2WithRSA.java -- RSA PKCS1 with MD2 JCE signature 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
+
+/**
+ * A JCE Adapter for the RSA PKCS1 (v1.5) signature with MD2 hash and X.509
+ * encoding format.
+ */
+public class MD2withRSA
+ extends SignatureAdapter
+{
+ public MD2withRSA()
+ {
+ super(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.MD2_HASH,
+ new RSAPKCS1V1_5SignatureX509Codec());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/MD5withRSA.java b/libjava/classpath/gnu/java/security/jce/sig/MD5withRSA.java
new file mode 100644
index 00000000000..42c481b0a6d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/MD5withRSA.java
@@ -0,0 +1,56 @@
+/* MD5withRSA.java -- RSA PKCS1 with MD5 JCE signature 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
+
+/**
+ * A JCE Adapter for the RSA PKCS1 (v1.5) signature with MD5 hash and X.509
+ * encoding format.
+ */
+public class MD5withRSA
+ extends SignatureAdapter
+{
+ public MD5withRSA()
+ {
+ super(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.MD5_HASH,
+ new RSAPKCS1V1_5SignatureX509Codec());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/RSAKeyFactory.java b/libjava/classpath/gnu/java/security/jce/sig/RSAKeyFactory.java
new file mode 100644
index 00000000000..fecf54cb8e9
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/RSAKeyFactory.java
@@ -0,0 +1,265 @@
+/* RSAKeyFactory.java -- RSA 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.rsa.GnuRSAPrivateKey;
+import gnu.java.security.key.rsa.GnuRSAPublicKey;
+import gnu.java.security.key.rsa.RSAKeyPairPKCS8Codec;
+import gnu.java.security.key.rsa.RSAKeyPairX509Codec;
+
+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.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPrivateKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+public class RSAKeyFactory
+ extends KeyFactorySpi
+{
+ // implicit 0-arguments constructor
+
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof RSAPublicKeySpec)
+ {
+ RSAPublicKeySpec spec = (RSAPublicKeySpec) keySpec;
+ BigInteger n = spec.getModulus();
+ BigInteger e = spec.getPublicExponent();
+ return new GnuRSAPublicKey(Registry.X509_ENCODING_ID, n, e);
+ }
+
+ if (keySpec instanceof X509EncodedKeySpec)
+ {
+ X509EncodedKeySpec spec = (X509EncodedKeySpec) keySpec;
+ byte[] encoded = spec.getEncoded();
+ PublicKey result;
+ try
+ {
+ result = new RSAKeyPairX509Codec().decodePublicKey(encoded);
+ }
+ 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 RSAPrivateCrtKeySpec)
+ {
+ RSAPrivateCrtKeySpec spec = (RSAPrivateCrtKeySpec) keySpec;
+ BigInteger n = spec.getModulus();
+ BigInteger e = spec.getPublicExponent();
+ BigInteger d = spec.getPrivateExponent();
+ BigInteger p = spec.getPrimeP();
+ BigInteger q = spec.getPrimeQ();
+ BigInteger dP = spec.getPrimeExponentP();
+ BigInteger dQ = spec.getPrimeExponentQ();
+ BigInteger qInv = spec.getCrtCoefficient();
+ return new GnuRSAPrivateKey(Registry.PKCS8_ENCODING_ID,
+ n, e, d, p, q, dP, dQ, qInv);
+ }
+
+// if (keySpec instanceof RSAPrivateKeySpec)
+// {
+// RSAPrivateKeySpec spec = (RSAPrivateKeySpec) keySpec;
+// BigInteger n = spec.getModulus();
+// BigInteger d = spec.getPrivateExponent();
+// return new GnuRSAPrivateKey(Registry.PKCS8_ENCODING_ID,
+// n, null, d, null, null, null, null, null);
+// }
+
+ if (keySpec instanceof PKCS8EncodedKeySpec)
+ {
+ PKCS8EncodedKeySpec spec = (PKCS8EncodedKeySpec) keySpec;
+ byte[] encoded = spec.getEncoded();
+ PrivateKey result;
+ try
+ {
+ result = new RSAKeyPairPKCS8Codec().decodePrivateKey(encoded);
+ }
+ 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 RSAPublicKey)
+ {
+ if (keySpec.isAssignableFrom(RSAPublicKeySpec.class))
+ {
+ RSAPublicKey rsaKey = (RSAPublicKey) key;
+ BigInteger n = rsaKey.getModulus();
+ BigInteger e = rsaKey.getPublicExponent();
+ return new RSAPublicKeySpec(n, e);
+ }
+
+ if (keySpec.isAssignableFrom(X509EncodedKeySpec.class))
+ {
+ if (key instanceof GnuRSAPublicKey)
+ {
+ GnuRSAPublicKey rsaKey = (GnuRSAPublicKey) key;
+ byte[] encoded = rsaKey.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 RSAPrivateCrtKey)
+ && keySpec.isAssignableFrom(RSAPrivateCrtKeySpec.class))
+ {
+ RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
+ BigInteger n = rsaKey.getModulus();
+ BigInteger e = rsaKey.getPublicExponent();
+ BigInteger d = rsaKey.getPrivateExponent();
+ BigInteger p = rsaKey.getPrimeP();
+ BigInteger q = rsaKey.getPrimeQ();
+ BigInteger dP = rsaKey.getPrimeExponentP();
+ BigInteger dQ = rsaKey.getPrimeExponentQ();
+ BigInteger qInv = rsaKey.getCrtCoefficient();
+ return new RSAPrivateCrtKeySpec(n, e, d, p, q, dP, dQ, qInv);
+ }
+
+ if ((key instanceof RSAPrivateKey)
+ && keySpec.isAssignableFrom(RSAPrivateKeySpec.class))
+ {
+ RSAPrivateKey rsaKey = (RSAPrivateKey) key;
+ BigInteger n = rsaKey.getModulus();
+ BigInteger d = rsaKey.getPrivateExponent();
+ return new RSAPrivateKeySpec(n, d);
+ }
+
+ if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class))
+ {
+ if (key instanceof GnuRSAPrivateKey)
+ {
+ GnuRSAPrivateKey rsaKey = (GnuRSAPrivateKey) key;
+ byte[] encoded = rsaKey.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("Wrong key type or unsupported key specification");
+ }
+
+ protected Key engineTranslateKey(Key key) throws InvalidKeyException
+ {
+ if ((key instanceof GnuRSAPublicKey) || (key instanceof GnuRSAPrivateKey))
+ return key;
+
+ if (key instanceof RSAPublicKey)
+ {
+ RSAPublicKey rsaKey = (RSAPublicKey) key;
+ BigInteger n = rsaKey.getModulus();
+ BigInteger e = rsaKey.getPublicExponent();
+ return new GnuRSAPublicKey(Registry.X509_ENCODING_ID, n, e);
+ }
+
+ if (key instanceof RSAPrivateCrtKey)
+ {
+ RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
+ BigInteger n = rsaKey.getModulus();
+ BigInteger e = rsaKey.getPublicExponent();
+ BigInteger d = rsaKey.getPrivateExponent();
+ BigInteger p = rsaKey.getPrimeP();
+ BigInteger q = rsaKey.getPrimeQ();
+ BigInteger dP = rsaKey.getPrimeExponentP();
+ BigInteger dQ = rsaKey.getPrimeExponentQ();
+ BigInteger qInv = rsaKey.getCrtCoefficient();
+ return new GnuRSAPrivateKey(Registry.PKCS8_ENCODING_ID,
+ n, e, d, p, q, dP, dQ, qInv);
+ }
+
+// if (key instanceof RSAPrivateKey)
+// {
+// RSAPrivateKey rsaKey = (RSAPrivateKey) key;
+// BigInteger n = rsaKey.getModulus();
+// BigInteger d = rsaKey.getPrivateExponent();
+// return new GnuRSAPrivateKey(Registry.PKCS8_ENCODING_ID,
+// n, null, d, null, null, null, null, null);
+// }
+
+ throw new InvalidKeyException("Unsupported key type");
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java b/libjava/classpath/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java
new file mode 100644
index 00000000000..24dc7c50177
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/RSAKeyPairGeneratorSpi.java
@@ -0,0 +1,115 @@
+/* RSAKeyPairGeneratorSpi.java -- JCE RSA KeyPairGenerator Adapter
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.rsa.RSAKeyPairGenerator;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.RSAKeyGenParameterSpec;
+import java.util.HashMap;
+
+/**
+ * The implementation of a {@link java.security.KeyPairGenerator} adapter class
+ * to wrap gnu.crypto RSA keypair generator instances.<p>
+ *
+ * In case the client does not explicitly initialize the KeyPairGenerator (via
+ * a call to an <code>initialize()</code> method), the GNU Crypto provider
+ * uses a default <i>modulus</i> size (keysize) of 1024 bits.<p>
+ */
+public class RSAKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RSAKeyPairGeneratorSpi()
+ {
+ super(Registry.RSA_KPG);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public void initialize(int keysize, SecureRandom random)
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(RSAKeyPairGenerator.MODULUS_LENGTH, new Integer(keysize));
+ if (random != null)
+ {
+ attributes.put(RSAKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+ }
+
+ attributes.put(RSAKeyPairGenerator.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 RSAKeyGenParameterSpec))
+ {
+ throw new InvalidAlgorithmParameterException("params");
+ }
+
+ attributes.put(RSAKeyPairGenerator.RSA_PARAMETERS, params);
+ }
+
+ if (random != null)
+ {
+ attributes.put(RSAKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+ }
+
+ attributes.put(RSAKeyPairGenerator.PREFERRED_ENCODING_FORMAT,
+ new Integer(Registry.ASN1_ENCODING_ID));
+ adaptee.setup(attributes);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java b/libjava/classpath/gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java
new file mode 100644
index 00000000000..e44b8adf14d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/RSAPSSRawSignatureSpi.java
@@ -0,0 +1,69 @@
+/* RSAPSSRawSignatureSpi.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.RSAPSSSignatureRawCodec;
+
+/**
+ * The implementation of <i>Service Provider Interface</i> (<b>SPI</b>) adapter
+ * for the RSA-PSS signature scheme, encoded and/or decoded in RAW format.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RSAPSSRawSignatureSpi extends SignatureAdapter
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public RSAPSSRawSignatureSpi()
+ {
+ super(Registry.RSA_PSS_SIG, new RSAPSSSignatureRawCodec());
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/SHA160withDSS.java b/libjava/classpath/gnu/java/security/jce/sig/SHA160withDSS.java
new file mode 100644
index 00000000000..c55139f4658
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/SHA160withDSS.java
@@ -0,0 +1,54 @@
+/* SHA160withDSS.java -- JCE Adapter for DSS with SHA1 signatures
+ 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.dss.DSSSignatureX509Codec;
+
+/**
+ * A JCE Adapter for providing X.509 formatted DSS with SHA1 signatures.
+ */
+public class SHA160withDSS
+ extends SignatureAdapter
+{
+ public SHA160withDSS()
+ {
+ super(Registry.DSS_SIG, new DSSSignatureX509Codec());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/SHA160withRSA.java b/libjava/classpath/gnu/java/security/jce/sig/SHA160withRSA.java
new file mode 100644
index 00000000000..d3b2054e0ea
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/SHA160withRSA.java
@@ -0,0 +1,56 @@
+/* SHA160withRSA.java -- RSA PKCS1 with SHA160 JCE signature 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
+
+/**
+ * A JCE Adapter for the RSA PKCS1 (v1.5) signature with SHA160 hash and X.509
+ * encoding format.
+ */
+public class SHA160withRSA
+ extends SignatureAdapter
+{
+ public SHA160withRSA()
+ {
+ super(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.SHA160_HASH,
+ new RSAPKCS1V1_5SignatureX509Codec());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/SHA256withRSA.java b/libjava/classpath/gnu/java/security/jce/sig/SHA256withRSA.java
new file mode 100644
index 00000000000..d21888b5993
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/SHA256withRSA.java
@@ -0,0 +1,56 @@
+/* SHA256withRSA.java -- RSA PKCS1 with SHA256 JCE signature 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
+
+/**
+ * A JCE Adapter for the RSA PKCS1 (v1.5) signature with SHA256 hash and X.509
+ * encoding format.
+ */
+public class SHA256withRSA
+ extends SignatureAdapter
+{
+ public SHA256withRSA()
+ {
+ super(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.SHA256_HASH,
+ new RSAPKCS1V1_5SignatureX509Codec());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/SHA384withRSA.java b/libjava/classpath/gnu/java/security/jce/sig/SHA384withRSA.java
new file mode 100644
index 00000000000..5495ec1caa0
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/SHA384withRSA.java
@@ -0,0 +1,56 @@
+/* SHA384withRSA.java -- RSA PKCS1 with SHA384 JCE signature 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
+
+/**
+ * A JCE Adapter for the RSA PKCS1 (v1.5) signature with SHA384 hash and X.509
+ * encoding format.
+ */
+public class SHA384withRSA
+ extends SignatureAdapter
+{
+ public SHA384withRSA()
+ {
+ super(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.SHA384_HASH,
+ new RSAPKCS1V1_5SignatureX509Codec());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/SHA512withRSA.java b/libjava/classpath/gnu/java/security/jce/sig/SHA512withRSA.java
new file mode 100644
index 00000000000..f7632290ab6
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/SHA512withRSA.java
@@ -0,0 +1,56 @@
+/* SHA512withRSA.java -- RSA PKCS1 with SHA512 JCE signature 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.java.security.jce.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
+
+/**
+ * A JCE Adapter for the RSA PKCS1 (v1.5) signature with SHA512 hash and X.509
+ * encoding format.
+ */
+public class SHA512withRSA
+ extends SignatureAdapter
+{
+ public SHA512withRSA()
+ {
+ super(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.SHA512_HASH,
+ new RSAPKCS1V1_5SignatureX509Codec());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/jce/sig/SignatureAdapter.java b/libjava/classpath/gnu/java/security/jce/sig/SignatureAdapter.java
new file mode 100644
index 00000000000..6cb7c7c7128
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/jce/sig/SignatureAdapter.java
@@ -0,0 +1,263 @@
+/* SignatureAdapter.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.jce.sig;
+
+import gnu.java.security.sig.BaseSignature;
+import gnu.java.security.sig.ISignature;
+import gnu.java.security.sig.ISignatureCodec;
+import gnu.java.security.sig.SignatureFactory;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.SignatureException;
+import java.security.SignatureSpi;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.HashMap;
+import java.util.logging.Logger;
+
+/**
+ * The implementation of a generic {@link java.security.Signature} adapter class
+ * to wrap gnu.crypto signature instances.<p>
+ *
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
+ * {@link java.security.Signature} class, which provides the functionality of a
+ * digital signature algorithm. Digital signatures are used for authentication
+ * and integrity assurance of digital data.<p>
+ *
+ * All the abstract methods in the {@link java.security.SignatureSpi} class are
+ * implemented by this class and all its sub-classes.<p>
+ *
+ * All the implementations which subclass this object, and which are serviced by
+ * the GNU Crypto provider implement the {@link java.lang.Cloneable} interface.<p>
+ *
+ * @version $Revision: 1.2 $
+ */
+class SignatureAdapter extends SignatureSpi implements Cloneable
+{
+ private static final Logger log = Logger.getLogger(SignatureAdapter.class.getName());
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Our underlying signature instance. */
+ private ISignature adaptee;
+
+ /** Our underlying signature encoder/decoder engine. */
+ private ISignatureCodec codec;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial protected constructor.<p>
+ *
+ * @param sigName the canonical name of the signature scheme.
+ * @param codec the signature codec engine to use with this scheme.
+ */
+ protected SignatureAdapter(String sigName, ISignatureCodec codec)
+ {
+ this(SignatureFactory.getInstance(sigName), codec);
+ }
+
+ /**
+ * Private constructor for cloning purposes.<p>
+ *
+ * @param adaptee a clone of the underlying signature scheme instance.
+ * @param codec the signature codec engine to use with this scheme.
+ */
+ private SignatureAdapter(ISignature adaptee, ISignatureCodec codec)
+ {
+ super();
+
+ this.adaptee = adaptee;
+ this.codec = codec;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // java.security.SignatureSpi interface implementation
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new SignatureAdapter((ISignature) adaptee.clone(), codec);
+ }
+
+ public void engineInitVerify(PublicKey publicKey) throws InvalidKeyException
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(BaseSignature.VERIFIER_KEY, publicKey);
+ try
+ {
+ adaptee.setupVerify(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new InvalidKeyException(String.valueOf(x));
+ }
+ }
+
+ public void engineInitSign(PrivateKey privateKey) throws InvalidKeyException
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(BaseSignature.SIGNER_KEY, privateKey);
+ try
+ {
+ adaptee.setupSign(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new InvalidKeyException(String.valueOf(x));
+ }
+ }
+
+ public void engineInitSign(PrivateKey privateKey, SecureRandom random)
+ throws InvalidKeyException
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(BaseSignature.SIGNER_KEY, privateKey);
+ attributes.put(BaseSignature.SOURCE_OF_RANDOMNESS, random);
+ try
+ {
+ adaptee.setupSign(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new InvalidKeyException(String.valueOf(x));
+ }
+ }
+
+ public void engineUpdate(byte b) throws SignatureException
+ {
+ try
+ {
+ adaptee.update(b);
+ }
+ catch (IllegalStateException x)
+ {
+ throw new SignatureException(String.valueOf(x));
+ }
+ }
+
+ public void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException
+ {
+ try
+ {
+ adaptee.update(b, off, len);
+ }
+ catch (IllegalStateException x)
+ {
+ throw new SignatureException(String.valueOf(x));
+ }
+ }
+
+ public byte[] engineSign() throws SignatureException
+ {
+ Object signature = null;
+ try
+ {
+ signature = adaptee.sign();
+ }
+ catch (IllegalStateException x)
+ {
+ throw new SignatureException(String.valueOf(x));
+ }
+
+ byte[] result = codec.encodeSignature(signature);
+ return result;
+ }
+
+ public int engineSign(byte[] outbuf, int offset, int len)
+ throws SignatureException
+ {
+ byte[] signature = this.engineSign();
+ int result = signature.length;
+ if (result > len)
+ {
+ throw new SignatureException("len");
+ }
+
+ System.arraycopy(signature, 0, outbuf, offset, result);
+ return result;
+ }
+
+ public boolean engineVerify(byte[] sigBytes) throws SignatureException
+ {
+ log.entering("SignatureAdapter", "engineVerify");
+
+ Object signature = codec.decodeSignature(sigBytes);
+ boolean result = false;
+ try
+ {
+ result = adaptee.verify(signature);
+ }
+ catch (IllegalStateException x)
+ {
+ throw new SignatureException(String.valueOf(x));
+ }
+
+ log.exiting("SignatureAdapter", "engineVerify", new Boolean(result));
+ return result;
+ }
+
+ // Deprecated. Replaced by engineSetParameter.
+ public void engineSetParameter(String param, Object value)
+ throws InvalidParameterException
+ {
+ throw new InvalidParameterException("deprecated");
+ }
+
+ public void engineSetParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ }
+
+ // Deprecated
+ public Object engineGetParameter(String param)
+ throws InvalidParameterException
+ {
+ throw new InvalidParameterException("deprecated");
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/IKeyPairCodec.java b/libjava/classpath/gnu/java/security/key/IKeyPairCodec.java
new file mode 100644
index 00000000000..c64f928574b
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/IKeyPairCodec.java
@@ -0,0 +1,132 @@
+/* IKeyPairCodec.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key;
+
+import gnu.java.security.Registry;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>The visible methods of an object that knows how to encode and decode
+ * cryptographic asymmetric keypairs. Codecs are useful for (a) externalising
+ * public and private keys for storage and on-the-wire transmission, as well as
+ * (b) re-creating their internal Java representation from external sources.</p>
+ *
+ * @version $Revision: 1.2 $
+ */
+public interface IKeyPairCodec
+{
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** Constant identifying the <i>Raw</i> encoding format. */
+ int RAW_FORMAT = Registry.RAW_ENCODING_ID;
+
+ /** Constant identifying the <i>X.509</i> encoding format. */
+ int X509_FORMAT = Registry.X509_ENCODING_ID;
+
+ /** Constant identifying the <i>PKCS#8</i> encoding format. */
+ int PKCS8_FORMAT = Registry.PKCS8_ENCODING_ID;
+
+ /**
+ * Constant identifying the <i>ASN.1</i> encoding format: a combined encoding
+ * of <i>X.509</i> for public keys, and <i>PKCS#8</i> for private ones.
+ */
+ int ASN1_FORMAT = Registry.ASN1_ENCODING_ID;
+
+ // Method(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the unique identifier (within this library) of the format used
+ * to externalise public and private keys.</p>
+ *
+ * @return the identifier of the format, the object supports.
+ */
+ int getFormatID();
+
+ /**
+ * <p>Encodes an instance of a public key for storage or transmission purposes.</p>
+ *
+ * @param key the non-null key to encode.
+ * @return a byte sequence representing the encoding of the designated key
+ * according to the format supported by this codec.
+ * @exception IllegalArgumentException if the designated key is not supported
+ * by this codec.
+ */
+ byte[] encodePublicKey(PublicKey key);
+
+ /**
+ * <p>Encodes an instance of a private key for storage or transmission purposes.</p>
+ *
+ * @param key the non-null key to encode.
+ * @return a byte sequence representing the encoding of the designated key
+ * according to the format supported by this codec.
+ * @exception IllegalArgumentException if the designated key is not supported
+ * by this codec.
+ */
+ byte[] encodePrivateKey(PrivateKey key);
+
+ /**
+ * <p>Decodes an instance of an external public key into its native Java
+ * representation.</p>
+ *
+ * @param input the source of the externalised key to decode.
+ * @return a concrete instance of a public key, reconstructed from the
+ * designated input.
+ * @exception IllegalArgumentException if the designated input does not
+ * contain a known representation of a public key for the format supported by
+ * the concrete codec.
+ */
+ PublicKey decodePublicKey(byte[] input);
+
+ /**
+ * <p>Decodes an instance of an external private key into its native Java
+ * representation.</p>
+ *
+ * @param input the source of the externalised key to decode.
+ * @return a concrete instance of a private key, reconstructed from the
+ * designated input.
+ * @exception IllegalArgumentException if the designated input does not
+ * contain a known representation of a private key for the format supported
+ * by the concrete codec.
+ */
+ PrivateKey decodePrivateKey(byte[] input);
+}
diff --git a/libjava/classpath/gnu/java/security/key/IKeyPairGenerator.java b/libjava/classpath/gnu/java/security/key/IKeyPairGenerator.java
new file mode 100644
index 00000000000..219863d33eb
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/IKeyPairGenerator.java
@@ -0,0 +1,82 @@
+/* IKeyPairGenerator.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key;
+
+import java.security.KeyPair;
+import java.util.Map;
+
+/**
+ * The visible methods of every asymmetric keypair generator.<p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface IKeyPairGenerator
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns the canonical name of this keypair generator.<p>
+ *
+ * @return the canonical name of this instance.
+ */
+ String name();
+
+ /**
+ * [Re]-initialises this instance for use with a given set of attributes.<p>
+ *
+ * @param attributes a map of name/value pairs to use for setting up the
+ * instance.
+ * @exception IllegalArgumentException if at least one of the mandatory
+ * attributes is missing or an invalid value was specified.
+ */
+ void setup(Map attributes);
+
+ /**
+ * Generates a new keypair based on the attributes used to configure the
+ * instance.
+ *
+ * @return a new keypair.
+ */
+ KeyPair generate();
+}
diff --git a/libjava/classpath/gnu/java/security/key/KeyPairCodecFactory.java b/libjava/classpath/gnu/java/security/key/KeyPairCodecFactory.java
new file mode 100644
index 00000000000..1a8b8aa0388
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/KeyPairCodecFactory.java
@@ -0,0 +1,362 @@
+/* KeyPairCodecFactory.java --
+ Copyright 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSKeyPairPKCS8Codec;
+import gnu.java.security.key.dss.DSSKeyPairRawCodec;
+import gnu.java.security.key.dss.DSSKeyPairX509Codec;
+import gnu.java.security.key.dss.DSSPrivateKey;
+import gnu.java.security.key.dss.DSSPublicKey;
+import gnu.java.security.key.rsa.GnuRSAPrivateKey;
+import gnu.java.security.key.rsa.GnuRSAPublicKey;
+import gnu.java.security.key.rsa.RSAKeyPairPKCS8Codec;
+import gnu.java.security.key.rsa.RSAKeyPairRawCodec;
+import gnu.java.security.key.rsa.RSAKeyPairX509Codec;
+import gnu.java.security.util.FormatUtil;
+
+import java.lang.reflect.Constructor;
+import java.security.Key;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A <i>Factory</i> class to instantiate key encoder/decoder instances.
+ */
+public class KeyPairCodecFactory
+{
+ private static Set names;
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private KeyPairCodecFactory()
+ {
+ super();
+ }
+
+ /**
+ * Returns the appropriate codec given a composed key-pair generator algorithm
+ * and an encoding format. A composed name is formed by the concatenation of
+ * the canonical key-pair algorithm name, the forward slash character
+ * <code>/</code> and the canonical name of the encoding format.
+ * <p>
+ * <b>IMPORTANT</b>: For backward compatibility, when the encoding format
+ * name is missing, the Raw encoding format is assumed. When this is the case
+ * the trailing forward slash is discarded from the name.
+ *
+ * @param name the case-insensitive key codec name.
+ * @return an instance of the keypair codec, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairCodec getInstance(String name)
+ {
+ if (name == null)
+ return null;
+
+ name = name.trim();
+ if (name.length() == 0)
+ return null;
+
+ if (name.startsWith("/"))
+ return null;
+
+ if (name.endsWith("/"))
+ return getInstance(name.substring(0, name.length() - 1),
+ Registry.RAW_ENCODING_ID);
+
+ int i = name.indexOf("/");
+ if (i == -1)
+ return getInstance(name, Registry.RAW_ENCODING_ID);
+
+ String kpgName = name.substring(0, i);
+ String formatName = name.substring(i + 1);
+ return getInstance(kpgName, formatName);
+ }
+
+ /**
+ * Returns an instance of a keypair codec given the canonical name of the
+ * key-pair algorithm, and the name of the encoding format to use when
+ * externalizing the keys.
+ *
+ * @param name the case-insensitive key-pair algorithm name.
+ * @param format the name of the encoding format to use when externalizing the
+ * keys generated by the key-pair algorithm.
+ * @return an instance of the key-pair codec, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairCodec getInstance(String name, String format)
+ {
+ int formatID = FormatUtil.getFormatID(format);
+ if (formatID == 0)
+ return null;
+
+ return getInstance(name, formatID);
+ }
+
+ /**
+ * Returns an instance of a keypair codec given the canonical name of the
+ * key-pair algorithm, and the identifier of the format to use when
+ * externalizing the keys.
+ *
+ * @param name the case-insensitive key-pair algorithm name.
+ * @param formatID the identifier of the format to use when externalizing the
+ * keys generated by the key-pair algorithm.
+ * @return an instance of the key-pair codec, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairCodec getInstance(String name, int formatID)
+ {
+ if (name == null)
+ return null;
+
+ name = name.trim();
+ switch (formatID)
+ {
+ case Registry.RAW_ENCODING_ID:
+ return getRawCodec(name);
+ case Registry.X509_ENCODING_ID:
+ return getX509Codec(name);
+ case Registry.PKCS8_ENCODING_ID:
+ return getPKCS8Codec(name);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns an instance of a keypair codec given a key.
+ *
+ * @param key the key to encode.
+ * @return an instance of the keypair codec, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairCodec getInstance(Key key)
+ {
+ if (key == null)
+ return null;
+
+ String format = key.getFormat();
+ int formatID = FormatUtil.getFormatID(format);
+ if (formatID == 0)
+ return null;
+
+ switch (formatID)
+ {
+ case Registry.RAW_ENCODING_ID:
+ return getRawCodec(key);
+ case Registry.X509_ENCODING_ID:
+ return getX509Codec(key);
+ case Registry.PKCS8_ENCODING_ID:
+ return getPKCS8Codec(key);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a {@link Set} of supported key-pair codec names.
+ *
+ * @return a {@link Set} of the names of supported key-pair codec (Strings).
+ */
+ public static synchronized final Set getNames()
+ {
+ if (names == null)
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.DSS_KPG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
+ hs.add(Registry.DSS_KPG + "/" + Registry.X509_ENCODING_SORT_NAME);
+ hs.add(Registry.DSS_KPG + "/" + Registry.PKCS8_ENCODING_SHORT_NAME);
+ hs.add(Registry.RSA_KPG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
+ hs.add(Registry.RSA_KPG + "/" + Registry.X509_ENCODING_SORT_NAME);
+ hs.add(Registry.RSA_KPG + "/" + Registry.PKCS8_ENCODING_SHORT_NAME);
+ hs.add(Registry.DH_KPG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
+ hs.add(Registry.SRP_KPG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
+
+ names = Collections.unmodifiableSet(hs);
+ }
+
+ return names;
+ }
+
+ private static IKeyPairCodec makeInstance (String clazz)
+ {
+ try
+ {
+ Class c = Class.forName (clazz);
+ Constructor ctor = c.getConstructor (new Class[0]);
+ return (IKeyPairCodec) ctor.newInstance (new Object[0]);
+ }
+ catch (Exception x)
+ {
+ IllegalArgumentException iae =
+ new IllegalArgumentException ("strong crypto key codec not available: "
+ + clazz);
+ iae.initCause (x);
+ throw iae;
+ }
+ }
+
+ private static boolean matches (Object o, String clazz)
+ {
+ try
+ {
+ Class c = Class.forName (clazz);
+ return c.isAssignableFrom (o.getClass ());
+ }
+ catch (Exception x)
+ {
+ // Can't match.
+ return false;
+ }
+ }
+
+ /**
+ * @param name the trimmed name of a key-pair algorithm.
+ * @return a Raw format codec for the designated key-pair algorithm, or
+ * <code>null</code> if none exists.
+ */
+ private static IKeyPairCodec getRawCodec(String name)
+ {
+ IKeyPairCodec result = null;
+ if (name.equalsIgnoreCase(Registry.DSA_KPG)
+ || name.equals(Registry.DSS_KPG))
+ result = new DSSKeyPairRawCodec();
+ else if (name.equalsIgnoreCase(Registry.RSA_KPG))
+ result = new RSAKeyPairRawCodec();
+ else if (name.equalsIgnoreCase(Registry.DH_KPG))
+ result = makeInstance("gnu.javax.crypto.key.dh.DHKeyPairRawCodec");
+ else if (name.equalsIgnoreCase(Registry.SRP_KPG))
+ result = makeInstance("gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec");
+
+ return result;
+ }
+
+ /**
+ * @param name the trimmed name of a key-pair algorithm.
+ * @return a X.509 format codec for the designated key-pair algorithm, or
+ * <code>null</code> if none exists.
+ */
+ private static IKeyPairCodec getX509Codec(String name)
+ {
+ IKeyPairCodec result = null;
+ if (name.equalsIgnoreCase(Registry.DSA_KPG)
+ || name.equals(Registry.DSS_KPG))
+ result = new DSSKeyPairX509Codec();
+ else if (name.equalsIgnoreCase(Registry.RSA_KPG))
+ result = new RSAKeyPairX509Codec();
+ else if (name.equalsIgnoreCase(Registry.DH_KPG))
+ result = makeInstance("gnu.javax.crypto.key.dh.DHKeyPairX509Codec");
+
+ return result;
+ }
+
+ /**
+ * @param name the trimmed name of a key-pair algorithm.
+ * @return a PKCS#8 format codec for the designated key-pair algorithm, or
+ * <code>null</code> if none exists.
+ */
+ private static IKeyPairCodec getPKCS8Codec(String name)
+ {
+ IKeyPairCodec result = null;
+ if (name.equalsIgnoreCase(Registry.DSA_KPG)
+ || name.equals(Registry.DSS_KPG))
+ result = new DSSKeyPairPKCS8Codec();
+ else if (name.equalsIgnoreCase(Registry.RSA_KPG))
+ result = new RSAKeyPairPKCS8Codec();
+ else if (name.equalsIgnoreCase(Registry.DH_KPG))
+ result = makeInstance("gnu.javax.crypto.key.dh.DHKeyPairPKCS8Codec");
+
+ return result;
+ }
+
+ /**
+ * @param key a {@link Key} for which we want to return a Raw codec.
+ * @return the Raw codec corresponding to the key, or <code>null</code> if
+ * none exists for this key.
+ */
+ private static IKeyPairCodec getRawCodec(Key key)
+ {
+ IKeyPairCodec result = null;
+ if ((key instanceof DSSPublicKey) || (key instanceof DSSPrivateKey))
+ result = new DSSKeyPairRawCodec();
+ else if ((key instanceof GnuRSAPublicKey)
+ || (key instanceof GnuRSAPrivateKey))
+ result = new RSAKeyPairRawCodec();
+ else if (matches(key, "gnu.javax.crypto.key.dh.GnuDHPublicKey")
+ || matches(key, "gnu.javax.crypto.key.dh.GnuDHPrivateKey"))
+ result = makeInstance("gnu.javax.crypto.key.dh.DHKeyPairRawCodec");
+ else if (matches(key, "gnu.javax.crypto.key.srp6.SRPPublicKey")
+ || matches(key, "gnu.javax.crypto.key.srp6.SRPPrivateKey"))
+ result = makeInstance("gnu.javax.crypto.key.srp6.SRPKeyPairRawCodec");
+
+ return result;
+ }
+
+ /**
+ * @param key a {@link Key} for which we want to return an X.509 codec.
+ * @return the X.509 codec corresponding to the key, or <code>null</code> if
+ * none exists for this key.
+ */
+ private static IKeyPairCodec getX509Codec(Key key)
+ {
+ IKeyPairCodec result = null;
+ if (key instanceof DSSPublicKey)
+ result = new DSSKeyPairX509Codec();
+ else if (key instanceof GnuRSAPublicKey)
+ result = new RSAKeyPairX509Codec();
+
+ return result;
+ }
+
+ /**
+ * @param key a {@link Key} for which we want to return a PKCS#8 codec.
+ * @return the PKCS#8 codec corresponding to the key, or <code>null</code> if
+ * none exists for this key.
+ */
+ private static IKeyPairCodec getPKCS8Codec(Key key)
+ {
+ IKeyPairCodec result = null;
+ if (key instanceof DSSPrivateKey)
+ result = new DSSKeyPairPKCS8Codec();
+ else if (key instanceof GnuRSAPrivateKey)
+ result = new RSAKeyPairPKCS8Codec();
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/KeyPairGeneratorFactory.java b/libjava/classpath/gnu/java/security/key/KeyPairGeneratorFactory.java
new file mode 100644
index 00000000000..edcc186e2c7
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/KeyPairGeneratorFactory.java
@@ -0,0 +1,148 @@
+/* KeyPairGeneratorFactory.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSKeyPairGenerator;
+import gnu.java.security.key.rsa.RSAKeyPairGenerator;
+
+import java.lang.reflect.Constructor;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p>A Factory to instantiate asymmetric keypair generators.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class KeyPairGeneratorFactory
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private KeyPairGeneratorFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a keypair generator given its name.</p>
+ *
+ * @param name the case-insensitive key generator name.
+ * @return an instance of the keypair generator, or <code>null</code> if none
+ * found.
+ */
+ public static IKeyPairGenerator getInstance(String name)
+ {
+ if (name == null)
+ {
+ return null;
+ }
+
+ name = name.trim();
+ IKeyPairGenerator result = null;
+ if (name.equalsIgnoreCase(Registry.DSA_KPG)
+ || name.equals(Registry.DSS_KPG))
+ {
+ result = new DSSKeyPairGenerator();
+ }
+ else if (name.equalsIgnoreCase(Registry.RSA_KPG))
+ {
+ result = new RSAKeyPairGenerator();
+ }
+ else if (name.equalsIgnoreCase(Registry.DH_KPG))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.dh.GnuDHKeyPairGenerator");
+ }
+ else if (name.equalsIgnoreCase(Registry.SRP_KPG))
+ {
+ result = makeInstance ("gnu.javax.crypto.key.srp6.SRPKeyPairGenerator");
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of keypair generator names supported by this
+ * <i>Factory</i>. Those keypair generators may be used in conjunction with
+ * the digital signature schemes with appendix supported by this library.</p>
+ *
+ * @return a {@link Set} of keypair generator names (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.DSS_KPG);
+ hs.add(Registry.RSA_KPG);
+ hs.add(Registry.DH_KPG);
+ hs.add(Registry.SRP_KPG);
+
+ return Collections.unmodifiableSet(hs);
+ }
+
+ private static IKeyPairGenerator makeInstance (String clazz)
+ {
+ try
+ {
+ Class c = Class.forName (clazz);
+ Constructor ctor = c.getConstructor (new Class[0]);
+ return (IKeyPairGenerator) ctor.newInstance (new Object[0]);
+ }
+ catch (Exception x)
+ {
+ IllegalArgumentException iae =
+ new IllegalArgumentException ("strong crypto key pair generator not available: "
+ + clazz);
+ iae.initCause (x);
+ throw iae;
+ }
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/key/dss/DSSKey.java b/libjava/classpath/gnu/java/security/key/dss/DSSKey.java
new file mode 100644
index 00000000000..428cab1e78e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/dss/DSSKey.java
@@ -0,0 +1,182 @@
+/* DSSKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.FormatUtil;
+
+import java.math.BigInteger;
+import java.security.Key;
+import java.security.interfaces.DSAKey;
+import java.security.interfaces.DSAParams;
+import java.security.spec.DSAParameterSpec;
+
+/**
+ * <p>A base asbtract class for both public and private DSS (Digital Signature
+ * Standard) keys. It encapsulates the three DSS numbers: <code>p</code>,
+ * <code>q</code> and <code>g</code>.</p>
+ *
+ * <p>According to the JDK, cryptographic <i>Keys</i> all have a <i>format</i>.
+ * The format used in this implementation is called <i>Raw</i>, and basically
+ * consists of the raw byte sequences of algorithm parameters. The exact order
+ * of the byte sequences and the implementation details are given in each of
+ * the relevant <code>getEncoded()</code> methods of each of the private and
+ * public keys.</p>
+ *
+ * @version $Revision: 1.4 $
+ * @see DSSPrivateKey#getEncoded
+ * @see DSSPublicKey#getEncoded
+ */
+public abstract class DSSKey implements Key, DSAKey
+{
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * A prime modulus, where <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup></code>
+ * for <code>512 &lt;= L &lt;= 1024</code> and <code>L</code> a multiple of
+ * <code>64</code>.
+ */
+ protected final BigInteger p;
+
+ /**
+ * A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup> &lt; q
+ * &lt; 2<sup>160</sup></code>.
+ */
+ protected final BigInteger q;
+
+ /**
+ * <code>g = h<sup>(p-1)</sup>/q mod p</code>, where <code>h</code> is any
+ * integer with <code>1 &lt; h &lt; p - 1</code> such that <code>h<sup>
+ * (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order <code>q mod p
+ * </code>).
+ */
+ protected final BigInteger g;
+
+ /**
+ * 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 p the DSS parameter <code>p</code>.
+ * @param q the DSS parameter <code>q</code>.
+ * @param g the DSS parameter <code>g</code>.
+ */
+ protected DSSKey(int defaultFormat, BigInteger p, BigInteger q, BigInteger g)
+ {
+ super();
+
+ this.defaultFormat = defaultFormat <= 0 ? Registry.RAW_ENCODING_ID
+ : defaultFormat;
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.DSAKey interface implementation ----------------
+
+ public DSAParams getParams()
+ {
+ return new DSAParameterSpec(p, q, g);
+ }
+
+ // java.security.Key interface implementation ------------------------------
+
+ public String getAlgorithm()
+ {
+ return Registry.DSS_KPG;
+ }
+
+ /** @deprecated see getEncoded(int). */
+ public byte[] getEncoded()
+ {
+ return getEncoded(defaultFormat);
+ }
+
+ public String getFormat()
+ {
+ return FormatUtil.getEncodingShortName(defaultFormat);
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link DSAKey} and has the same DSS (Digital Signature Standard) parameter
+ * values as this one.</p>
+ *
+ * @param obj the other non-null DSS key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof DSAKey))
+ {
+ return false;
+ }
+ DSAKey that = (DSAKey) obj;
+ return p.equals(that.getParams().getP())
+ && q.equals(that.getParams().getQ())
+ && g.equals(that.getParams().getG());
+ }
+
+ // abstract methods to be implemented by subclasses ------------------------
+
+ public abstract byte[] getEncoded(int format);
+}
diff --git a/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairGenerator.java b/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairGenerator.java
new file mode 100644
index 00000000000..5aa746147eb
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairGenerator.java
@@ -0,0 +1,445 @@
+/* DSSKeyPairGenerator.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.key.IKeyPairGenerator;
+import 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.security.spec.DSAParameterSpec;
+import java.util.Map;
+
+/**
+ * <p>A key-pair generator for asymetric keys to use in conjunction with the DSS
+ * (Digital Signature Standard).</p>
+ *
+ * References:<br>
+ * <a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature
+ * Standard (DSS)</a>, Federal Information Processing Standards Publication 186.
+ * National Institute of Standards and Technology.
+ */
+public class DSSKeyPairGenerator implements IKeyPairGenerator
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "dss";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The BigInteger constant 2. */
+ private static final BigInteger TWO = new BigInteger("2");
+
+ /** Property name of the length (Integer) of the modulus (p) of a DSS key. */
+ public static final String MODULUS_LENGTH = "gnu.crypto.dss.L";
+
+ /**
+ * Property name of the Boolean indicating wether or not to use default pre-
+ * computed values of <code>p</code>, <code>q</code> and <code>g</code> for
+ * a given modulus length. The ultimate behaviour of this generator with
+ * regard to using pre-computed parameter sets will depend on the value of
+ * this property and of the following one {@link #STRICT_DEFAULTS}:
+ *
+ * <ol>
+ * <li>If this property is {@link Boolean#FALSE} then this generator
+ * will accept being setup for generating parameters for any modulus length
+ * provided the modulus length is between <code>512</code> and
+ * <code>1024</code>, and is of the form <code>512 + 64 * n</code>. In
+ * addition, a new paramter set will always be generated; i.e. no pre-
+ * computed values are used.</li>
+ *
+ * <li>If this property is {@link Boolean#TRUE} and the value of
+ * {@link #STRICT_DEFAULTS} is also {@link Boolean#TRUE} then this generator
+ * will only accept being setup for generating parameters for modulus
+ * lengths of <code>512</code>, <code>768</code> and <code>1024</code>. Any
+ * other value, of the modulus length, even if between <code>512</code> and
+ * <code>1024</code>, and of the form <code>512 + 64 * n</code>, will cause
+ * an {@link IllegalArgumentException} to be thrown. When those modulus
+ * length (<code>512</code>, <code>768</code>, and <code>1024</code>) are
+ * specified, the paramter set is always the same.</li>
+ *
+ * <li>Finally, if this property is {@link Boolean#TRUE} and the value of
+ * {@link #STRICT_DEFAULTS} is {@link Boolean#FALSE} then this generator
+ * will behave as in point 1 above, except that it will use pre-computed
+ * values when possible; i.e. the modulus length is one of <code>512</code>,
+ * <code>768</code>, or <code>1024</code>.</li>
+ * </ol>
+ *
+ * The default value of this property is {@link Boolean#TRUE}.
+ */
+ public static final String USE_DEFAULTS = "gnu.crypto.dss.use.defaults";
+
+ /**
+ * Property name of the Boolean indicating wether or not to generate new
+ * parameters, even if the modulus length <i>L</i> is not one of the pre-
+ * computed defaults (value {@link Boolean#FALSE}), or throw an exception
+ * (value {@link Boolean#TRUE}) -- the exception in this case is an
+ * {@link IllegalArgumentException}. The default value for this property is
+ * {@link Boolean#FALSE}. The ultimate behaviour of this generator will
+ * depend on the values of this and {@link #USE_DEFAULTS} properties -- see
+ * {@link #USE_DEFAULTS} for more information.
+ */
+ public static final String STRICT_DEFAULTS = "gnu.crypto.dss.strict.defaults";
+
+ /**
+ * Property name of an optional {@link SecureRandom} instance to use. The
+ * default is to use a classloader singleton from {@link PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dss.prng";
+
+ /**
+ * Property name of an optional {@link DSAParameterSpec} instance to use for
+ * this generator's <code>p</code>, <code>q</code>, and <code>g</code> values.
+ * The default is to generate these values or use pre-computed ones,
+ * depending on the value of the <code>USE_DEFAULTS</code> attribute.
+ */
+ public static final String DSS_PARAMETERS = "gnu.crypto.dss.params";
+
+ /**
+ * 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.dss.encoding";
+
+ /** Default value for the modulus length. */
+ public static final int DEFAULT_MODULUS_LENGTH = 1024;
+
+ /** Default encoding format to use when none was specified. */
+ private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
+
+ /** Initial SHS context. */
+ private static final int[] T_SHS = new int[] { 0x67452301, 0xEFCDAB89,
+ 0x98BADCFE, 0x10325476,
+ 0xC3D2E1F0 };
+
+ // from jdk1.3.1/docs/guide/security/CryptoSpec.html#AppB
+ public static final DSAParameterSpec KEY_PARAMS_512 = new DSAParameterSpec(
+ new BigInteger(
+ "fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae"
+ + "01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e17",
+ 16),
+ new BigInteger(
+ "962eddcc369cba8ebb260ee6b6a126d9346e38c5",
+ 16),
+ new BigInteger(
+ "678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e"
+ + "35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4",
+ 16));
+
+ public static final DSAParameterSpec KEY_PARAMS_768 = new DSAParameterSpec(
+ new BigInteger(
+ "e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5d8901419"
+ + "22d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a22219d470bce7d77"
+ + "7d4a21fbe9c270b57f607002f3cef8393694cf45ee3688c11a8c56ab127a3daf",
+ 16),
+ new BigInteger(
+ "9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511",
+ 16),
+ new BigInteger(
+ "30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7a31d23c4"
+ + "dbbcbe06174544401a5b2c020965d8c2bd2171d3668445771f74ba084d2029d8"
+ + "3c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a7064f316933a346d3f529252",
+ 16));
+
+ public static final DSAParameterSpec KEY_PARAMS_1024 = new DSAParameterSpec(
+ new BigInteger(
+ "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669"
+ + "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7"
+ + "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb"
+ + "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7",
+ 16),
+ new BigInteger(
+ "9760508f15230bccb292b982a2eb840bf0581cf5",
+ 16),
+ new BigInteger(
+ "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267"
+ + "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1"
+ + "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b"
+ + "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a",
+ 16));
+
+ private static final BigInteger TWO_POW_160 = TWO.pow(160);
+
+ /** The length of the modulus of DSS keys generated by this instance. */
+ private int L;
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ private BigInteger seed;
+
+ private BigInteger counter;
+
+ private BigInteger p;
+
+ private BigInteger q;
+
+ private BigInteger e;
+
+ private BigInteger g;
+
+ private BigInteger XKEY;
+
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
+ /** Preferred encoding format of generated keys. */
+ private int preferredFormat;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
+
+ public String name()
+ {
+ return Registry.DSS_KPG;
+ }
+
+ /**
+ * <p>Configures this instance.</p>
+ *
+ * @param attributes the map of name/value pairs to use.
+ * @exception IllegalArgumentException if the designated MODULUS_LENGTH
+ * value is not greater than 512, less than 1024 and not of the form
+ * <code>512 + 64j</code>.
+ */
+ public void setup(Map attributes)
+ {
+ // find out the modulus length
+ Integer l = (Integer) attributes.get(MODULUS_LENGTH);
+ L = (l == null ? DEFAULT_MODULUS_LENGTH : l.intValue());
+ if ((L % 64) != 0 || L < 512 || L > 1024)
+ throw new IllegalArgumentException(MODULUS_LENGTH);
+
+ // should we use the default pre-computed params?
+ Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
+ if (useDefaults == null)
+ {
+ useDefaults = Boolean.TRUE;
+ }
+
+ Boolean strictDefaults = (Boolean) attributes.get(STRICT_DEFAULTS);
+ if (strictDefaults == null)
+ strictDefaults = Boolean.FALSE;
+
+ // are we given a set of DSA params or we shall use/generate our own?
+ DSAParameterSpec params = (DSAParameterSpec) attributes.get(DSS_PARAMETERS);
+ if (params != null)
+ {
+ p = params.getP();
+ q = params.getQ();
+ g = params.getG();
+ }
+ else if (useDefaults.equals(Boolean.TRUE))
+ {
+ switch (L)
+ {
+ case 512:
+ p = KEY_PARAMS_512.getP();
+ q = KEY_PARAMS_512.getQ();
+ g = KEY_PARAMS_512.getG();
+ break;
+ case 768:
+ p = KEY_PARAMS_768.getP();
+ q = KEY_PARAMS_768.getQ();
+ g = KEY_PARAMS_768.getG();
+ break;
+ case 1024:
+ p = KEY_PARAMS_1024.getP();
+ q = KEY_PARAMS_1024.getQ();
+ g = KEY_PARAMS_1024.getG();
+ break;
+ default:
+ if (strictDefaults.equals(Boolean.TRUE))
+ throw new IllegalArgumentException(
+ "Does not provide default parameters for " + L
+ + "-bit modulus length");
+ else
+ {
+ p = null;
+ q = null;
+ g = null;
+ }
+ }
+ }
+ else
+ {
+ p = null;
+ q = null;
+ g = null;
+ }
+
+ // do we have a SecureRandom, or should we use our own?
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ // what is the preferred encoding format
+ Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
+ preferredFormat = formatID == null
+ ? DEFAULT_ENCODING_FORMAT
+ : formatID.intValue();
+
+ // set the seed-key
+ byte[] kb = new byte[20]; // we need 160 bits of randomness
+ nextRandomBytes(kb);
+ XKEY = new BigInteger(1, kb).setBit(159).setBit(0);
+ }
+
+ public KeyPair generate()
+ {
+ if (p == null)
+ {
+ BigInteger[] params = new FIPS186(L, rnd).generateParameters();
+ seed = params[FIPS186.DSA_PARAMS_SEED];
+ counter = params[FIPS186.DSA_PARAMS_COUNTER];
+ q = params[FIPS186.DSA_PARAMS_Q];
+ p = params[FIPS186.DSA_PARAMS_P];
+ e = params[FIPS186.DSA_PARAMS_E];
+ g = params[FIPS186.DSA_PARAMS_G];
+ if (DEBUG && debuglevel > 0)
+ {
+ debug("seed: " + seed.toString(16));
+ debug("counter: " + counter.intValue());
+ debug("q: " + q.toString(16));
+ debug("p: " + p.toString(16));
+ debug("e: " + e.toString(16));
+ debug("g: " + g.toString(16));
+ }
+ }
+
+ BigInteger x = nextX();
+ BigInteger y = g.modPow(x, p);
+
+ PublicKey pubK = new DSSPublicKey(preferredFormat, p, q, g, y);
+ PrivateKey secK = new DSSPrivateKey(preferredFormat, p, q, g, x);
+
+ return new KeyPair(pubK, secK);
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>This method applies the following algorithm described in 3.1 of
+ * FIPS-186:</p>
+ *
+ * <ol>
+ * <li>XSEED = optional user input.</li>
+ * <li>XVAL = (XKEY + XSEED) mod 2<sup>b</sup>.</li>
+ * <li>x = G(t, XVAL) mod q.</li>
+ * <li>XKEY = (1 + XKEY + x) mod 2<sup>b</sup>.</li>
+ * </ol>
+ *
+ * <p>Where <code>b</code> is the length of a secret b-bit seed-key (XKEY).</p>
+ *
+ * <p>Note that in this implementation, XSEED, the optional user input, is
+ * always zero.</p>
+ */
+ private synchronized BigInteger nextX()
+ {
+ byte[] xk = XKEY.toByteArray();
+ byte[] in = new byte[64]; // 512-bit block for SHS
+ System.arraycopy(xk, 0, in, 0, xk.length);
+
+ int[] H = Sha160.G(T_SHS[0], T_SHS[1], T_SHS[2], T_SHS[3], T_SHS[4], in, 0);
+ byte[] h = new byte[20];
+ for (int i = 0, j = 0; i < 5; i++)
+ {
+ h[j++] = (byte) (H[i] >>> 24);
+ h[j++] = (byte) (H[i] >>> 16);
+ h[j++] = (byte) (H[i] >>> 8);
+ h[j++] = (byte) H[i];
+ }
+ BigInteger result = new BigInteger(1, h).mod(q);
+ XKEY = XKEY.add(result).add(BigInteger.ONE).mod(TWO_POW_160);
+
+ return result;
+ }
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java b/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java
new file mode 100644
index 00000000000..30e30bd144d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairPKCS8Codec.java
@@ -0,0 +1,235 @@
+/* DSSKeyPairPKCS8Codec.java -- PKCS#8 Encoding/Decoding handler
+ 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.java.security.key.dss;
+
+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;
+
+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;
+
+/**
+ * An implementation of an {@link IKeyPairCodec} that knows how to encode /
+ * decode PKCS#8 ASN.1 external representation of DSS private keys.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public class DSSKeyPairPKCS8Codec
+ implements IKeyPairCodec
+{
+ private static final OID DSA_ALG_OID = new OID(Registry.DSA_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 PKCS#8 ASN.1 <i>PrivateKeyInfo</i> representation of a DSA
+ * 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
+ * }
+ *
+ * DssParams ::= SEQUENCE {
+ * p INTEGER,
+ * q INTEGER,
+ * g INTEGER
+ * }
+ * </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 DSSPrivateKey))
+ throw new InvalidParameterException("Wrong key type");
+
+ DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
+
+ DSSPrivateKey pk = (DSSPrivateKey) key;
+ BigInteger p = pk.getParams().getP();
+ BigInteger q = pk.getParams().getQ();
+ BigInteger g = pk.getParams().getG();
+ BigInteger x = pk.getX();
+
+ ArrayList params = new ArrayList(3);
+ params.add(new DERValue(DER.INTEGER, p));
+ params.add(new DERValue(DER.INTEGER, q));
+ params.add(new DERValue(DER.INTEGER, g));
+ 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 DSS
+ * {@link PrivateKey} instance. MUST NOT be null.
+ * @return a new instance of a {@link DSSPrivateKey} 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(DSA_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 Q field");
+ q = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong G field");
+ g = (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 DSSPrivateKey(Registry.PKCS8_ENCODING_ID, p, q, g, x);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairRawCodec.java b/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairRawCodec.java
new file mode 100644
index 00000000000..86e5b0bef7e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairRawCodec.java
@@ -0,0 +1,383 @@
+/* DSSKeyPairRawCodec.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>An object that implements the {@link IKeyPairCodec} operations for the
+ * <i>Raw</i> format to use with DSS keypairs.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSKeyPairRawCodec implements IKeyPairCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.keys.IKeyPairCodec interface implementation ------------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated DSS (Digital Signature
+ * Standard) public key according to the <i>Raw</i> format supported by
+ * this library.</p>
+ *
+ * <p>The <i>Raw</i> format for a DSA public key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_DSS_PUBLIC_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>p</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>p</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>q</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>q</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>g</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>g</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>y</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>y</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @throws IllegalArgumentException if the designated key is not a DSS
+ * (Digital Signature Standard) one.
+ * @see Registry#MAGIC_RAW_DSS_PUBLIC_KEY
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (!(key instanceof DSSPublicKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ DSSPublicKey dssKey = (DSSPublicKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // p
+ byte[] buffer = dssKey.getParams().getP().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // q
+ buffer = dssKey.getParams().getQ().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // g
+ buffer = dssKey.getParams().getG().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // y
+ buffer = dssKey.getY().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PublicKey decodePublicKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // p
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger p = new BigInteger(1, buffer);
+
+ // q
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger q = new BigInteger(1, buffer);
+
+ // g
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger g = new BigInteger(1, buffer);
+
+ // y
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger y = new BigInteger(1, buffer);
+
+ return new DSSPublicKey(p, q, g, y);
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated DSS (Digital Signature
+ * Standard) private key according to the <i>Raw</i> format supported by
+ * this library.</p>
+ *
+ * <p>The <i>Raw</i> format for a DSA private key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_DSS_PRIVATE_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>p</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>p</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>q</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>q</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>g</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>g</code>,</li>
+ * <li>4-byte count of following bytes representing the DSA parameter
+ * <code>x</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSA parameter
+ * <code>x</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @throws IllegalArgumentException if the designated key is not a DSS
+ * (Digital Signature Standard) one.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (!(key instanceof DSSPrivateKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ DSSPrivateKey dssKey = (DSSPrivateKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // p
+ byte[] buffer = dssKey.getParams().getP().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // q
+ buffer = dssKey.getParams().getQ().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // g
+ buffer = dssKey.getParams().getG().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // x
+ buffer = dssKey.getX().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PrivateKey decodePrivateKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // p
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger p = new BigInteger(1, buffer);
+
+ // q
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger q = new BigInteger(1, buffer);
+
+ // g
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger g = new BigInteger(1, buffer);
+
+ // x
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger x = new BigInteger(1, buffer);
+
+ return new DSSPrivateKey(p, q, g, x);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairX509Codec.java b/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairX509Codec.java
new file mode 100644
index 00000000000..516ef92afd5
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/dss/DSSKeyPairX509Codec.java
@@ -0,0 +1,248 @@
+/* DSSKeyPairX509Codec.java -- X.509 Encoding/Decoding handler
+ 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.java.security.key.dss;
+
+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;
+
+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;
+
+/**
+ * An implementation of an {@link IKeyPairCodec} that knows how to encode /
+ * decode X.509 ASN.1 external representation of DSS public keys.
+ */
+public class DSSKeyPairX509Codec
+ implements IKeyPairCodec
+{
+ private static final OID DSA_ALG_OID = new OID(Registry.DSA_OID_STRING);
+
+ // implicit 0-arguments constructor
+
+ public int getFormatID()
+ {
+ return X509_FORMAT;
+ }
+
+ /**
+ * Returns the X.509 ASN.1 <i>SubjectPublicKeyInfo</i> representation of a
+ * DSA 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
+ * }
+ *
+ * DssParams ::= SEQUENCE {
+ * p INTEGER,
+ * q INTEGER,
+ * g INTEGER
+ * }
+ * </pre>
+ *
+ * <p>The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
+ * DER-encoded form of the DSA public key as an INTEGER.</p>
+ *
+ * <pre>
+ * DSAPublicKey ::= INTEGER -- public key, Y
+ * </pre>
+ *
+ * @param key the {@link PublicKey} instance to encode. MUST be an instance of
+ * {@link DSSPublicKey}.
+ * @return 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 DSSPublicKey} or if an exception occurs during the
+ * marshalling process.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (! (key instanceof DSSPublicKey))
+ throw new InvalidParameterException("key");
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
+
+ DSSPublicKey dssKey = (DSSPublicKey) key;
+ BigInteger p = dssKey.getParams().getP();
+ BigInteger q = dssKey.getParams().getQ();
+ BigInteger g = dssKey.getParams().getG();
+ BigInteger y = dssKey.getY();
+
+ DERValue derP = new DERValue(DER.INTEGER, p);
+ DERValue derQ = new DERValue(DER.INTEGER, q);
+ DERValue derG = new DERValue(DER.INTEGER, g);
+
+ ArrayList params = new ArrayList(3);
+ params.add(derP);
+ params.add(derQ);
+ params.add(derG);
+ 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 derDSAPublicKey = new DERValue(DER.INTEGER, y);
+ byte[] yBytes = derDSAPublicKey.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 DSS
+ * {@link PublicKey} instance. MUST NOT be null.
+ * @return a new instance of a {@link DSSPublicKey} 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(DSA_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 Q field");
+ q = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong G field");
+ g = (BigInteger) val.getValue();
+
+ val = der.read();
+ if (! (val.getValue() instanceof BitString))
+ throw new InvalidParameterException("Wrong SubjectPublicKey field");
+
+ byte[] yBytes = ((BitString) val.getValue()).toByteArray();
+
+ DERReader dsaPub = new DERReader(yBytes);
+ val = dsaPub.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 DSSPublicKey(Registry.X509_ENCODING_ID, p, q, g, y);
+ }
+
+ /**
+ * @throws InvalidParameterException ALWAYS.
+ */
+ public PrivateKey decodePrivateKey(byte[] input)
+ {
+ throw new InvalidParameterException("Wrong format for private keys");
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/dss/DSSPrivateKey.java b/libjava/classpath/gnu/java/security/key/dss/DSSPrivateKey.java
new file mode 100644
index 00000000000..c81eb93b078
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/dss/DSSPrivateKey.java
@@ -0,0 +1,201 @@
+/* DSSPrivateKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.interfaces.DSAPrivateKey;
+
+/**
+ * <p>An object that embodies a DSS (Digital Signature Standard) private key.</p>
+ *
+ * @version $Revision: 1.2 $
+ * @see #getEncoded
+ */
+public class DSSPrivateKey extends DSSKey implements PrivateKey, DSAPrivateKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>A randomly or pseudorandomly generated integer with <code>0 &lt; x &lt;
+ * q</code>.</p>
+ */
+ private final BigInteger x;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Convenience constructor. Calls the constructor with 5 arguments passing
+ * {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
+ * encoding format.
+ *
+ * @param p the public modulus.
+ * @param q the public prime divisor of <code>p-1</code>.
+ * @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
+ * <sub>p</sub></code>.
+ * @param x the private key part.
+ */
+ public DSSPrivateKey(BigInteger p, BigInteger q, BigInteger g, BigInteger x)
+ {
+ this(Registry.RAW_ENCODING_ID, p, q, g, x);
+ }
+
+ /**
+ * Constructs a new instance of a <code>DSSPrivateKey</code> given the
+ * designated arguments.
+ *
+ * @param preferredFormat the indetifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param p the public modulus.
+ * @param q the public prime divisor of <code>p-1</code>.
+ * @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
+ * <sub>p</sub></code>.
+ * @param x the private key part.
+ */
+ public DSSPrivateKey(int preferredFormat, BigInteger p, BigInteger q,
+ BigInteger g, BigInteger x)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
+ : preferredFormat,
+ p, q, g);
+
+ this.x = x;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * A class method that takes the output of the <code>encodePrivateKey()</code>
+ * method of a DSS keypair codec object (an instance implementing
+ * {@link gnu.java.security.key.IKeyPairCodec} for DSS keys, and re-constructs
+ * an instance of this object.
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an
+ * instance of this object.
+ * @exception IllegalArgumentException if the byte sequence does not represent
+ * a valid encoding of an instance of this object.
+ */
+ public static DSSPrivateKey valueOf(byte[] k)
+ {
+ // try RAW codec
+ if (k[0] == Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0])
+ try
+ {
+ return (DSSPrivateKey) new DSSKeyPairRawCodec().decodePrivateKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try PKCS#8 codec
+ return (DSSPrivateKey) new DSSKeyPairPKCS8Codec().decodePrivateKey(k);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.DSAPrivateKey interface implementation ---------
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this private key according to the
+ * designated format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @exception IllegalArgumentException if the format is not supported.
+ * @see DSSKeyPairRawCodec
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new DSSKeyPairRawCodec().encodePrivateKey(this);
+ break;
+ case IKeyPairCodec.PKCS8_FORMAT:
+ result = new DSSKeyPairPKCS8Codec().encodePrivateKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link DSAPrivateKey} and has the same DSS (Digital Signature Standard)
+ * parameter values as this one.</p>
+ *
+ * @param obj the other non-null DSS key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof DSAPrivateKey))
+ {
+ return false;
+ }
+ DSAPrivateKey that = (DSAPrivateKey) obj;
+ return super.equals(that) && x.equals(that.getX());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/dss/DSSPublicKey.java b/libjava/classpath/gnu/java/security/key/dss/DSSPublicKey.java
new file mode 100644
index 00000000000..93bb6402203
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/dss/DSSPublicKey.java
@@ -0,0 +1,201 @@
+/* DSSPublicKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.interfaces.DSAPublicKey;
+
+/**
+ * <p>An object that embodies a DSS (Digital Signature Standard) public key.</p>
+ *
+ * @version $Revision: 1.2 $
+ * @see #getEncoded
+ */
+public class DSSPublicKey extends DSSKey implements PublicKey, DSAPublicKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /**
+ * <code>y = g<sup>x</sup> mod p</code> where <code>x</code> is the private
+ * part of the DSA key.
+ */
+ private final BigInteger y;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Conveience constructor. Calls the constructor with 5 arguments passing
+ * {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
+ * encoding format.
+ *
+ * @param p the public modulus.
+ * @param q the public prime divisor of <code>p-1</code>.
+ * @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
+ * <sub>p</sub></code>.
+ * @param y the public key part.
+ */
+ public DSSPublicKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y)
+ {
+ this(Registry.RAW_ENCODING_ID, p, q, g, y);
+ }
+
+ /**
+ * Constructs a new instance of <code>DSSPublicKey</code> given the designated
+ * arguments.
+ *
+ * @param preferredFormat the identifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param p the public modulus.
+ * @param q the public prime divisor of <code>p-1</code>.
+ * @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
+ * <sub>p</sub></code>.
+ * @param y the public key part.
+ */
+ public DSSPublicKey(int preferredFormat, BigInteger p, BigInteger q,
+ BigInteger g, BigInteger y)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
+ : preferredFormat,
+ p, q, g);
+
+ this.y = y;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * A class method that takes the output of the <code>encodePublicKey()</code>
+ * method of a DSS keypair codec object (an instance implementing
+ * {@link gnu.java.security.key.IKeyPairCodec} for DSS keys, and re-constructs
+ * an instance of this object.
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an
+ * instance of this object.
+ * @exception IllegalArgumentException if the byte sequence does not represent
+ * a valid encoding of an instance of this object.
+ */
+ public static DSSPublicKey valueOf(byte[] k)
+ {
+ // try RAW codec
+ if (k[0] == Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0])
+ try
+ {
+ return (DSSPublicKey) new DSSKeyPairRawCodec().decodePublicKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try X.509 codec
+ return (DSSPublicKey) new DSSKeyPairX509Codec().decodePublicKey(k);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.DSAPublicKey interface implementation ----------
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this public key according to the designated
+ * format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @exception IllegalArgumentException if the format is not supported.
+ * @see DSSKeyPairRawCodec
+ */
+ public byte[] getEncoded(int format)
+ {
+ byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new DSSKeyPairRawCodec().encodePublicKey(this);
+ break;
+ case IKeyPairCodec.X509_FORMAT:
+ result = new DSSKeyPairX509Codec().encodePublicKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link DSAPublicKey} and has the same DSS (Digital Signature Standard)
+ * parameter values as this one.</p>
+ *
+ * @param obj the other non-null DSS key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof DSAPublicKey))
+ {
+ return false;
+ }
+ DSAPublicKey that = (DSAPublicKey) obj;
+ return super.equals(that) && y.equals(that.getY());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/dss/FIPS186.java b/libjava/classpath/gnu/java/security/key/dss/FIPS186.java
new file mode 100644
index 00000000000..74be626f58e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/dss/FIPS186.java
@@ -0,0 +1,296 @@
+/* FIPS186.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.util.PRNG;
+import gnu.java.security.util.Prime2;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * <p>An implementation of the DSA parameters generation as described in
+ * FIPS-186.</p>
+ *
+ * References:<br>
+ * <a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature
+ * Standard (DSS)</a>, Federal Information Processing Standards Publication 186.
+ * National Institute of Standards and Technology.
+ *
+ * @version $Revision: 1.2 $
+ */
+public class FIPS186
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ public static final int DSA_PARAMS_SEED = 0;
+
+ public static final int DSA_PARAMS_COUNTER = 1;
+
+ public static final int DSA_PARAMS_Q = 2;
+
+ public static final int DSA_PARAMS_P = 3;
+
+ public static final int DSA_PARAMS_E = 4;
+
+ public static final int DSA_PARAMS_G = 5;
+
+ /** The BigInteger constant 2. */
+ private static final BigInteger TWO = new BigInteger("2");
+
+ private static final BigInteger TWO_POW_160 = TWO.pow(160);
+
+ /** The SHA instance to use. */
+ private Sha160 sha = new Sha160();
+
+ /** The length of the modulus of DSS keys generated by this instance. */
+ private int L;
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public FIPS186(int L, SecureRandom rnd)
+ {
+ super();
+
+ this.L = L;
+ this.rnd = rnd;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * This method generates the DSS <code>p</code>, <code>q</code>, and
+ * <code>g</code> parameters only when <code>L</code> (the modulus length)
+ * is not one of the following: <code>512</code>, <code>768</code> and
+ * <code>1024</code>. For those values of <code>L</code>, this implementation
+ * uses pre-computed values of <code>p</code>, <code>q</code>, and
+ * <code>g</code> given in the document <i>CryptoSpec</i> included in the
+ * security guide documentation of the standard JDK distribution.<p>
+ *
+ * The DSS requires two primes , <code>p</code> and <code>q</code>,
+ * satisfying the following three conditions:
+ *
+ * <ul>
+ * <li><code>2<sup>159</sup> &lt; q &lt; 2<sup>160</sup></code></li>
+ * <li><code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup></code> for a
+ * specified <code>L</code>, where <code>L = 512 + 64j</code> for some
+ * <code>0 &lt;= j &lt;= 8</code></li>
+ * <li>q divides p - 1.</li>
+ * </ul>
+ *
+ * The algorithm used to find these primes is as described in FIPS-186,
+ * section 2.2: GENERATION OF PRIMES. This prime generation scheme starts by
+ * using the {@link Sha160} and a user supplied <i>SEED</i>
+ * to construct a prime, <code>q</code>, in the range 2<sup>159</sup> &lt; q
+ * &lt; 2<sup>160</sup>. Once this is accomplished, the same <i>SEED</i>
+ * value is used to construct an <code>X</code> in the range <code>2<sup>L-1
+ * </sup> &lt; X &lt; 2<sup>L</sup>. The prime, <code>p</code>, is then
+ * formed by rounding <code>X</code> to a number congruent to <code>1 mod
+ * 2q</code>. In this implementation we use the same <i>SEED</i> value given
+ * in FIPS-186, Appendix 5.
+ */
+ public BigInteger[] generateParameters()
+ {
+ int counter, offset;
+ BigInteger SEED, alpha, U, q, OFFSET, SEED_PLUS_OFFSET, W, X, p, c, g;
+ byte[] a, u;
+ byte[] kb = new byte[20]; // to hold 160 bits of randomness
+
+ // Let L-1 = n*160 + b, where b and n are integers and 0 <= b < 160.
+ int b = (L - 1) % 160;
+ int n = (L - 1 - b) / 160;
+ BigInteger[] V = new BigInteger[n + 1];
+ algorithm: while (true)
+ {
+ step1: while (true)
+ {
+ // 1. Choose an arbitrary sequence of at least 160 bits and
+ // call it SEED.
+ nextRandomBytes(kb);
+ SEED = new BigInteger(1, kb).setBit(159).setBit(0);
+ // Let g be the length of SEED in bits. here always 160
+ // 2. Compute: U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]
+ alpha = SEED.add(BigInteger.ONE).mod(TWO_POW_160);
+ synchronized (sha)
+ {
+ a = SEED.toByteArray();
+ sha.update(a, 0, a.length);
+ a = sha.digest();
+ u = alpha.toByteArray();
+ sha.update(u, 0, u.length);
+ u = sha.digest();
+ }
+ for (int i = 0; i < a.length; i++)
+ {
+ a[i] ^= u[i];
+ }
+ U = new BigInteger(1, a);
+ // 3. Form q from U by setting the most significant bit (the
+ // 2**159 bit) and the least significant bit to 1. In terms of
+ // boolean operations, q = U OR 2**159 OR 1. Note that
+ // 2**159 < q < 2**160.
+ q = U.setBit(159).setBit(0);
+ // 4. Use a robust primality testing algorithm to test whether
+ // q is prime(1). A robust primality test is one where the
+ // probability of a non-prime number passing the test is at
+ // most 1/2**80.
+ // 5. If q is not prime, go to step 1.
+ if (Prime2.isProbablePrime(q))
+ {
+ break step1;
+ }
+ } // step1
+
+ // 6. Let counter = 0 and offset = 2.
+ counter = 0;
+ offset = 2;
+ step7: while (true)
+ {
+ OFFSET = BigInteger.valueOf(offset & 0xFFFFFFFFL);
+ SEED_PLUS_OFFSET = SEED.add(OFFSET);
+ // 7. For k = 0,...,n let V[k] = SHA[(SEED + offset + k) mod 2**g].
+ synchronized (sha)
+ {
+ for (int k = 0; k <= n; k++)
+ {
+ a = SEED_PLUS_OFFSET.add(
+ BigInteger.valueOf(k & 0xFFFFFFFFL)).mod(
+ TWO_POW_160).toByteArray();
+ sha.update(a, 0, a.length);
+ V[k] = new BigInteger(1, sha.digest());
+ }
+ }
+ // 8. Let W be the integer:
+ // V[0]+V[1]*2**160+...+V[n-1]*2**((n-1)*160)+(V[n]mod2**b)*2**(n*160)
+ // and let : X = W + 2**(L-1).
+ // Note that 0 <= W < 2**(L-1) and hence 2**(L-1) <= X < 2**L.
+ W = V[0];
+ for (int k = 1; k < n; k++)
+ {
+ W = W.add(V[k].multiply(TWO.pow(k * 160)));
+ }
+ W = W.add(V[n].mod(TWO.pow(b)).multiply(TWO.pow(n * 160)));
+ X = W.add(TWO.pow(L - 1));
+ // 9. Let c = X mod 2q and set p = X - (c - 1).
+ // Note that p is congruent to 1 mod 2q.
+ c = X.mod(TWO.multiply(q));
+ p = X.subtract(c.subtract(BigInteger.ONE));
+ // 10. If p < 2**(L-1), then go to step 13.
+ if (p.compareTo(TWO.pow(L - 1)) >= 0)
+ {
+ // 11. Perform a robust primality test on p.
+ // 12. If p passes the test performed in step 11, go to step 15.
+ if (Prime2.isProbablePrime(p))
+ {
+ break algorithm;
+ }
+ }
+ // 13. Let counter = counter + 1 and offset = offset + n + 1.
+ counter++;
+ offset += n + 1;
+ // 14. If counter >= 4096 go to step 1, otherwise go to step 7.
+ if (counter >= 4096)
+ {
+ continue algorithm;
+ }
+ } // step7
+ } // algorithm
+
+ // compute g. from FIPS-186, Appendix 4:
+ // 1. Generate p and q as specified in Appendix 2.
+ // 2. Let e = (p - 1) / q
+ BigInteger e = p.subtract(BigInteger.ONE).divide(q);
+ BigInteger h = TWO;
+ BigInteger p_minus_1 = p.subtract(BigInteger.ONE);
+ g = TWO;
+ // 3. Set h = any integer, where 1 < h < p - 1 and
+ // h differs from any value previously tried
+ for (; h.compareTo(p_minus_1) < 0; h = h.add(BigInteger.ONE))
+ {
+ // 4. Set g = h**e mod p
+ g = h.modPow(e, p);
+ // 5. If g = 1, go to step 3
+ if (!g.equals(BigInteger.ONE))
+ {
+ break;
+ }
+ }
+
+ return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g };
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ * Fills the designated byte array with random data.
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/rsa/GnuRSAKey.java b/libjava/classpath/gnu/java/security/key/rsa/GnuRSAKey.java
new file mode 100644
index 00000000000..72cd808d43b
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/rsa/GnuRSAKey.java
@@ -0,0 +1,181 @@
+/* GnuRSAKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+import gnu.java.security.util.FormatUtil;
+
+import java.math.BigInteger;
+import java.security.Key;
+import java.security.interfaces.RSAKey;
+
+/**
+ * <p>A base asbtract class for both public and private RSA keys.</p>
+ *
+ * @version $Revision: 1.3 $
+ */
+public abstract class GnuRSAKey implements Key, RSAKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The public modulus of an RSA key pair. */
+ private final BigInteger n;
+
+ /** The public exponent of an RSA key pair. */
+ private final BigInteger e;
+
+ /**
+ * 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 n the public modulus <code>n</code>.
+ * @param e the public exponent <code>e</code>.
+ */
+ protected GnuRSAKey(int defaultFormat, BigInteger n, BigInteger e)
+ {
+ super();
+
+ this.defaultFormat = defaultFormat <= 0 ? Registry.RAW_ENCODING_ID
+ : defaultFormat;
+ this.n = n;
+ this.e = e;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // java.security.interfaces.RSAKey interface implementation ----------------
+
+ public BigInteger getModulus()
+ {
+ return getN();
+ }
+
+ // java.security.Key interface implementation ------------------------------
+
+ public String getAlgorithm()
+ {
+ return Registry.RSA_KPG;
+ }
+
+ /** @deprecated see getEncoded(int). */
+ public byte[] getEncoded()
+ {
+ return getEncoded(IKeyPairCodec.RAW_FORMAT);
+ }
+
+ public String getFormat()
+ {
+ return FormatUtil.getEncodingShortName(defaultFormat);
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>Returns the modulus <code>n</code>.</p>
+ *
+ * @return the modulus <code>n</code>.
+ */
+ public BigInteger getN()
+ {
+ return n;
+ }
+
+ /**
+ * <p>Returns the public exponent <code>e</code>.</p>
+ *
+ * @return the public exponent <code>e</code>.
+ */
+ public BigInteger getPublicExponent()
+ {
+ return getE();
+ }
+
+ /**
+ * <p>Same as {@link #getPublicExponent()}.</p>
+ *
+ * @return the public exponent <code>e</code>.
+ */
+ public BigInteger getE()
+ {
+ return e;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * {@link RSAKey} and has the same RSA parameter values as this one.</p>
+ *
+ * @param obj the other non-null RSA key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(final Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof RSAKey))
+ {
+ return false;
+ }
+ final RSAKey that = (RSAKey) obj;
+ return n.equals(that.getModulus());
+ }
+
+ // abstract methods to be implemented by subclasses ------------------------
+
+ public abstract byte[] getEncoded(int format);
+}
diff --git a/libjava/classpath/gnu/java/security/key/rsa/GnuRSAPrivateKey.java b/libjava/classpath/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
new file mode 100644
index 00000000000..f8acaa50df7
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
@@ -0,0 +1,299 @@
+/* GnuRSAPrivateKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+
+/**
+ * <p>An object that embodies an RSA private key.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.3 $
+ */
+public class GnuRSAPrivateKey extends GnuRSAKey implements PrivateKey,
+ RSAPrivateCrtKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The first prime divisor of the modulus. */
+ private final BigInteger p;
+
+ /** The second prime divisor of the modulus. */
+ private final BigInteger q;
+
+ /** The public exponent of an RSA key. */
+ // private final BigInteger e;
+ /** The private exponent of an RSA private key. */
+ private final BigInteger d;
+
+ /** The first factor's exponent. */
+ private final BigInteger dP;
+
+ /** The second factor's exponent. */
+ private final BigInteger dQ;
+
+ /** The CRT (Chinese Remainder Theorem) coefficient. */
+ private final BigInteger qInv;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Convenience constructor. Calls the constructor with 5 arguments passing
+ * {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
+ * encoding format.
+ *
+ * @param p the modulus first prime divisor.
+ * @param q the modulus second prime divisor.
+ * @param e the public exponent.
+ * @param d the private exponent.
+ */
+ public GnuRSAPrivateKey(BigInteger p, BigInteger q, BigInteger e,
+ BigInteger d)
+ {
+ this(Registry.RAW_ENCODING_ID, p, q, e, d);
+ }
+
+ /**
+ * Constructs a new instance of a <code>GnuRSAPrivateKey</code> given the
+ * designated arguments.
+ *
+ * @param preferredFormat the indetifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param p the modulus first prime divisor.
+ * @param q the modulus second prime divisor.
+ * @param e the public exponent.
+ * @param d the private exponent.
+ */
+ public GnuRSAPrivateKey(int preferredFormat, BigInteger p, BigInteger q,
+ BigInteger e, BigInteger d)
+ {
+ this(preferredFormat, p.multiply(q), e, d, p, q,
+ e.modInverse(p.subtract(BigInteger.ONE)),
+ e.modInverse(q.subtract(BigInteger.ONE)),
+ q.modInverse(p));
+ }
+
+ /**
+ * Constructs a new instance of a <code>GnuRSAPrivateKey</code> given the
+ * designated arguments.
+ *
+ * @param preferredFormat the indetifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param n the public modulus, which is also the product of <code>p</code>
+ * and <code>q</code>.
+ * @param e the public exponent.
+ * @param d the private exponent.
+ * @param p the modulus first prime divisor.
+ * @param q the modulus second prime divisor.
+ * @param dP the first prime's exponen. A positive integer less than
+ * <code>p</code> and <code>q</code>, satisfying <code>e * dP = 1 (mod p-1)
+ * </code>.
+ * @param dQ the second prime's exponent. A positive integer less than
+ * <code>p</code> and <code>q</code>, satisfying <code>e * dQ = 1 (mod p-1)
+ * </code>.
+ * @param qInv the Chinese Remainder Theorem coefiicient. A positive integer
+ * less than <code>p</code>, satisfying <code>q * qInv = 1 (mod p)</code>.
+ */
+ public GnuRSAPrivateKey(int preferredFormat, BigInteger n, BigInteger e,
+ BigInteger d, BigInteger p, BigInteger q,
+ BigInteger dP, BigInteger dQ, BigInteger qInv)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
+ : preferredFormat,
+ n, e);
+
+ this.d = d;
+ this.p = p;
+ this.q = q;
+ // the exponents dP and dQ are positive integers less than p and q
+ // respectively satisfying
+ // e * dP = 1 (mod p-1);
+ // e * dQ = 1 (mod q-1),
+ this.dP = dP;
+ this.dQ = dQ;
+ // the CRT coefficient qInv is a positive integer less than p satisfying
+ // q * qInv = 1 (mod p).
+ this.qInv = qInv;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * A class method that takes the output of the <code>encodePrivateKey()</code>
+ * method of an RSA keypair codec object (an instance implementing
+ * {@link IKeyPairCodec} for RSA keys, and re-constructs an instance of this
+ * object.
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an instance
+ * of this object.
+ * @throws IllegalArgumentException if the byte sequence does not represent a
+ * valid encoding of an instance of this object.
+ */
+ public static GnuRSAPrivateKey valueOf(final byte[] k)
+ {
+ // try RAW codec
+ if (k[0] == Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0])
+ try
+ {
+ return (GnuRSAPrivateKey) new RSAKeyPairRawCodec().decodePrivateKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try PKCS#8 codec
+ return (GnuRSAPrivateKey) new RSAKeyPairPKCS8Codec().decodePrivateKey(k);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public BigInteger getPrimeP()
+ {
+ return p;
+ }
+
+ public BigInteger getPrimeQ()
+ {
+ return q;
+ }
+
+ public BigInteger getPrimeExponentP()
+ {
+ return dP;
+ }
+
+ public BigInteger getPrimeExponentQ()
+ {
+ return dQ;
+ }
+
+ public BigInteger getCrtCoefficient()
+ {
+ return qInv;
+ }
+
+ // java.security.interfaces.RSAPrivateKey interface implementation ---------
+
+ public BigInteger getPrivateExponent()
+ {
+ return d;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * Returns the encoded form of this private key according to the
+ * designated format.
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @throws IllegalArgumentException if the format is not supported.
+ * @see RSAKeyPairRawCodec
+ * @see RSAKeyPairPKCS8Codec
+ */
+ public byte[] getEncoded(int format)
+ {
+ final byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new RSAKeyPairRawCodec().encodePrivateKey(this);
+ break;
+ case IKeyPairCodec.PKCS8_FORMAT:
+ result = new RSAKeyPairPKCS8Codec().encodePrivateKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * this class and has the same RSA parameter values as this one.</p>
+ *
+ * @param obj the other non-null RSA key to compare to.
+ * @return <code>true</code> if the designated object is of the same type
+ * and value as this one.
+ */
+ public boolean equals(final Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj instanceof RSAPrivateKey)
+ {
+ final RSAPrivateKey that = (RSAPrivateKey) obj;
+ return super.equals(that) && d.equals(that.getPrivateExponent());
+ }
+ if (obj instanceof RSAPrivateCrtKey)
+ {
+ final RSAPrivateCrtKey that = (RSAPrivateCrtKey) obj;
+ return super.equals(that) && p.equals(that.getPrimeP())
+ && q.equals(that.getPrimeQ())
+ && dP.equals(that.getPrimeExponentP())
+ && dQ.equals(that.getPrimeExponentQ())
+ && qInv.equals(that.getCrtCoefficient());
+ }
+ return false;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/rsa/GnuRSAPublicKey.java b/libjava/classpath/gnu/java/security/key/rsa/GnuRSAPublicKey.java
new file mode 100644
index 00000000000..f49027ca621
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/rsa/GnuRSAPublicKey.java
@@ -0,0 +1,185 @@
+/* GnuRSAPublicKey.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * <p>An object that encapsulates an RSA public key.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.2 $
+ */
+public class GnuRSAPublicKey extends GnuRSAKey implements PublicKey,
+ RSAPublicKey
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Conveience constructor. Calls the constructor with 3 arguments passing
+ * {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
+ * encoding format.
+ *
+ * @param n the modulus.
+ * @param e the public exponent.
+ */
+ public GnuRSAPublicKey(final BigInteger n, final BigInteger e)
+ {
+ this(Registry.RAW_ENCODING_ID, n, e);
+ }
+
+ /**
+ * Constructs a new instance of <code>GnuRSAPublicKey</code> given the
+ * designated arguments.
+ *
+ * @param preferredFormat the identifier of the preferred encoding format to
+ * use when externalizing this key.
+ * @param n the modulus.
+ * @param e the public exponent.
+ */
+ public GnuRSAPublicKey(int preferredFormat, BigInteger n, BigInteger e)
+ {
+ super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
+ : preferredFormat,
+ n, e);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * A class method that takes the output of the <code>encodePublicKey()</code>
+ * method of an RSA keypair codec object (an instance implementing
+ * {@link IKeyPairCodec} for RSA keys, and re-constructs an instance of this
+ * object.
+ *
+ * @param k the contents of a previously encoded instance of this object.
+ * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
+ * <code>k</code>, to represent a valid encoding of an instance
+ * of this object.
+ * @throws IllegalArgumentException if the byte sequence does not represent a
+ * valid encoding of an instance of this object.
+ */
+ public static GnuRSAPublicKey valueOf(final byte[] k)
+ {
+ // try RAW codec
+ if (k[0] == Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0])
+ try
+ {
+ return (GnuRSAPublicKey) new RSAKeyPairRawCodec().decodePublicKey(k);
+ }
+ catch (IllegalArgumentException ignored)
+ {
+ }
+
+ // try X.509 codec
+ return (GnuRSAPublicKey) new RSAKeyPairX509Codec().decodePublicKey(k);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the encoded form of this public key according to the designated
+ * format.</p>
+ *
+ * @param format the desired format identifier of the resulting encoding.
+ * @return the byte sequence encoding this key according to the designated
+ * format.
+ * @throws IllegalArgumentException if the format is not supported.
+ * @see RSAKeyPairRawCodec
+ */
+ public byte[] getEncoded(final int format)
+ {
+ final byte[] result;
+ switch (format)
+ {
+ case IKeyPairCodec.RAW_FORMAT:
+ result = new RSAKeyPairRawCodec().encodePublicKey(this);
+ break;
+ case IKeyPairCodec.X509_FORMAT:
+ result = new RSAKeyPairX509Codec().encodePublicKey(this);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported encoding format: "
+ + format);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the designated object is an instance of
+ * this class and has the same RSA parameter values as this one.</p>
+ *
+ * @param obj the other non-null RSA key to compare to.
+ * @return <code>true</code> if the designated object is of the same type and
+ * value as this one.
+ */
+ public boolean equals(final Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof RSAPublicKey))
+ {
+ return false;
+ }
+ final RSAPublicKey that = (RSAPublicKey) obj;
+ return super.equals(that)
+ && getPublicExponent().equals(that.getPublicExponent());
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairGenerator.java b/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
new file mode 100644
index 00000000000..9c7338f662a
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
@@ -0,0 +1,264 @@
+/* RSAKeyPairGenerator.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairGenerator;
+import gnu.java.security.util.PRNG;
+import gnu.java.security.util.Prime2;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.RSAKeyGenParameterSpec;
+import java.util.Map;
+
+/**
+ * <p>A key-pair generator for asymetric keys to use in conjunction with the RSA
+ * scheme.</p>
+ *
+ * <p>Reference:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix</a>, part B. Primitive
+ * specification and supporting documentation. Jakob Jonsson and Burt Kaliski.
+ * </li>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac/">Handbook of Applied
+ * Cryptography</a>, Alfred J. Menezes, Paul C. van Oorschot and Scott A.
+ * Vanstone. Section 11.3 RSA and related signature schemes.</li>
+ * </ol>
+ */
+public class RSAKeyPairGenerator implements IKeyPairGenerator
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The BigInteger constant 1. */
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ /** The BigInteger constant 2. */
+ private static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ /** Property name of the length (Integer) of the modulus of an RSA key. */
+ public static final String MODULUS_LENGTH = "gnu.crypto.rsa.L";
+
+ /**
+ * Property name of an optional {@link SecureRandom} instance to use. The
+ * default is to use a classloader singleton from {@link PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.rsa.prng";
+
+ /**
+ * Property name of an optional {@link RSAKeyGenParameterSpec} instance to
+ * use for this generator's <code>n</code>, and <code>e</code> values. The
+ * default is to generate <code>n</code> and use a fixed value for
+ * <code>e</.code> (Fermat's F4 number).
+ */
+ public static final String RSA_PARAMETERS = "gnu.crypto.rsa.params";
+
+ /**
+ * 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.rsa.encoding";
+
+ /** Default value for the modulus length. */
+ private static final int DEFAULT_MODULUS_LENGTH = 1024;
+
+ /** Default encoding format to use when none was specified. */
+ private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
+
+ /** The desired bit length of the modulus. */
+ private int L;
+
+ /**
+ * This implementation uses, by default, Fermat's F4 number as the public
+ * exponent.
+ */
+ private BigInteger e = BigInteger.valueOf(65537L);
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
+ /** Preferred encoding format of generated keys. */
+ private int preferredFormat;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
+
+ public String name()
+ {
+ return Registry.RSA_KPG;
+ }
+
+ /**
+ * <p>Configures this instance.</p>
+ *
+ * @param attributes the map of name/value pairs to use.
+ * @exception IllegalArgumentException if the designated MODULUS_LENGTH
+ * value is less than 1024.
+ */
+ public void setup(Map attributes)
+ {
+ // do we have a SecureRandom, or should we use our own?
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ // are we given a set of RSA params or we shall use our own?
+ RSAKeyGenParameterSpec params = (RSAKeyGenParameterSpec) attributes.get(RSA_PARAMETERS);
+
+ // find out the modulus length
+ if (params != null)
+ {
+ L = params.getKeysize();
+ e = params.getPublicExponent();
+ }
+ else
+ {
+ Integer l = (Integer) attributes.get(MODULUS_LENGTH);
+ L = (l == null ? DEFAULT_MODULUS_LENGTH : l.intValue());
+ }
+
+ if (L < 1024)
+ {
+ throw new IllegalArgumentException(MODULUS_LENGTH);
+ }
+
+ // what is the preferred encoding format
+ Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
+ preferredFormat = formatID == null ? DEFAULT_ENCODING_FORMAT
+ : formatID.intValue();
+ }
+
+ /**
+ * <p>The algorithm used here is described in <i>nessie-pss-B.pdf</i>
+ * document which is part of the RSA-PSS submission to NESSIE.</p>
+ *
+ * @return an RSA keypair.
+ */
+ public KeyPair generate()
+ {
+ BigInteger p, q, n, d;
+
+ // 1. Generate a prime p in the interval [2**(M-1), 2**M - 1], where
+ // M = CEILING(L/2), and such that GCD(p, e) = 1
+ int M = (L + 1) / 2;
+ BigInteger lower = TWO.pow(M - 1);
+ BigInteger upper = TWO.pow(M).subtract(ONE);
+ byte[] kb = new byte[(M + 7) / 8]; // enough bytes to frame M bits
+ step1: while (true)
+ {
+ nextRandomBytes(kb);
+ p = new BigInteger(1, kb).setBit(0);
+ if (p.compareTo(lower) >= 0 && p.compareTo(upper) <= 0
+ && Prime2.isProbablePrime(p) && p.gcd(e).equals(ONE))
+ {
+ break step1;
+ }
+ }
+
+ // 2. Generate a prime q such that the product of p and q is an L-bit
+ // number, and such that GCD(q, e) = 1
+ step2: while (true)
+ {
+ nextRandomBytes(kb);
+ q = new BigInteger(1, kb).setBit(0);
+ n = p.multiply(q);
+ if (n.bitLength() == L && Prime2.isProbablePrime(q)
+ && q.gcd(e).equals(ONE))
+ {
+ break step2;
+ }
+
+ // TODO: test for p != q
+ }
+
+ // TODO: ensure p < q
+
+ // 3. Put n = pq. The public key is (n, e).
+ // 4. Compute the parameters necessary for the private key K (see
+ // Section 2.2).
+ BigInteger phi = p.subtract(ONE).multiply(q.subtract(ONE));
+ d = e.modInverse(phi);
+
+ // 5. Output the public key and the private key.
+ PublicKey pubK = new GnuRSAPublicKey(preferredFormat, n, e);
+ PrivateKey secK = new GnuRSAPrivateKey(preferredFormat, p, q, e, d);
+
+ return new KeyPair(pubK, secK);
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java b/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java
new file mode 100644
index 00000000000..a7f65b61012
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java
@@ -0,0 +1,284 @@
+/* RSAKeyPairPKCS8Codec.java -- PKCS#8 Encoding/Decoding handler
+ 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.java.security.key.rsa;
+
+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;
+
+/**
+ * An implementation of an {@link IKeyPairCodec} that knows how to encode /
+ * decode PKCS#8 ASN.1 external representation of RSA private keys.
+ */
+public class RSAKeyPairPKCS8Codec
+ implements IKeyPairCodec
+{
+ private static final OID RSA_ALG_OID = new OID(Registry.RSA_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 PKCS#8 ASN.1 <i>PrivateKeyInfo</i> representation of an RSA
+ * 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
+ * }
+ * </pre>
+ *
+ * <p>The <i>privateKey</i> field, which is an OCTET STRING, contains the
+ * DER-encoded form of the RSA private key defined as:</p>
+ *
+ * <pre>
+ * RSAPrivateKey ::= SEQUENCE {
+ * version INTEGER, -- MUST be 0
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * }
+ * </pre>
+ *
+ * @return the DER encoded form of the ASN.1 representation of the
+ * <i>PrivateKeyInfo</i> field for an RSA {@link PrivateKey}..
+ * @throw InvalidParameterException if an error occurs during the marshalling
+ * process.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (! (key instanceof GnuRSAPrivateKey))
+ throw new InvalidParameterException("Wrong key type");
+
+ GnuRSAPrivateKey pk = (GnuRSAPrivateKey) key;
+ BigInteger n = pk.getN();
+ BigInteger e = pk.getE();
+ BigInteger d = pk.getPrivateExponent();
+ BigInteger p = pk.getPrimeP();
+ BigInteger q = pk.getPrimeQ();
+ BigInteger dP = pk.getPrimeExponentP();
+ BigInteger dQ = pk.getPrimeExponentQ();
+ BigInteger qInv = pk.getCrtCoefficient();
+
+ DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, RSA_ALG_OID);
+
+ ArrayList algorithmID = new ArrayList(1);
+ algorithmID.add(derOID);
+ DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ algorithmID);
+
+ DERValue derRSAVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
+ DERValue derN = new DERValue(DER.INTEGER, n);
+ DERValue derE = new DERValue(DER.INTEGER, e);
+ DERValue derD = new DERValue(DER.INTEGER, d);
+ DERValue derP = new DERValue(DER.INTEGER, p);
+ DERValue derQ = new DERValue(DER.INTEGER, q);
+ DERValue derDP = new DERValue(DER.INTEGER, dP);
+ DERValue derDQ = new DERValue(DER.INTEGER, dQ);
+ DERValue derQInv = new DERValue(DER.INTEGER, qInv);
+
+ ArrayList rsaPrivateKey = new ArrayList();
+ rsaPrivateKey.add(derRSAVersion);
+ rsaPrivateKey.add(derN);
+ rsaPrivateKey.add(derE);
+ rsaPrivateKey.add(derD);
+ rsaPrivateKey.add(derP);
+ rsaPrivateKey.add(derQ);
+ rsaPrivateKey.add(derDP);
+ rsaPrivateKey.add(derDQ);
+ rsaPrivateKey.add(derQInv);
+ DERValue derRSAPrivateKey = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ rsaPrivateKey);
+ byte[] pkBytes = derRSAPrivateKey.getEncoded();
+ DERValue derPrivateKey = new DERValue(DER.OCTET_STRING, pkBytes);
+
+ 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 x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ 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 RSA
+ * {@link PrivateKey} instance. MUST NOT be null.
+ * @return a new instance of a {@link GnuRSAPrivateKey} 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, n, e, d, p, q, dP, dQ, qInv;
+ DERReader der = new DERReader(input);
+ try
+ {
+ DERValue derPKI = der.read();
+ DerUtil.checkIsConstructed(derPKI, "Wrong PrivateKeyInfo field");
+
+ DERValue derVersion = der.read();
+ DerUtil.checkIsBigInteger(derVersion, "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(RSA_ALG_OID))
+ throw new InvalidParameterException("Unexpected OID: " + algOID);
+
+ DERValue val = der.read();
+ byte[] pkBytes = (byte[]) val.getValue();
+
+ der = new DERReader(pkBytes);
+ DERValue derRSAPrivateKey = der.read();
+ DerUtil.checkIsConstructed(derRSAPrivateKey, "Wrong RSAPrivateKey field");
+
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong RSAPrivateKey Version field");
+ version = (BigInteger) val.getValue();
+ if (version.compareTo(BigInteger.ZERO) != 0)
+ throw new InvalidParameterException("Unexpected RSAPrivateKey Version: "
+ + version);
+
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong modulus field");
+ n = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong publicExponent field");
+ e = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong privateExponent field");
+ d = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong prime1 field");
+ p = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong prime2 field");
+ q = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong exponent1 field");
+ dP = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong exponent2 field");
+ dQ = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong coefficient field");
+ qInv = (BigInteger) val.getValue();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ return new GnuRSAPrivateKey(Registry.PKCS8_ENCODING_ID, n, e, d, p, q,
+ dP, dQ, qInv);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java b/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java
new file mode 100644
index 00000000000..fb7cea99edd
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java
@@ -0,0 +1,332 @@
+/* RSAKeyPairRawCodec.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.key.IKeyPairCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * <p>An object that implements the {@link IKeyPairCodec} interface for the
+ * <i>Raw</i> format to use with RSA keypairs.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RSAKeyPairRawCodec implements IKeyPairCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.key.IKeyPairCodec interface implementation -------------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated RSA public key according to
+ * the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for an RSA public key, in this implementation, is
+ * a byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_RSA_PUBLIC_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>n</code> (the modulus) in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>n</code>,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>e</code> (the public exponent) in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>e</code>.</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ * @exception IllegalArgumentException if the designated key is not an RSA
+ * one.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ if (!(key instanceof GnuRSAPublicKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ GnuRSAPublicKey rsaKey = (GnuRSAPublicKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_RSA_PUBLIC_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // n
+ byte[] buffer = rsaKey.getModulus().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // e
+ buffer = rsaKey.getPublicExponent().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PublicKey decodePublicKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_RSA_PUBLIC_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // n
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger n = new BigInteger(1, buffer);
+
+ // e
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger e = new BigInteger(1, buffer);
+
+ return new GnuRSAPublicKey(n, e);
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated RSA private key according to
+ * the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for an RSA private key, in this implementation,
+ * is a byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_RSA_PRIVATE_KEY},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>p</code> (the first prime factor of the modulus) in internet
+ * order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>p</code>,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>q</code> (the second prime factor of the modulus) in internet
+ * order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>q</code>,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>e</code> (the public exponent) in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>e</code>,</li>
+ * <li>4-byte count of following bytes representing the RSA parameter
+ * <code>d</code> (the private exponent) in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the RSA parameter <code>d</code>,</li>
+ * </ol>
+ *
+ * @param key the key to encode.
+ * @return the <i>Raw</i> format encoding of the designated key.
+ */
+ public byte[] encodePrivateKey(PrivateKey key)
+ {
+ if (!(key instanceof GnuRSAPrivateKey))
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ GnuRSAPrivateKey rsaKey = (GnuRSAPrivateKey) key;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0]);
+ baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[1]);
+ baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[2]);
+ baos.write(Registry.MAGIC_RAW_RSA_PRIVATE_KEY[3]);
+
+ // version
+ baos.write(0x01);
+
+ // p
+ byte[] buffer = rsaKey.getPrimeP().toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // q
+ buffer = rsaKey.getPrimeQ().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // e
+ buffer = rsaKey.getPublicExponent().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // d
+ buffer = rsaKey.getPrivateExponent().toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public PrivateKey decodePrivateKey(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[0]
+ || k[1] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[1]
+ || k[2] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[2]
+ || k[3] != Registry.MAGIC_RAW_RSA_PRIVATE_KEY[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+ int i = 5;
+
+ int l;
+ byte[] buffer;
+
+ // p
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger p = new BigInteger(1, buffer);
+
+ // q
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger q = new BigInteger(1, buffer);
+
+ // e
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger e = new BigInteger(1, buffer);
+
+ // d
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger d = new BigInteger(1, buffer);
+
+ return new GnuRSAPrivateKey(p, q, e, d);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairX509Codec.java b/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairX509Codec.java
new file mode 100644
index 00000000000..1c362784b35
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/key/rsa/RSAKeyPairX509Codec.java
@@ -0,0 +1,248 @@
+/* RSAKeyPairX509Codec.java -- X.509 Encoding/Decoding handler
+ 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.java.security.key.rsa;
+
+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;
+
+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 java.util.logging.Logger;
+
+/**
+ * An implementation of an {@link IKeyPairCodec} that knows how to encode /
+ * decode X.509 ASN.1 external representation of RSA public keys.
+ */
+public class RSAKeyPairX509Codec
+ implements IKeyPairCodec
+{
+ private static final Logger log = Logger.getLogger(RSAKeyPairX509Codec.class.getName());
+ private static final OID RSA_ALG_OID = new OID(Registry.RSA_OID_STRING);
+
+ // implicit 0-arguments constructor
+
+ public int getFormatID()
+ {
+ return X509_FORMAT;
+ }
+
+ /**
+ * Returns the X.509 ASN.1 <i>SubjectPublicKeyInfo</i> representation of an
+ * RSA 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
+ * }
+ * </pre>
+ * <p>
+ * As indicated in RFC-2459: "The parameters field shall have ASN.1 type NULL
+ * for this algorithm identifier.".
+ * <p>
+ * The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
+ * DER-encoded form of the RSA public key defined as:
+ *
+ * <pre>
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ * </pre>
+ *
+ * @param key the {@link PublicKey} instance to encode. MUST be an instance of
+ * {@link GnuRSAPublicKey}.
+ * @return 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 GnuRSAPublicKey} or if an exception occurs during the
+ * marshalling process.
+ */
+ public byte[] encodePublicKey(PublicKey key)
+ {
+ log.entering(this.getClass().getName(), "encodePublicKey()", key);
+
+ if (! (key instanceof GnuRSAPublicKey))
+ throw new InvalidParameterException("key");
+
+ DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, RSA_ALG_OID);
+
+ GnuRSAPublicKey rsaKey = (GnuRSAPublicKey) key;
+ BigInteger n = rsaKey.getN();
+ BigInteger e = rsaKey.getE();
+
+ DERValue derN = new DERValue(DER.INTEGER, n);
+ DERValue derE = new DERValue(DER.INTEGER, e);
+
+ ArrayList algorithmID = new ArrayList(1);
+ algorithmID.add(derOID);
+ DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ algorithmID);
+
+ ArrayList publicKey = new ArrayList(2);
+ publicKey.add(derN);
+ publicKey.add(derE);
+ DERValue derPublicKey = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ publicKey);
+ byte[] spkBytes = derPublicKey.getEncoded();
+ DERValue derSPK = new DERValue(DER.BIT_STRING, new BitString(spkBytes));
+
+ 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 y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ log.exiting(this.getClass().getName(), "encodePublicKey()", result);
+ 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 RSA
+ * {@link PublicKey} instance. MUST NOT be null.
+ * @return a new instance of a {@link GnuRSAPublicKey} 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)
+ {
+ log.entering(this.getClass().getName(), "decodePublicKey()", input);
+
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ BigInteger n, e;
+ 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(RSA_ALG_OID))
+ throw new InvalidParameterException("Unexpected OID: " + algOID);
+
+ // rfc-2459 states that this field is OPTIONAL but NULL if/when present
+ DERValue val = der.read();
+ if (val.getTag() == DER.NULL)
+ val = der.read();
+
+ if (! (val.getValue() instanceof BitString))
+ throw new InvalidParameterException("Wrong SubjectPublicKey field");
+
+ byte[] spkBytes = ((BitString) val.getValue()).toByteArray();
+
+ der = new DERReader(spkBytes);
+ val = der.read();
+ DerUtil.checkIsConstructed(derAlgorithmID, "Wrong subjectPublicKey field");
+
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong modulus field");
+ n = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong publicExponent field");
+ e = (BigInteger) val.getValue();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ PublicKey result = new GnuRSAPublicKey(Registry.X509_ENCODING_ID, n, e);
+ log.exiting(this.getClass().getName(), "decodePublicKey()", result);
+ return result;
+ }
+
+ /**
+ * @throws InvalidParameterException ALWAYS.
+ */
+ public PrivateKey decodePrivateKey(byte[] input)
+ {
+ throw new InvalidParameterException("Wrong format for private keys");
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/prng/BasePRNG.java b/libjava/classpath/gnu/java/security/prng/BasePRNG.java
new file mode 100644
index 00000000000..fe815d7004e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/prng/BasePRNG.java
@@ -0,0 +1,199 @@
+/* BasePRNG.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import java.util.Map;
+
+/**
+ * <p>An abstract class to facilitate implementing PRNG algorithms.</p>
+ */
+public abstract class BasePRNG implements IRandom
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name prefix of the PRNG algorithm. */
+ protected String name;
+
+ /** Indicate if this instance has already been initialised or not. */
+ protected boolean initialised;
+
+ /** A temporary buffer to serve random bytes. */
+ protected byte[] buffer;
+
+ /** The index into buffer of where the next byte will come from. */
+ protected int ndx;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial constructor for use by concrete subclasses.</p>
+ *
+ * @param name the canonical name of this instance.
+ */
+ protected BasePRNG(String name)
+ {
+ super();
+
+ this.name = name;
+ initialised = false;
+ buffer = new byte[0];
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // IRandom interface implementation ----------------------------------------
+
+ public String name()
+ {
+ return name;
+ }
+
+ public void init(Map attributes)
+ {
+ this.setup(attributes);
+
+ ndx = 0;
+ initialised = true;
+ }
+
+ public byte nextByte() throws IllegalStateException, LimitReachedException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException();
+ }
+ return nextByteInternal();
+ }
+
+ public void nextBytes(byte[] out) throws IllegalStateException,
+ LimitReachedException
+ {
+ nextBytes(out, 0, out.length);
+ }
+
+ public void nextBytes(byte[] out, int offset, int length)
+ throws IllegalStateException, LimitReachedException
+ {
+ if (!initialised)
+ throw new IllegalStateException("not initialized");
+
+ if (length == 0)
+ return;
+
+ if (offset < 0 || length < 0 || offset + length > out.length)
+ throw new ArrayIndexOutOfBoundsException("offset=" + offset + " length="
+ + length + " limit="
+ + out.length);
+
+ if (ndx >= buffer.length)
+ {
+ fillBlock();
+ ndx = 0;
+ }
+ int count = 0;
+ while (count < length)
+ {
+ int amount = Math.min(buffer.length - ndx, length - count);
+ System.arraycopy(buffer, ndx, out, offset + count, amount);
+ count += amount;
+ ndx += amount;
+ if (ndx >= buffer.length)
+ {
+ fillBlock();
+ ndx = 0;
+ }
+ }
+ }
+
+ public void addRandomByte(byte b)
+ {
+ throw new UnsupportedOperationException("random state is non-modifiable");
+ }
+
+ public void addRandomBytes(byte[] buffer)
+ {
+ addRandomBytes(buffer, 0, buffer.length);
+ }
+
+ public void addRandomBytes(byte[] buffer, int offset, int length)
+ {
+ throw new UnsupportedOperationException("random state is non-modifiable");
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ public boolean isInitialised()
+ {
+ return initialised;
+ }
+
+ private byte nextByteInternal() throws LimitReachedException
+ {
+ if (ndx >= buffer.length)
+ {
+ this.fillBlock();
+ ndx = 0;
+ }
+
+ return buffer[ndx++];
+ }
+
+ // abstract methods to implement by subclasses -----------------------------
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ BasePRNG result = (BasePRNG) super.clone();
+ if (this.buffer != null)
+ result.buffer = (byte[]) this.buffer.clone();
+
+ return result;
+ }
+
+ public abstract void setup(Map attributes);
+
+ public abstract void fillBlock() throws LimitReachedException;
+}
diff --git a/libjava/classpath/gnu/java/security/prng/EntropySource.java b/libjava/classpath/gnu/java/security/prng/EntropySource.java
new file mode 100644
index 00000000000..260c668f8df
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/prng/EntropySource.java
@@ -0,0 +1,62 @@
+/* EntropySource.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+/**
+ * A generic interface for adding random bytes to an entropy pool.
+ */
+public interface EntropySource
+{
+
+ /**
+ * Returns the estimated quality of this source. This value should be
+ * between 0 and 100 (the running quality is computed as a percentage,
+ * 100 percent being perfect-quality).
+ *
+ * @return The quality.
+ */
+ double quality();
+
+ /**
+ * Returns a new buffer with the next random bytes to add.
+ *
+ * @return The next random bytes.
+ */
+ byte[] nextBytes();
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/java/security/prng/IRandom.java b/libjava/classpath/gnu/java/security/prng/IRandom.java
new file mode 100644
index 00000000000..2c89e7ad56f
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/prng/IRandom.java
@@ -0,0 +1,180 @@
+/* IRandom.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import java.util.Map;
+
+/**
+ * <p>The basic visible methods of any pseudo-random number generator.</p>
+ *
+ * <p>The [HAC] defines a PRNG (as implemented in this library) as follows:</p>
+ *
+ * <ul>
+ * <li>"5.6 Definition: A pseudorandom bit generator (PRBG) is said to pass
+ * the <em>next-bit test</em> if there is no polynomial-time algorithm which,
+ * on input of the first <code>L</code> bits of an output sequence <code>S</code>,
+ * can predict the <code>(L+1)</code>st bit of <code>S</code> with a
+ * probability significantly grater than <code>1/2</code>."</li>
+ *
+ * <li>"5.8 Definition: A PRBG that passes the <em>next-bit test</em>
+ * (possibly under some plausible but unproved mathematical assumption such
+ * as the intractability of factoring integers) is called a
+ * <em>cryptographically secure pseudorandom bit generator</em> (CSPRBG)."</li>
+ * </ul>
+ *
+ * <p><b>IMPLEMENTATION NOTE</b>: Although all the concrete classes in this
+ * package implement the {@link Cloneable} interface, it is important to note
+ * here that such an operation, for those algorithms that use an underlting
+ * symmetric key block cipher, <b>DOES NOT</b> clone any session key material
+ * that may have been used in initialising the source PRNG (the instance to be
+ * cloned). Instead a clone of an already initialised PRNG, that uses and
+ * underlying symmetric key block cipher, is another instance with a clone of
+ * the same cipher that operates with the <b>same block size</b> but without any
+ * knowledge of neither key material nor key size.</p>
+ *
+ * <p>References:</p>
+ *
+ * <ol>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
+ * Applied Cryptography.<br>
+ * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
+ * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
+ * </ol>
+ */
+public interface IRandom extends Cloneable
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of this instance.</p>
+ *
+ * @return the canonical name of this instance. */
+ String name();
+
+ /**
+ * <p>Initialises the pseudo-random number generator scheme with the
+ * appropriate attributes.</p>
+ *
+ * @param attributes a set of name-value pairs that describe the desired
+ * future instance behaviour.
+ * @exception IllegalArgumentException if at least one of the defined name/
+ * value pairs contains invalid data.
+ */
+ void init(Map attributes);
+
+ /**
+ * <p>Returns the next 8 bits of random data generated from this instance.</p>
+ *
+ * @return the next 8 bits of random data generated from this instance.
+ * @exception IllegalStateException if the instance is not yet initialised.
+ * @exception LimitReachedException if this instance has reached its
+ * theoretical limit for generating non-repetitive pseudo-random data.
+ */
+ byte nextByte() throws IllegalStateException, LimitReachedException;
+
+ /**
+ * <p>Fills the designated byte array, starting from byte at index
+ * <code>offset</code>, for a maximum of <code>length</code> bytes with the
+ * output of this generator instance.
+ *
+ * @param out the placeholder to contain the generated random bytes.
+ * @param offset the starting index in <i>out</i> to consider. This method
+ * does nothing if this parameter is not within <code>0</code> and
+ * <code>out.length</code>.
+ * @param length the maximum number of required random bytes. This method
+ * does nothing if this parameter is less than <code>1</code>.
+ * @exception IllegalStateException if the instance is not yet initialised.
+ * @exception LimitReachedException if this instance has reached its
+ * theoretical limit for generating non-repetitive pseudo-random data.
+ */
+ void nextBytes(byte[] out, int offset, int length)
+ throws IllegalStateException, LimitReachedException;
+
+ /**
+ * <p>Supplement, or possibly replace, the random state of this PRNG with
+ * a random byte.</p>
+ *
+ * <p>Implementations are not required to implement this method in any
+ * meaningful way; this may be a no-operation, and implementations may
+ * throw an {@link UnsupportedOperationException}.</p>
+ *
+ * @param b The byte to add.
+ */
+ void addRandomByte(byte b);
+
+ /**
+ * <p>Supplement, or possibly replace, the random state of this PRNG with
+ * a sequence of new random bytes.</p>
+ *
+ * <p>Implementations are not required to implement this method in any
+ * meaningful way; this may be a no-operation, and implementations may
+ * throw an {@link UnsupportedOperationException}.</p>
+ *
+ * @param in The buffer of new random bytes to add.
+ */
+ void addRandomBytes(byte[] in);
+
+ /**
+ * <p>Supplement, or possibly replace, the random state of this PRNG with
+ * a sequence of new random bytes.</p>
+ *
+ * <p>Implementations are not required to implement this method in any
+ * meaningful way; this may be a no-operation, and implementations may
+ * throw an {@link UnsupportedOperationException}.</p>
+ *
+ * @param in The buffer of new random bytes to add.
+ * @param offset The offset from whence to begin reading random bytes.
+ * @param length The number of random bytes to add.
+ * @exception IndexOutOfBoundsException If <i>offset</i>, <i>length</i>,
+ * or <i>offset</i>+<i>length</i> is out of bounds.
+ */
+ void addRandomBytes(byte[] in, int offset, int length);
+
+ /**
+ * <p>Returns a clone copy of this instance.</p>
+ *
+ * @return a clone copy of this instance.
+ */
+ Object clone() throws CloneNotSupportedException;
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/java/security/prng/LimitReachedException.java b/libjava/classpath/gnu/java/security/prng/LimitReachedException.java
new file mode 100644
index 00000000000..2fd8bfa7fd1
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/prng/LimitReachedException.java
@@ -0,0 +1,69 @@
+/* LimitReachedException.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+/**
+ * A checked exception that indicates that a pseudo random number generated has
+ * reached its theoretical limit in generating random bytes.
+ */
+public class LimitReachedException extends Exception
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ public LimitReachedException()
+ {
+ super();
+ }
+
+ public LimitReachedException(String msg)
+ {
+ super(msg);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instant methods
+ // -------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/java/security/prng/MDGenerator.java b/libjava/classpath/gnu/java/security/prng/MDGenerator.java
new file mode 100644
index 00000000000..255647d1c5f
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/prng/MDGenerator.java
@@ -0,0 +1,135 @@
+/* MDGenerator.java --
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+
+import java.util.Map;
+
+/**
+ * <p>A simple pseudo-random number generator that relies on a hash algorithm,
+ * that (a) starts its operation by hashing a <code>seed</code>, and then (b)
+ * continuously re-hashing its output. If no hash algorithm name is specified
+ * in the {@link Map} of attributes used to initialise the instance then the
+ * SHA-160 algorithm is used as the underlying hash function. Also, if no
+ * <code>seed</code> is given, an empty octet sequence is used.</p>
+ */
+public class MDGenerator extends BasePRNG implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Property name of underlying hash algorithm for this generator. */
+ public static final String MD_NAME = "gnu.crypto.prng.md.hash.name";
+
+ /** Property name of seed material. */
+ public static final String SEEED = "gnu.crypto.prng.md.seed";
+
+ /** The underlying hash instance. */
+ private IMessageDigest md;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public MDGenerator()
+ {
+ super(Registry.MD_PRNG);
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in BaseRandom ------------------------
+
+ public void setup(Map attributes)
+ {
+ // find out which hash to use
+ String underlyingMD = (String) attributes.get(MD_NAME);
+ if (underlyingMD == null)
+ {
+ if (md == null)
+ { // happy birthday
+ // ensure we have a reliable implementation of this hash
+ md = HashFactory.getInstance(Registry.SHA160_HASH);
+ }
+ else
+ { // a clone. reset it for reuse
+ md.reset();
+ }
+ }
+ else
+ { // ensure we have a reliable implementation of this hash
+ md = HashFactory.getInstance(underlyingMD);
+ }
+
+ // get the seeed
+ byte[] seed = (byte[]) attributes.get(SEEED);
+ if (seed == null)
+ {
+ seed = new byte[0];
+ }
+
+ md.update(seed, 0, seed.length);
+ }
+
+ public void fillBlock() throws LimitReachedException
+ {
+ IMessageDigest mdc = (IMessageDigest) md.clone();
+ buffer = mdc.digest();
+ md.update(buffer, 0, buffer.length);
+ }
+
+ // Cloneable interface implementation ---------------------------------------
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ MDGenerator result = (MDGenerator) super.clone();
+ if (this.md != null)
+ result.md = (IMessageDigest) this.md.clone();
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/prng/PRNGFactory.java b/libjava/classpath/gnu/java/security/prng/PRNGFactory.java
new file mode 100644
index 00000000000..8b5141456e6
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/prng/PRNGFactory.java
@@ -0,0 +1,109 @@
+/* PRNGFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import gnu.java.security.Registry;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * <p>A Factory to instantiate pseudo random number generators.</p>
+ */
+public class PRNGFactory implements Registry
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce <i>Singleton</i> pattern. */
+ protected PRNGFactory()
+ {
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of a padding algorithm given its name.</p>
+ *
+ * @param prng the case-insensitive name of the PRNG.
+ * @return an instance of the pseudo-random number generator.
+ * @exception InternalError if the implementation does not pass its self-
+ * test.
+ */
+ public static final IRandom getInstance(String prng)
+ {
+ if (prng == null)
+ {
+ return null;
+ }
+
+ prng = prng.trim();
+ IRandom result = null;
+ if (prng.equalsIgnoreCase(MD_PRNG))
+ {
+ result = new MDGenerator();
+ }
+
+ return result;
+ }
+
+ /**
+ * <p>Returns a {@link Set} of names of padding algorithms supported by this
+ * <i>Factory</i>.</p>
+ *
+ * @return a {@link Set} of pseudo-random number generator algorithm names
+ * (Strings).
+ */
+ public static final Set getNames()
+ {
+ HashSet hs = new HashSet();
+ hs.add(MD_PRNG);
+ return Collections.unmodifiableSet(hs);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+}
diff --git a/libjava/classpath/gnu/java/security/prng/RandomEvent.java b/libjava/classpath/gnu/java/security/prng/RandomEvent.java
new file mode 100644
index 00000000000..c07062125dc
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/prng/RandomEvent.java
@@ -0,0 +1,82 @@
+/* RandomEvent.java -- an event with random data.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import java.util.EventObject;
+
+/**
+ * An interface for entropy accumulators that will be notified of random
+ * events.
+ */
+public class RandomEvent extends EventObject
+{
+
+ private final byte sourceNumber;
+
+ private final byte poolNumber;
+
+ private final byte[] data;
+
+ public RandomEvent(Object source, byte sourceNumber, byte poolNumber,
+ byte[] data)
+ {
+ super(source);
+ this.sourceNumber = sourceNumber;
+ this.poolNumber = poolNumber;
+ if (data.length == 0 || data.length > 32)
+ throw new IllegalArgumentException(
+ "random events take between 1 and 32 bytes of data");
+ this.data = (byte[]) data.clone();
+ }
+
+ public byte getSourceNumber()
+ {
+ return sourceNumber;
+ }
+
+ public byte getPoolNumber()
+ {
+ return poolNumber;
+ }
+
+ public byte[] getData()
+ {
+ return data;
+ }
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/java/security/prng/RandomEventListener.java b/libjava/classpath/gnu/java/security/prng/RandomEventListener.java
new file mode 100644
index 00000000000..1dc14619fe9
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/prng/RandomEventListener.java
@@ -0,0 +1,50 @@
+/* RandomEventListener.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.prng;
+
+import java.util.EventListener;
+
+/**
+ * An interface for entropy accumulators that will be notified of random
+ * events.
+ */
+public interface RandomEventListener extends EventListener
+{
+ void addRandomEvent(RandomEvent event);
+} \ No newline at end of file
diff --git a/libjava/classpath/gnu/java/security/provider/DSAKeyFactory.java b/libjava/classpath/gnu/java/security/provider/DSAKeyFactory.java
deleted file mode 100644
index 7e154e27473..00000000000
--- a/libjava/classpath/gnu/java/security/provider/DSAKeyFactory.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/* DSAKeyFactory.java -- DSA key factory.
- Copyright (C) 2003 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.java.security.provider;
-
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.KeyFactorySpi;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-import java.security.spec.DSAPrivateKeySpec;
-import java.security.spec.DSAPublicKeySpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-
-/**
- * DSA key factory.
- *
- * @author Casey Marshall (rsdio@metastatic.org)
- */
-public class DSAKeyFactory extends KeyFactorySpi
-{
-
- // Constructor.
- // ------------------------------------------------------------------------
-
- public DSAKeyFactory()
- {
- super();
- }
-
- // Instance methods.
- // ------------------------------------------------------------------------
-
- protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
- throws InvalidKeySpecException
- {
- if (!(keySpec instanceof DSAPrivateKeySpec))
- throw new InvalidKeySpecException();
- return new GnuDSAPrivateKey(
- ((DSAPrivateKeySpec) keySpec).getX(),
- ((DSAPrivateKeySpec) keySpec).getP(),
- ((DSAPrivateKeySpec) keySpec).getQ(),
- ((DSAPrivateKeySpec) keySpec).getG());
- }
-
- protected PublicKey engineGeneratePublic(KeySpec keySpec)
- throws InvalidKeySpecException
- {
- if (!(keySpec instanceof DSAPublicKeySpec))
- throw new InvalidKeySpecException();
- return new GnuDSAPublicKey(
- ((DSAPublicKeySpec) keySpec).getY(),
- ((DSAPublicKeySpec) keySpec).getP(),
- ((DSAPublicKeySpec) keySpec).getQ(),
- ((DSAPublicKeySpec) keySpec).getG());
- }
-
- protected KeySpec engineGetKeySpec(Key key, Class keySpec)
- throws InvalidKeySpecException
- {
- if ((key instanceof DSAPublicKey) &&
- keySpec.isAssignableFrom(DSAPublicKeySpec.class))
- {
- return new DSAPublicKeySpec(((DSAPublicKey) key).getY(),
- ((DSAPublicKey) key).getParams().getP(),
- ((DSAPublicKey) key).getParams().getQ(),
- ((DSAPublicKey) key).getParams().getG());
- }
- if ((key instanceof DSAPrivateKey) &&
- keySpec.isAssignableFrom(DSAPrivateKeySpec.class))
- {
- return new DSAPrivateKeySpec(((DSAPrivateKey) key).getX(),
- ((DSAPrivateKey) key).getParams().getP(),
- ((DSAPrivateKey) key).getParams().getQ(),
- ((DSAPrivateKey) key).getParams().getG());
- }
- throw new InvalidKeySpecException();
- }
-
- protected Key engineTranslateKey(Key key) throws InvalidKeyException
- {
- if ((key instanceof GnuDSAPublicKey) || (key instanceof GnuDSAPrivateKey))
- return key;
- if (key instanceof DSAPublicKey)
- return new GnuDSAPublicKey(((DSAPublicKey) key).getY(),
- ((DSAPublicKey) key).getParams().getP(),
- ((DSAPublicKey) key).getParams().getQ(),
- ((DSAPublicKey) key).getParams().getG());
- if (key instanceof DSAPrivateKey)
- return new GnuDSAPrivateKey(((DSAPrivateKey) key).getX(),
- ((DSAPrivateKey) key).getParams().getP(),
- ((DSAPrivateKey) key).getParams().getQ(),
- ((DSAPrivateKey) key).getParams().getG());
- throw new InvalidKeyException();
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/DSAKeyPairGenerator.java b/libjava/classpath/gnu/java/security/provider/DSAKeyPairGenerator.java
deleted file mode 100644
index ddd1800a717..00000000000
--- a/libjava/classpath/gnu/java/security/provider/DSAKeyPairGenerator.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/* GnuDSAKeyPairGenerator.java --- Gnu DSA Key Pair Generator
- Copyright (C) 1999, 2005 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.java.security.provider;
-
-import java.math.BigInteger;
-import java.security.AlgorithmParameterGenerator;
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidParameterException;
-import java.security.KeyPair;
-import java.security.KeyPairGeneratorSpi;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.interfaces.DSAParams;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.DSAParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.util.Random;
-
-public class DSAKeyPairGenerator extends KeyPairGeneratorSpi
- implements java.security.interfaces.DSAKeyPairGenerator
-{
-int keysize;
-SecureRandom random;
-private BigInteger q = null; // the small prime
-private BigInteger p = null; // the big prime
-private BigInteger g = null;
-
-public DSAKeyPairGenerator()
-{
- keysize = 1024;
- getDefaults ();
-}
-
-public void initialize(int keysize, SecureRandom random)
-{
- initialize (keysize, false, random);
-}
-
-public void initialize(AlgorithmParameterSpec params,
- SecureRandom random)
- throws InvalidAlgorithmParameterException
-{
- if( !( params instanceof DSAParameterSpec ) )
- throw new InvalidAlgorithmParameterException("Must be DSAParameterSpec");
-
- try
- {
- initialize ((DSAParams) params, random);
- }
- catch (InvalidParameterException ipe)
- {
- InvalidAlgorithmParameterException iape =
- new InvalidAlgorithmParameterException();
- iape.initCause (ipe);
- throw iape;
- }
-}
-
-public void initialize (DSAParams params, SecureRandom random)
-{
- DSAParameterSpec dsaparameterspec = (DSAParameterSpec)params;
- if (dsaparameterspec.getP() == null
- || dsaparameterspec.getQ() == null
- || dsaparameterspec.getG() == null)
- {
- throw new InvalidParameterException ("none of p, q, or g may be null");
- }
- p = dsaparameterspec.getP();
- q = dsaparameterspec.getQ();
- g = dsaparameterspec.getG();
- this.random = random;
-}
-
-public void initialize(int modlen, boolean genParams, SecureRandom random)
- throws InvalidParameterException
-{
- if( ((modlen % 64) != 0) || (modlen < 512) || (modlen > 1024) )
- throw new InvalidParameterException();
-
- this.keysize = modlen;
- this.random = random;
- if (this.random == null)
- {
- this.random = new SecureRandom ();
- }
- if (genParams)
- {
- try
- {
- AlgorithmParameterGenerator apgDSA = AlgorithmParameterGenerator.getInstance("DSA");
- apgDSA.init (modlen, random);
- AlgorithmParameters apDSA = apgDSA.generateParameters();
- DSAParameterSpec dsaparameterspec = (DSAParameterSpec)apDSA.getParameterSpec( DSAParameterSpec.class );
- p = dsaparameterspec.getP();
- q = dsaparameterspec.getQ();
- g = dsaparameterspec.getG();
- }
- catch (NoSuchAlgorithmException nsae)
- {
- InvalidParameterException ipe =
- new InvalidParameterException ("can't generate DSA parameters");
- ipe.initCause (nsae);
- throw ipe;
- }
- catch (InvalidParameterSpecException ipse)
- {
- InvalidParameterException ipe =
- new InvalidParameterException ("can't generate DSA parameters");
- ipe.initCause (ipse);
- throw ipe;
- }
- }
- else if (!getDefaults ())
- {
- throw new InvalidParameterException ("unsupported key size: " + modlen);
- }
-}
-
-public KeyPair generateKeyPair()
-{
- if (random == null)
- {
- random = new SecureRandom ();
- }
-
- BigInteger x = new BigInteger( 159, random );
-
- BigInteger y = g.modPow( x, p );
-
- return new KeyPair( new GnuDSAPublicKey(y,p,q,g), new GnuDSAPrivateKey(x,p,q,g));
- //return new KeyPair( public, private );
-}
-
-//These constants are Sun's Constants copied from the
-//Cryptography Specification
-private boolean getDefaults()
-{
- if( keysize == 512) {
- p = new BigInteger("fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e17", 16);
- q = new BigInteger("962eddcc369cba8ebb260ee6b6a126d9346e38c5", 16);
- g = new BigInteger("678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4", 16);
- return true;
- } else if( keysize == 768) {
- p = new BigInteger("e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5d890141922d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a22219d470bce7d777d4a21fbe9c270b57f607002f3cef8393694cf45ee3688c11a8c56ab127a3daf", 16);
- q = new BigInteger("9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511", 16);
- g = new BigInteger("30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7a31d23c4dbbcbe06174544401a5b2c020965d8c2bd2171d3668445771f74ba084d2029d83c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a7064f316933a346d3f529252", 16);
- return true;
- } else if( keysize == 1024) {
- p = new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16);
- q = new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16);
- g = new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d0782675159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16);
- return true;
- }
- return false;
-}
-
-}
diff --git a/libjava/classpath/gnu/java/security/provider/DSAParameters.java b/libjava/classpath/gnu/java/security/provider/DSAParameters.java
deleted file mode 100644
index 77d648956ee..00000000000
--- a/libjava/classpath/gnu/java/security/provider/DSAParameters.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/* DSAParameters.java --- DSA Parameters Implementation
- Copyright (C) 1999, 2003, 2004 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.java.security.provider;
-
-import gnu.java.io.ASN1ParsingException;
-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 java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.AlgorithmParametersSpi;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.DSAParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.util.ArrayList;
-
-/*
- ASN.1 Encoding for DSA from rfc2459
-
- id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040)
- x9cm(4) 1 }
-
- Dss-Parms ::= SEQUENCE {
- p INTEGER,
- q INTEGER,
- g INTEGER }
-
-*/
-public class DSAParameters extends AlgorithmParametersSpi
-{
-private BigInteger q; // the small prime
-private BigInteger p; // the big prime
-private BigInteger g;
-
-
-public void engineInit(AlgorithmParameterSpec paramSpec)
- throws InvalidParameterSpecException
-{
- if( paramSpec instanceof DSAParameterSpec ) {
- DSAParameterSpec dsaParamSpec = (DSAParameterSpec)paramSpec;
- p = dsaParamSpec.getP();
- q = dsaParamSpec.getQ();
- g = dsaParamSpec.getG();
- }
- else
- throw new InvalidParameterSpecException("Only accepts DSAParameterSpec");
-}
-
-public void engineInit(byte[] params)
- throws IOException
-{
- DERReader in = new DERReader(params);
- DERValue val = in.read();
- if (val.getValue() != DER.CONSTRUCTED_VALUE)
- throw new ASN1ParsingException("badly formed parameters");
- try
- {
- p = (BigInteger) in.read().getValue();
- q = (BigInteger) in.read().getValue();
- g = (BigInteger) in.read().getValue();
- }
- catch (Exception x)
- {
- throw new ASN1ParsingException("badly formed parameters");
- }
-}
-
-public void engineInit(byte[] params, String format)
- throws IOException
-{
- if( !format.equals("ASN.1") )
- throw new IOException("Invalid Format: Only accepts ASN.1");
- engineInit( params );
-}
-
-public AlgorithmParameterSpec engineGetParameterSpec(Class paramSpec)
- throws InvalidParameterSpecException
-{
- if( paramSpec.isAssignableFrom(DSAParameterSpec.class) )
- return new DSAParameterSpec(p, q, g);
- else
- throw new InvalidParameterSpecException("Only accepts DSAParameterSpec");
-}
-
-public byte[] engineGetEncoded()
- throws IOException
-{
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- ArrayList seq = new ArrayList(3);
- seq.add(new DERValue(DER.INTEGER, p));
- seq.add(new DERValue(DER.INTEGER, q));
- seq.add(new DERValue(DER.INTEGER, g));
- DERWriter.write(bout, new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, seq));
- return bout.toByteArray();
-}
-
-
-public byte[] engineGetEncoded(String format)
- throws IOException
-{
- if( !format.equals("ASN.1") )
- throw new IOException("Invalid Format: Only accepts ASN.1");
- return engineGetEncoded();
-}
-
-public String engineToString()
-{
- return ("q: " + q + " p: " + p + " g: " + g);
-}
-
-}
diff --git a/libjava/classpath/gnu/java/security/provider/DSASignature.java b/libjava/classpath/gnu/java/security/provider/DSASignature.java
deleted file mode 100644
index 1d3875d28e3..00000000000
--- a/libjava/classpath/gnu/java/security/provider/DSASignature.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/* DSASignature.java --
- Copyright (C) 1999, 2003, 2004 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.java.security.provider;
-
-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 java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.InvalidParameterException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.SignatureException;
-import java.security.SignatureSpi;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-import java.security.spec.AlgorithmParameterSpec;
-import java.util.ArrayList;
-import java.util.Random;
-
-public class DSASignature extends SignatureSpi
-{
- private DSAPublicKey publicKey;
- private DSAPrivateKey privateKey;
- private final MessageDigest digest;
- private final SecureRandom random;
-
- public DSASignature() throws NoSuchAlgorithmException
- {
- random = new SecureRandom();
- digest = MessageDigest.getInstance ("SHA1");
- }
-
- private void init()
- {
- digest.reset();
- }
-
- public void engineInitVerify (PublicKey publicKey)
- throws InvalidKeyException
- {
- if (publicKey instanceof DSAPublicKey)
- this.publicKey = (DSAPublicKey) publicKey;
- else
- throw new InvalidKeyException();
- init();
- }
-
- public void engineInitSign (PrivateKey privateKey)
- throws InvalidKeyException
- {
- if (privateKey instanceof DSAPrivateKey)
- this.privateKey = (DSAPrivateKey) privateKey;
- else
- throw new InvalidKeyException ("not a DSA private key");
-
- init();
- }
-
- public void engineInitSign (PrivateKey privateKey,
- SecureRandom random)
- throws InvalidKeyException
- {
- if (privateKey instanceof DSAPrivateKey)
- this.privateKey = (DSAPrivateKey) privateKey;
- else
- throw new InvalidKeyException ("not a DSA private key");
-
- appRandom = random;
- init();
- }
-
- public void engineUpdate(byte b)
- throws SignatureException
- {
- digest.update (b);
- }
-
- public void engineUpdate (byte[] b, int off, int len)
- throws SignatureException
- {
- digest.update (b, off, len);
- }
-
- public byte[] engineSign() throws SignatureException
- {
- if (privateKey == null)
- throw new SignatureException ("not initialized for signing");
-
- try
- {
- BigInteger g = privateKey.getParams().getG();
- BigInteger p = privateKey.getParams().getP();
- BigInteger q = privateKey.getParams().getQ();
-
- BigInteger x = privateKey.getX();
-
- BigInteger k = new BigInteger (159, appRandom != null ? appRandom : random);
-
- BigInteger r = g.modPow(k, p);
- r = r.mod(q);
-
- byte bytes[] = digest.digest();
- BigInteger sha = new BigInteger (1, bytes);
-
- BigInteger s = sha.add (x.multiply (r));
- s = s.multiply (k.modInverse(q)).mod (q);
-
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- ArrayList seq = new ArrayList (2);
- seq.add(0, new DERValue (DER.INTEGER, r));
- seq.add(1, new DERValue (DER.INTEGER, s));
- DERWriter.write (bout, new DERValue (DER.CONSTRUCTED | DER.SEQUENCE, seq));
- return bout.toByteArray();
- }
- catch (IOException ioe)
- {
- SignatureException se = new SignatureException();
- se.initCause (ioe);
- throw se;
- }
- catch (ArithmeticException ae)
- {
- SignatureException se = new SignatureException();
- se.initCause (ae);
- throw se;
- }
- }
-
- public int engineSign (byte[] outbuf, int offset, int len)
- throws SignatureException
- {
- byte tmp[] = engineSign();
- if (tmp.length > len)
- throw new SignatureException ("output buffer too short");
- System.arraycopy (tmp, 0, outbuf, offset, tmp.length);
- return tmp.length;
- }
-
- public boolean engineVerify (byte[] sigBytes)
- throws SignatureException
- {
- // Decode sigBytes from ASN.1 DER encoding
- try
- {
- DERReader in = new DERReader (sigBytes);
- DERValue val = in.read();
- if (!val.isConstructed())
- throw new SignatureException ("badly formed signature");
- BigInteger r = (BigInteger) in.read().getValue();
- BigInteger s = (BigInteger) in.read().getValue();
-
- BigInteger g = publicKey.getParams().getG();
- BigInteger p = publicKey.getParams().getP();
- BigInteger q = publicKey.getParams().getQ();
-
- BigInteger y = publicKey.getY();
-
- BigInteger w = s.modInverse (q);
-
- byte bytes[] = digest.digest();
- BigInteger sha = new BigInteger (1, bytes);
-
- BigInteger u1 = w.multiply (sha).mod ( q );
-
- BigInteger u2 = r.multiply (w).mod(q);
-
- BigInteger v = g.modPow (u1, p).multiply (y.modPow (u2, p)).mod (p).mod (q);
-
- if (v.equals (r))
- return true;
- else
- return false;
- }
- catch (IOException ioe)
- {
- SignatureException se = new SignatureException ("badly formed signature");
- se.initCause (ioe);
- throw se;
- }
- }
-
- public void engineSetParameter (String param,
- Object value)
- throws InvalidParameterException
- {
- throw new InvalidParameterException();
- }
-
- public void engineSetParameter (AlgorithmParameterSpec params)
- throws InvalidAlgorithmParameterException
- {
- throw new InvalidParameterException();
-
- }
-
- public Object engineGetParameter (String param)
- throws InvalidParameterException
- {
- throw new InvalidParameterException();
- }
-
- public Object clone() throws CloneNotSupportedException
- {
- return super.clone();
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/DiffieHellmanKeyFactoryImpl.java b/libjava/classpath/gnu/java/security/provider/DiffieHellmanKeyFactoryImpl.java
deleted file mode 100644
index 591fc688cc0..00000000000
--- a/libjava/classpath/gnu/java/security/provider/DiffieHellmanKeyFactoryImpl.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/* DiffieHellmanKeyFactoryImpl.java --
- Copyright (C) 2005 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.java.security.provider;
-
-import gnu.javax.crypto.GnuDHPrivateKey;
-
-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 javax.crypto.spec.DHParameterSpec;
-import javax.crypto.spec.DHPrivateKeySpec;
-import javax.crypto.spec.DHPublicKeySpec;
-
-import javax.crypto.interfaces.DHPrivateKey;
-import javax.crypto.interfaces.DHPublicKey;
-
-public class DiffieHellmanKeyFactoryImpl extends KeyFactorySpi
-{
- protected PrivateKey engineGeneratePrivate (final KeySpec spec)
- throws InvalidKeySpecException
- {
- if (spec instanceof DHPrivateKeySpec)
- {
- DHPrivateKeySpec dh = (DHPrivateKeySpec) spec;
- return new GnuDHPrivateKey (dh.getX (),
- new DHParameterSpec (dh.getP (), dh.getG ()));
- }
- throw new InvalidKeySpecException ();
- }
-
- protected PublicKey engineGeneratePublic (final KeySpec spec)
- throws InvalidKeySpecException
- {
- if (spec instanceof DHPublicKeySpec)
- {
- DHPublicKeySpec dh = (DHPublicKeySpec) spec;
- return new GnuDHPublicKey (new DHParameterSpec (dh.getP (), dh.getG ()),
- dh.getY(), null);
- }
- throw new InvalidKeySpecException ();
- }
-
- protected KeySpec engineGetKeySpec (final Key key, final Class specClass)
- throws InvalidKeySpecException
- {
- if (key instanceof DHPrivateKey)
- {
- if (DHPrivateKeySpec.class.isAssignableFrom (specClass))
- {
- DHParameterSpec params = ((DHPrivateKey) key).getParams ();
- return new DHPrivateKeySpec (((DHPrivateKey) key).getX (),
- params.getP (), params.getG ());
- }
- }
- if (key instanceof DHPublicKey)
- {
- if (DHPublicKeySpec.class.isAssignableFrom (specClass))
- {
- DHParameterSpec params = ((DHPublicKey) key).getParams ();
- return new DHPublicKeySpec (((DHPublicKey) key).getY (),
- params.getP (), params.getG ());
- }
- }
- throw new InvalidKeySpecException ();
- }
-
- protected Key engineTranslateKey (final Key key)
- throws InvalidKeyException
- {
- if (key instanceof DHPrivateKey)
- {
- return new GnuDHPrivateKey (((DHPrivateKey) key).getX (),
- ((DHPrivateKey) key).getParams ());
- }
- if (key instanceof DHPublicKey)
- {
- return new GnuDHPublicKey (((DHPublicKey) key).getParams (),
- ((DHPublicKey) key).getY (), null);
- }
- throw new InvalidKeyException ();
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/EncodedKeyFactory.java b/libjava/classpath/gnu/java/security/provider/EncodedKeyFactory.java
deleted file mode 100644
index 2bf0fff809e..00000000000
--- a/libjava/classpath/gnu/java/security/provider/EncodedKeyFactory.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/* EncodedKeyFactory.java -- encoded key factory.
- Copyright (C) 2004 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.java.security.provider;
-
-import gnu.java.security.OID;
-import gnu.java.security.der.BitString;
-import gnu.java.security.der.DERReader;
-import gnu.java.security.der.DERValue;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.AlgorithmParameters;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.KeyFactorySpi;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.spec.DSAParameterSpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.InvalidParameterSpecException;
-import java.security.spec.KeySpec;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.security.spec.RSAPublicKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-import javax.crypto.spec.DHParameterSpec;
-
-/**
- * A factory for keys encoded in either the X.509 format (for public
- * keys) or the PKCS#8 format (for private keys).
- *
- * @author Casey Marshall (rsdio@metastatic.org)
- */
-public class EncodedKeyFactory extends KeyFactorySpi
-{
-
- // Constants.
- // ------------------------------------------------------------------------
-
- private static final OID ID_DSA = new OID("1.2.840.10040.4.1");
- private static final OID ID_RSA = new OID("1.2.840.113549.1.1.1");
- private static final OID ID_DH = new OID("1.2.840.10046.2.1");
-
- // Instance methods.
- // ------------------------------------------------------------------------
-
- public PublicKey engineGeneratePublic(KeySpec spec)
- throws InvalidKeySpecException
- {
- if (!(spec instanceof X509EncodedKeySpec))
- throw new InvalidKeySpecException("only supports X.509 key specs");
- DERReader der = new DERReader(((X509EncodedKeySpec) spec).getEncoded());
- try
- {
- DERValue spki = der.read();
- if (!spki.isConstructed())
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- DERValue alg = der.read();
- if (!alg.isConstructed())
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- DERValue val = der.read();
- if (!(val.getValue() instanceof OID))
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- OID algId = (OID) val.getValue();
- byte[] algParams = null;
- if (alg.getLength() > val.getEncodedLength())
- {
- val = der.read();
- algParams = val.getEncoded();
- if (val.isConstructed())
- der.skip(val.getLength());
- }
- val = der.read();
- if (!(val.getValue() instanceof BitString))
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- byte[] publicKey = ((BitString) val.getValue()).toByteArray();
- if (algId.equals(ID_DSA))
- {
- BigInteger p = null, g = null, q = null, Y;
- if (algParams != null)
- {
- DERReader dsaParams = new DERReader(algParams);
- val = dsaParams.read();
- if (!val.isConstructed())
- throw new InvalidKeySpecException("malformed DSA parameters");
- val = dsaParams.read();
- if (!(val.getValue() instanceof BigInteger))
- throw new InvalidKeySpecException("malformed DSA parameters");
- p = (BigInteger) val.getValue();
- val = dsaParams.read();
- if (!(val.getValue() instanceof BigInteger))
- throw new InvalidKeySpecException("malformed DSA parameters");
- q = (BigInteger) val.getValue();
- val = dsaParams.read();
- if (!(val.getValue() instanceof BigInteger))
- throw new InvalidKeySpecException("malformed DSA parameters");
- g = (BigInteger) val.getValue();
- }
- DERReader dsaPub = new DERReader(publicKey);
- val = dsaPub.read();
- if (!(val.getValue() instanceof BigInteger))
- throw new InvalidKeySpecException("malformed DSA parameters");
- Y = (BigInteger) val.getValue();
- return new GnuDSAPublicKey(Y, p, q, g);
- }
- else if (algId.equals(ID_RSA))
- {
- DERReader rsaParams = new DERReader(publicKey);
- if (!rsaParams.read().isConstructed())
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- return new GnuRSAPublicKey(new RSAPublicKeySpec(
- (BigInteger) rsaParams.read().getValue(),
- (BigInteger) rsaParams.read().getValue()));
- }
- else if (algId.equals(ID_DH))
- {
- if (algParams == null)
- throw new InvalidKeySpecException("missing DH parameters");
- DERReader dhParams = new DERReader(algParams);
- val = dhParams.read();
- BigInteger p, g, q, Y;
- if (!val.isConstructed())
- throw new InvalidKeySpecException("malformed DH parameters");
- val = dhParams.read();
- if (!(val.getValue() instanceof BigInteger))
- throw new InvalidKeySpecException("malformed DH parameters");
- p = (BigInteger) val.getValue();
- val = dhParams.read();
- if (!(val.getValue() instanceof BigInteger))
- throw new InvalidKeySpecException("malformed DH parameters");
- g = (BigInteger) val.getValue();
- val = dhParams.read();
- if (!(val.getValue() instanceof BigInteger))
- throw new InvalidKeySpecException("malformed DH parameters");
- q = (BigInteger) val.getValue();
- DERReader dhPub = new DERReader(publicKey);
- val = dhPub.read();
- if (!(val.getValue() instanceof BigInteger))
- throw new InvalidKeySpecException("malformed DH parameters");
- Y = (BigInteger) val.getValue();
- return (PublicKey) new GnuDHPublicKey(new DHParameterSpec(p, g), Y, q);
- }
- else
- throw new InvalidKeySpecException("unknown algorithm: " + algId);
- }
- catch (IOException ioe)
- {
- throw new InvalidKeySpecException(ioe.getMessage());
- }
- }
-
- public PrivateKey engineGeneratePrivate(KeySpec spec)
- throws InvalidKeySpecException
- {
- if (!(spec instanceof PKCS8EncodedKeySpec))
- {
- throw new InvalidKeySpecException("only supports PKCS8 key specs");
- }
- DERReader der = new DERReader(((PKCS8EncodedKeySpec) spec).getEncoded());
- try
- {
- DERValue pki = der.read();
- if (!pki.isConstructed())
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- DERValue val = der.read();
- if (!(val.getValue() instanceof BigInteger))
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- DERValue alg = der.read();
- if (!alg.isConstructed())
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- val = der.read();
- if (!(val.getValue() instanceof OID))
- {
- throw new InvalidKeySpecException("malformed encoded key");
- }
- OID algId = (OID) val.getValue();
- byte[] algParams = null;
- if (alg.getLength() > val.getEncodedLength())
- {
- val = der.read();
- algParams = val.getEncoded();
- if (val.isConstructed())
- der.skip(val.getLength());
- }
- byte[] privateKey = (byte[]) der.read().getValue();
- if (algId.equals(ID_DSA))
- {
- if (algParams == null)
- {
- throw new InvalidKeySpecException("missing DSA parameters");
- }
- AlgorithmParameters params = AlgorithmParameters.getInstance("DSA");
- params.init(algParams);
- DSAParameterSpec dsaSpec = (DSAParameterSpec)
- params.getParameterSpec(DSAParameterSpec.class);
- DERReader dsaPriv = new DERReader(privateKey);
- return new GnuDSAPrivateKey((BigInteger) dsaPriv.read().getValue(),
- dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG());
- }
- else if (algId.equals(ID_RSA))
- {
- DERReader rsaParams = new DERReader(privateKey);
- if (!rsaParams.read().isConstructed())
- throw new InvalidKeySpecException("malformed encoded key");
- return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
- (BigInteger) rsaParams.read().getValue(), // n
- (BigInteger) rsaParams.read().getValue(), // e
- (BigInteger) rsaParams.read().getValue(), // d
- (BigInteger) rsaParams.read().getValue(), // p
- (BigInteger) rsaParams.read().getValue(), // q
- (BigInteger) rsaParams.read().getValue(), // d mod (p - 1)
- (BigInteger) rsaParams.read().getValue(), // d mod (q - 1)
- (BigInteger) rsaParams.read().getValue())); // (inv q) mod p
- }
- else
- throw new InvalidKeySpecException("unknown algorithm: " + algId);
- }
- catch (InvalidParameterSpecException iapse)
- {
- throw new InvalidKeySpecException(iapse.getMessage());
- }
- catch (NoSuchAlgorithmException nsae)
- {
- throw new InvalidKeySpecException(nsae.getMessage());
- }
- catch (IOException ioe)
- {
- throw new InvalidKeySpecException(ioe.getMessage());
- }
- }
-
- public KeySpec engineGetKeySpec(Key key, Class speClass)
- throws InvalidKeySpecException
- {
- if ((key instanceof PrivateKey) && key.getFormat().equals("PKCS#8")
- && speClass.isAssignableFrom(PKCS8EncodedKeySpec.class))
- return new PKCS8EncodedKeySpec(key.getEncoded());
- else if ((key instanceof PublicKey) && key.getFormat().equals("X.509")
- && speClass.isAssignableFrom(X509EncodedKeySpec.class))
- return new X509EncodedKeySpec(key.getEncoded());
- else
- throw new InvalidKeySpecException();
- }
-
- public Key engineTranslateKey(Key key) throws InvalidKeyException
- {
- throw new InvalidKeyException("translating keys not supported");
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/Gnu.java b/libjava/classpath/gnu/java/security/provider/Gnu.java
index e553bbcbd8a..06135664427 100644
--- a/libjava/classpath/gnu/java/security/provider/Gnu.java
+++ b/libjava/classpath/gnu/java/security/provider/Gnu.java
@@ -57,105 +57,209 @@ public final class Gnu extends Provider
// we automatically get all the implementation classes.
// Signature
- put("Signature.SHA1withDSA",
- gnu.java.security.provider.DSASignature.class.getName());
-
- put("Alg.Alias.Signature.DSS", "SHA1withDSA");
- put("Alg.Alias.Signature.DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
- put("Alg.Alias.Signature.DSAwithSHA", "SHA1withDSA");
- put("Alg.Alias.Signature.DSAwithSHA1", "SHA1withDSA");
- put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "SHA1withDSA");
- put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
- put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA");
- put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA");
-
- put("Signature.MD2withRSA", MD2withRSA.class.getName());
+ put("Signature.SHA160withDSS",
+ gnu.java.security.jce.sig.SHA160withDSS.class.getName());
+ put("Alg.Alias.Signature.SHA1withDSA", "SHA160withDSS");
+ put("Alg.Alias.Signature.DSS", "SHA160withDSS");
+ put("Alg.Alias.Signature.DSA", "SHA160withDSS");
+ put("Alg.Alias.Signature.SHAwithDSA", "SHA160withDSS");
+ put("Alg.Alias.Signature.DSAwithSHA", "SHA160withDSS");
+ put("Alg.Alias.Signature.DSAwithSHA1", "SHA160withDSS");
+ put("Alg.Alias.Signature.SHA/DSA", "SHA160withDSS");
+ put("Alg.Alias.Signature.SHA-1/DSA", "SHA160withDSS");
+ put("Alg.Alias.Signature.SHA1/DSA", "SHA160withDSS");
+ put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "SHA160withDSS");
+ put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA160withDSS");
+ put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA160withDSS");
+ put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA160withDSS");
+
+ put("Signature.MD2withRSA",
+ gnu.java.security.jce.sig.MD2withRSA.class.getName());
put("Signature.MD2withRSA ImplementedIn", "Software");
put("Alg.Alias.Signature.md2WithRSAEncryption", "MD2withRSA");
put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.2", "MD2withRSA");
put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2withRSA");
- put("Signature.MD4withRSA", MD4withRSA.class.getName());
- put("Signature.MD4withRSA ImplementedIn", "Software");
- put("Alg.Alias.Signature.md4WithRSAEncryption", "MD4withRSA");
- put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.3", "MD4withRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.3", "MD4withRSA");
-
- put("Signature.MD5withRSA", MD5withRSA.class.getName());
+ put("Signature.MD5withRSA",
+ gnu.java.security.jce.sig.MD5withRSA.class.getName());
put("Signature.MD5withRSA ImplementedIn", "Software");
put("Alg.Alias.Signature.md5WithRSAEncryption", "MD5withRSA");
put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4", "MD5withRSA");
put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
- put("Signature.SHA1withRSA", SHA1withRSA.class.getName());
- put("Signature.SHA1withRSA ImplementedIn", "Software");
- put("Alg.Alias.Signature.sha-1WithRSAEncryption", "SHA1withRSA");
- put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "SHA1withRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
+ put("Signature.SHA160withRSA",
+ gnu.java.security.jce.sig.SHA160withRSA.class.getName());
+ put("Signature.SHA160withRSA ImplementedIn", "Software");
+ put("Alg.Alias.Signature.sha-1WithRSAEncryption", "SHA160withRSA");
+ put("Alg.Alias.Signature.sha-160WithRSAEncryption", "SHA160withRSA");
+ put("Alg.Alias.Signature.sha1WithRSAEncryption", "SHA160withRSA");
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "SHA160withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA160withRSA");
+ put("Alg.Alias.Signature.SHA1withRSA", "SHA160withRSA");
+
+ put("Signature.SHA256withRSA",
+ gnu.java.security.jce.sig.SHA256withRSA.class.getName());
+ put("Signature.SHA160withRSA ImplementedIn", "Software");
+ put("Alg.Alias.Signature.sha256WithRSAEncryption", "SHA256withRSA");
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.11", "SHA256withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256withRSA");
+
+ put("Signature.SHA384withRSA",
+ gnu.java.security.jce.sig.SHA384withRSA.class.getName());
+ put("Signature.SHA160withRSA ImplementedIn", "Software");
+ put("Alg.Alias.Signature.sha384WithRSAEncryption", "SHA384withRSA");
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.12", "SHA384withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384withRSA");
+
+ put("Signature.SHA512withRSA",
+ gnu.java.security.jce.sig.SHA512withRSA.class.getName());
+ put("Signature.SHA160withRSA ImplementedIn", "Software");
+ put("Alg.Alias.Signature.sha512WithRSAEncryption", "SHA512withRSA");
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.13", "SHA512withRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512withRSA");
+
+ put("Signature.DSS/RAW",
+ gnu.java.security.jce.sig.DSSRawSignatureSpi.class.getName());
+ put("Signature.DSS/RAW KeySize", "1024");
+ put("Signature.DSS/RAW ImplementedIn", "Software");
+
+ put("Signature.RSA-PSS/RAW",
+ gnu.java.security.jce.sig.RSAPSSRawSignatureSpi.class.getName());
+ put("Signature.RSA-PSS/RAW KeySize", "1024");
+ put("Signature.RSA-PSS/RAW ImplementedIn", "Software");
// Key Pair Generator
- put("KeyPairGenerator.DSA",
- gnu.java.security.provider.DSAKeyPairGenerator.class.getName());
- put("KeyPairGenerator.DiffieHellman", DiffieHellmanKeyPairGeneratorImpl.class.getName ());
-
- put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
- put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
- put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
- put("Alg.Alias.KeyPairGenerator.DH", "DiffieHellman");
+ put("KeyPairGenerator.DSS",
+ gnu.java.security.jce.sig.DSSKeyPairGeneratorSpi.class.getName());
+ put("KeyPairGenerator.DSS KeySize", "1024");
+ put("KeyPairGenerator.DSS ImplementedIn", "Software");
+ put("Alg.Alias.KeyPairGenerator.DSA", "DSS");
+ put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSS");
+ put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSS");
+ put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSS");
+
+ put("KeyPairGenerator.RSA",
+ gnu.java.security.jce.sig.RSAKeyPairGeneratorSpi.class.getName());
+ put("KeyPairGenerator.RSA KeySize", "1024");
+ put("KeyPairGenerator.RSA ImplementedIn", "Software");
// Key Factory
- put("KeyFactory.DSA",
- gnu.java.security.provider.DSAKeyFactory.class.getName());
-
- put("KeyFactory.Encoded", EncodedKeyFactory.class.getName());
+ put("KeyFactory.DSS",
+ gnu.java.security.jce.sig.DSSKeyFactory.class.getName());
+ put("Alg.Alias.KeyFactory.DSA", "DSS");
+ put("Alg.Alias.KeyFactory.OID.1.2.840.10040.4.1", "DSS");
+ put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSS");
+ put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSS");
+
+ put("KeyFactory.RSA",
+ gnu.java.security.jce.sig.RSAKeyFactory.class.getName());
+
+ put("KeyFactory.Encoded",
+ gnu.java.security.jce.sig.EncodedKeyFactory.class.getName());
put("KeyFactory.Encoded ImplementedIn", "Software");
put("Alg.Alias.KeyFactory.X.509", "Encoded");
put("Alg.Alias.KeyFactory.X509", "Encoded");
put("Alg.Alias.KeyFactory.PKCS#8", "Encoded");
put("Alg.Alias.KeyFactory.PKCS8", "Encoded");
- put("KeyFactory.RSA", RSAKeyFactory.class.getName());
-
- put("Alg.Alias.KeyFactory.OID.1.2.840.10040.4.1", "DSA");
- put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");
- put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSA");
-
- put("KeyFactory.DiffieHellman", DiffieHellmanKeyFactoryImpl.class.getName());
- put("Alg.Alias.KeyFactory.DH", "DiffieHellman");
-
- // Message Digests
- put("MessageDigest.SHA", gnu.java.security.provider.SHA.class.getName());
- put("MessageDigest.MD5", gnu.java.security.provider.MD5.class.getName());
-
- // Format "Alias", "Actual Name"
- put("Alg.Alias.MessageDigest.SHA1", "SHA");
- put("Alg.Alias.MessageDigest.SHA-1", "SHA");
- put("Alg.Alias.MessageDigest.SHA-160", "SHA");
+ put("MessageDigest.HAVAL", gnu.java.security.jce.hash.HavalSpi.class.getName());
+ put("MessageDigest.HAVAL ImplementedIn", "Software");
+ put("MessageDigest.MD2", gnu.java.security.jce.hash.MD2Spi.class.getName());
+ put("MessageDigest.MD2 ImplementedIn", "Software");
+ put("MessageDigest.MD4", gnu.java.security.jce.hash.MD4Spi.class.getName());
+ put("MessageDigest.MD4 ImplementedIn", "Software");
+ put("MessageDigest.MD5", gnu.java.security.jce.hash.MD5Spi.class.getName());
+ put("MessageDigest.MD5 ImplementedIn", "Software");
+ put("MessageDigest.RIPEMD128", gnu.java.security.jce.hash.RipeMD128Spi.class.getName());
+ put("MessageDigest.RIPEMD128 ImplementedIn", "Software");
+ put("MessageDigest.RIPEMD160", gnu.java.security.jce.hash.RipeMD160Spi.class.getName());
+ put("MessageDigest.RIPEMD160 ImplementedIn", "Software");
+ put("MessageDigest.SHA-160", gnu.java.security.jce.hash.Sha160Spi.class.getName());
+ put("MessageDigest.SHA-160 ImplementedIn", "Software");
+ put("MessageDigest.SHA-256", gnu.java.security.jce.hash.Sha256Spi.class.getName());
+ put("MessageDigest.SHA-256 ImplementedIn", "Software");
+ put("MessageDigest.SHA-384", gnu.java.security.jce.hash.Sha384Spi.class.getName());
+ put("MessageDigest.SHA-384 ImplementedIn", "Software");
+ put("MessageDigest.SHA-512", gnu.java.security.jce.hash.Sha512Spi.class.getName());
+ put("MessageDigest.SHA-512 ImplementedIn", "Software");
+ put("MessageDigest.TIGER", gnu.java.security.jce.hash.TigerSpi.class.getName());
+ put("MessageDigest.TIGER ImplementedIn", "Software");
+ put("MessageDigest.WHIRLPOOL", gnu.java.security.jce.hash.WhirlpoolSpi.class.getName());
+ put("MessageDigest.WHIRLPOOL ImplementedIn", "Software");
+
+ put("Alg.Alias.MessageDigest.SHS", "SHA-160");
+ put("Alg.Alias.MessageDigest.SHA", "SHA-160");
+ put("Alg.Alias.MessageDigest.SHA1", "SHA-160");
+ put("Alg.Alias.MessageDigest.SHA-1", "SHA-160");
+ put("Alg.Alias.MessageDigest.SHA2-256", "SHA-256");
+ put("Alg.Alias.MessageDigest.SHA2-384", "SHA-384");
+ put("Alg.Alias.MessageDigest.SHA2-512", "SHA-512");
+ put("Alg.Alias.MessageDigest.SHA256", "SHA-256");
+ put("Alg.Alias.MessageDigest.SHA384", "SHA-384");
+ put("Alg.Alias.MessageDigest.SHA512", "SHA-512");
+ put("Alg.Alias.MessageDigest.RIPEMD-160", "RIPEMD160");
+ put("Alg.Alias.MessageDigest.RIPEMD-128", "RIPEMD128");
+ put("Alg.Alias.MessageDigest.OID.1.2.840.11359.2.2", "MD2");
+ put("Alg.Alias.MessageDigest.1.2.840.11359.2.2", "MD2");
+ put("Alg.Alias.MessageDigest.OID.1.2.840.11359.2.5", "MD5");
+ put("Alg.Alias.MessageDigest.1.2.840.11359.2.5", "MD5");
+ put("Alg.Alias.MessageDigest.OID.1.3.14.3.2.26", "SHA1");
+ put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA1");
// Algorithm Parameters
- put("AlgorithmParameters.DSA",
- gnu.java.security.provider.DSAParameters.class.getName());
-
- put("Alg.Alias.AlgorithmParameters.DSS", "DSA");
- put("Alg.Alias.AlgorithmParameters.SHAwithDSA", "DSA");
- put("Alg.Alias.AlgorithmParameters.OID.1.2.840.10040.4.3", "DSA");
- put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.3", "DSA");
+ put("AlgorithmParameters.DSS",
+ gnu.java.security.jce.sig.DSSParameters.class.getName());
+ put("Alg.Alias.AlgorithmParameters.DSA", "DSS");
+ put("Alg.Alias.AlgorithmParameters.SHAwithDSA", "DSS");
+ put("Alg.Alias.AlgorithmParameters.OID.1.2.840.10040.4.3", "DSS");
+ put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.3", "DSS");
// Algorithm Parameter Generator
put("AlgorithmParameterGenerator.DSA",
- gnu.java.security.provider.DSAParameterGenerator.class.getName());
+ gnu.java.security.jce.sig.DSSParametersGenerator.class.getName());
+ put("Alg.Alias.AlgorithmParameterGenerator.DSA", "DSS");
// SecureRandom
put("SecureRandom.SHA1PRNG",
- gnu.java.security.provider.SHA1PRNG.class.getName());
+ gnu.java.security.jce.prng.Sha160RandomSpi.class.getName());
+
+ put("SecureRandom.MD2PRNG", gnu.java.security.jce.prng.MD2RandomSpi.class.getName());
+ put("SecureRandom.MD2PRNG ImplementedIn", "Software");
+ put("SecureRandom.MD4PRNG", gnu.java.security.jce.prng.MD4RandomSpi.class.getName());
+ put("SecureRandom.MD4PRNG ImplementedIn", "Software");
+ put("SecureRandom.MD5PRNG", gnu.java.security.jce.prng.MD5RandomSpi.class.getName());
+ put("SecureRandom.MD5PRNG ImplementedIn", "Software");
+ put("SecureRandom.RIPEMD128PRNG", gnu.java.security.jce.prng.RipeMD128RandomSpi.class.getName());
+ put("SecureRandom.RIPEMD128PRNG ImplementedIn", "Software");
+ put("SecureRandom.RIPEMD160PRNG", gnu.java.security.jce.prng.RipeMD160RandomSpi.class.getName());
+ put("SecureRandom.RIPEMD160PRNG ImplementedIn", "Software");
+ put("SecureRandom.SHA-160PRNG", gnu.java.security.jce.prng.Sha160RandomSpi.class.getName());
+ put("SecureRandom.SHA-160PRNG ImplementedIn", "Software");
+ put("SecureRandom.SHA-256PRNG", gnu.java.security.jce.prng.Sha256RandomSpi.class.getName());
+ put("SecureRandom.SHA-256PRNG ImplementedIn", "Software");
+ put("SecureRandom.SHA-384PRNG", gnu.java.security.jce.prng.Sha384RandomSpi.class.getName());
+ put("SecureRandom.SHA-384PRNG ImplementedIn", "Software");
+ put("SecureRandom.SHA-512PRNG", gnu.java.security.jce.prng.Sha512RandomSpi.class.getName());
+ put("SecureRandom.SHA-512PRNG ImplementedIn", "Software");
+ put("SecureRandom.TIGERPRNG", gnu.java.security.jce.prng.TigerRandomSpi.class.getName());
+ put("SecureRandom.TIGERPRNG ImplementedIn", "Software");
+ put("SecureRandom.HAVALPRNG", gnu.java.security.jce.prng.HavalRandomSpi.class.getName());
+ put("SecureRandom.HAVALPRNG ImplementedIn", "Software");
+ put("SecureRandom.WHIRLPOOLPRNG", gnu.java.security.jce.prng.WhirlpoolRandomSpi.class.getName());
+ put("SecureRandom.WHIRLPOOLPRNG ImplementedIn", "Software");
+
+ put("Alg.Alias.SecureRandom.SHA-1PRNG", "SHA-160PRNG");
+ put("Alg.Alias.SecureRandom.SHA1PRNG", "SHA-160PRNG");
+ put("Alg.Alias.SecureRandom.SHAPRNG", "SHA-160PRNG");
+ put("Alg.Alias.SecureRandom.SHA-256PRNG", "SHA-256PRNG");
+ put("Alg.Alias.SecureRandom.SHA-2-1PRNG", "SHA-256PRNG");
+ put("Alg.Alias.SecureRandom.SHA-384PRNG", "SHA-384PRNG");
+ put("Alg.Alias.SecureRandom.SHA-2-2PRNG", "SHA-384PRNG");
+ put("Alg.Alias.SecureRandom.SHA-512PRNG", "SHA-512PRNG");
+ put("Alg.Alias.SecureRandom.SHA-2-3PRNG", "SHA-512PRNG");
// CertificateFactory
put("CertificateFactory.X509", X509CertificateFactory.class.getName());
-
put("CertificateFactory.X509 ImplementedIn", "Software");
put("Alg.Alias.CertificateFactory.X.509", "X509");
@@ -166,14 +270,6 @@ public final class Gnu extends Provider
// CertStore
put("CertStore.Collection", CollectionCertStoreImpl.class.getName());
- // KeyAgreement
- put("KeyAgreement.DiffieHellman", gnu.javax.crypto.DiffieHellmanImpl.class.getName());
- put("Alg.Alias.KeyAgreement.DH", "DiffieHellman");
-
- // Cipher
- put("Cipher.RSAES-PKCS1-v1_5", gnu.javax.crypto.RSACipherImpl.class.getName());
- put("Alg.Alias.Cipher.RSA", "RSAES-PKCS1-v1_5");
-
return null;
}
});
diff --git a/libjava/classpath/gnu/java/security/provider/GnuDSAPrivateKey.java b/libjava/classpath/gnu/java/security/provider/GnuDSAPrivateKey.java
deleted file mode 100644
index aac2faab229..00000000000
--- a/libjava/classpath/gnu/java/security/provider/GnuDSAPrivateKey.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/* GnuDSAPrivateKey.java --- Gnu DSA Private Key
- Copyright (C) 1999,2003,2004 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.java.security.provider;
-
-import gnu.java.security.OID;
-import gnu.java.security.der.DER;
-import gnu.java.security.der.DERValue;
-import gnu.java.security.der.DERWriter;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.interfaces.DSAParams;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.spec.DSAParameterSpec;
-import java.util.ArrayList;
-
-public class GnuDSAPrivateKey implements DSAPrivateKey
-{
- private byte[] encodedKey;
- BigInteger x;
- BigInteger p;
- BigInteger q;
- BigInteger g;
-
- public GnuDSAPrivateKey(BigInteger x, BigInteger p, BigInteger q, BigInteger g )
- {
- this.x = x;
- this.p = p;
- this.q = q;
- this.g = g;
- }
-
- public String getAlgorithm()
- {
- return "DSA";
- }
-
- public String getFormat()
- {
- return "PKCS#8";
- }
-
- /**
- * Encodes this key as a <code>PrivateKeyInfo</code>, as described in
- * PKCS #8. The ASN.1 specification for this structure is:
- *
- * <blockquote><pre>
- * PrivateKeyInfo ::= SEQUENCE {
- * version Version,
- * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
- * privateKey PrivateKey,
- * attributes [0] IMPLICIT Attributes OPTIONAL }
- *
- * Version ::= INTEGER
- *
- * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * PrivateKey ::= OCTET STRING
- *
- * Attributes ::= SET OF Attribute
- * </pre></blockquote>
- *
- * <p>DSA private keys (in Classpath at least) have no attributes.
- */
- public byte[] getEncoded()
- {
- if (encodedKey != null)
- return (byte[]) encodedKey.clone();
- try
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ArrayList pki = new ArrayList(3);
- pki.add(new DERValue(DER.INTEGER, BigInteger.ZERO));
- ArrayList algId = new ArrayList(2);
- algId.add(new DERValue(DER.OBJECT_IDENTIFIER,
- new OID("1.2.840.10040.4.1")));
- ArrayList algParams = new ArrayList(3);
- algParams.add(new DERValue(DER.INTEGER, p));
- algParams.add(new DERValue(DER.INTEGER, q));
- algParams.add(new DERValue(DER.INTEGER, g));
- algId.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, algParams));
- pki.add(new DERValue(DER.OCTET_STRING, x.toByteArray()));
- DERWriter.write(out, new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, pki));
- return (byte[]) (encodedKey = out.toByteArray()).clone();
- }
- catch (IOException ioe)
- {
- return null;
- }
- }
-
- public DSAParams getParams()
- {
- return (DSAParams)(new DSAParameterSpec(p,q,g));
- }
-
- public BigInteger getX()
- {
- return x;
- }
-
- public String toString()
- {
- return "GnuDSAPrivateKey: x="
- + (x != null ? x.toString(16) : "null") + " p="
- + (p != null ? p.toString(16) : "null") + " q="
- + (q != null ? q.toString(16) : "null") + " g="
- + (g != null ? g.toString(16) : "null");
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/GnuDSAPublicKey.java b/libjava/classpath/gnu/java/security/provider/GnuDSAPublicKey.java
deleted file mode 100644
index 41195fa992c..00000000000
--- a/libjava/classpath/gnu/java/security/provider/GnuDSAPublicKey.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/* GnuDSAPublicKey.java --- Gnu DSA Public Key
- Copyright (C) 1999,2003,2004 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.java.security.provider;
-
-import gnu.java.security.OID;
-import gnu.java.security.der.BitString;
-import gnu.java.security.der.DER;
-import gnu.java.security.der.DERValue;
-import gnu.java.security.der.DERWriter;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.interfaces.DSAParams;
-import java.security.interfaces.DSAPublicKey;
-import java.security.spec.DSAParameterSpec;
-import java.util.ArrayList;
-
-public class GnuDSAPublicKey implements DSAPublicKey
-{
- private byte[] encodedKey;
- BigInteger y;
- BigInteger p;
- BigInteger q;
- BigInteger g;
-
- public GnuDSAPublicKey(BigInteger y, BigInteger p, BigInteger q, BigInteger g )
- {
- this.y = y;
- this.p = p;
- this.q = q;
- this.g = g;
- }
-
- public String getAlgorithm()
- {
- return "DSA";
- }
-
- public String getFormat()
- {
- return "X.509";
- }
-
- /**
- * The encoded form of DSA public keys is:
- *
- * <blockquote><pre>
- * SubjectPublicKeyInfo ::= SEQUENCE {
- * algorithm AlgorithmIdentifier,
- * subjectPublicKey BIT STRING }
- * </pre></blockquote>
- */
- public byte[] getEncoded()
- {
- if (encodedKey != null)
- return (byte[]) encodedKey.clone();
- try
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ArrayList spki = new ArrayList(2);
- ArrayList alg = new ArrayList(2);
- alg.add(new DERValue(DER.OBJECT_IDENTIFIER,
- new OID("1.2.840.113549.1.1.1")));
- ArrayList params = new ArrayList(3);
- params.add(new DERValue(DER.INTEGER, p));
- params.add(new DERValue(DER.INTEGER, q));
- params.add(new DERValue(DER.INTEGER, g));
- alg.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, params));
- spki.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, alg));
- spki.add(new DERValue(DER.BIT_STRING, new BitString(y.toByteArray())));
- DERWriter.write(out, new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, spki));
- return (byte[]) (encodedKey = out.toByteArray()).clone();
- }
- catch (IOException ioe)
- {
- return null;
- }
- }
-
- public DSAParams getParams()
- {
- if (p == null || q == null || g == null)
- return null;
- return (DSAParams)(new DSAParameterSpec(p,q,g));
- }
-
- public BigInteger getY()
- {
- return y;
- }
-
- public String toString()
- {
- return
- "GnuDSAPublicKey: y=" + (y != null ? y.toString(16) : "(null)") +
- " p=" + (p != null ? p.toString(16) : "(null)") +
- " q=" + (q != null ? q.toString(16) : "(null)") +
- " g=" + (g != null ? g.toString(16) : "(null)");
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/GnuRSAPrivateKey.java b/libjava/classpath/gnu/java/security/provider/GnuRSAPrivateKey.java
deleted file mode 100644
index b09fc88bc5c..00000000000
--- a/libjava/classpath/gnu/java/security/provider/GnuRSAPrivateKey.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/* GnuRSAPrivateKey.java -- GNU RSA private key.
- Copyright (C) 2004 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.java.security.provider;
-
-import gnu.java.security.OID;
-import gnu.java.security.der.DER;
-import gnu.java.security.der.DERValue;
-
-import java.math.BigInteger;
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.util.ArrayList;
-
-class GnuRSAPrivateKey implements RSAPrivateCrtKey
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private final RSAPrivateCrtKeySpec spec;
- private byte[] encodedKey;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- public GnuRSAPrivateKey(RSAPrivateCrtKeySpec spec)
- {
- this.spec = spec;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public BigInteger getModulus()
- {
- return spec.getModulus();
- }
-
- public BigInteger getPrivateExponent()
- {
- return spec.getPrivateExponent();
- }
-
- public BigInteger getCrtCoefficient()
- {
- return spec.getCrtCoefficient();
- }
-
- public BigInteger getPrimeExponentP()
- {
- return spec.getPrimeExponentP();
- }
-
- public BigInteger getPrimeExponentQ()
- {
- return spec.getPrimeExponentQ();
- }
-
- public BigInteger getPrimeP()
- {
- return spec.getPrimeP();
- }
-
- public BigInteger getPrimeQ()
- {
- return spec.getPrimeQ();
- }
-
- public BigInteger getPublicExponent()
- {
- return spec.getPublicExponent();
- }
-
- public String getAlgorithm()
- {
- return "RSA";
- }
-
- public String getFormat()
- {
- return "PKCS#8";
- }
-
- /**
- * The encoded form is:
- *
- * <pre>
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER -- (inverse of q) mod p }
- * </pre>
- *
- * <p>Which is in turn encoded in a PrivateKeyInfo structure from PKCS#8.
- */
- public byte[] getEncoded()
- {
- if (encodedKey != null)
- return (byte[]) encodedKey.clone();
- ArrayList key = new ArrayList(9);
- key.add(new DERValue(DER.INTEGER, BigInteger.ZERO));
- key.add(new DERValue(DER.INTEGER, getModulus()));
- key.add(new DERValue(DER.INTEGER, getPublicExponent()));
- key.add(new DERValue(DER.INTEGER, getPrivateExponent()));
- key.add(new DERValue(DER.INTEGER, getPrimeP()));
- key.add(new DERValue(DER.INTEGER, getPrimeQ()));
- key.add(new DERValue(DER.INTEGER, getPrimeExponentP()));
- key.add(new DERValue(DER.INTEGER, getPrimeExponentQ()));
- key.add(new DERValue(DER.INTEGER, getCrtCoefficient()));
- DERValue pk = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, key);
- ArrayList pki = new ArrayList(3);
- pki.add(new DERValue(DER.INTEGER, BigInteger.ZERO));
- ArrayList alg = new ArrayList(2);
- alg.add(new DERValue(DER.OBJECT_IDENTIFIER,
- new OID("1.2.840.113549.1.1.1")));
- alg.add(new DERValue(DER.NULL, null));
- pki.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, alg));
- pki.add(new DERValue(DER.OCTET_STRING, pk.getEncoded()));
- encodedKey = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, pki).getEncoded();
- return (byte[]) encodedKey.clone();
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/MD5.java b/libjava/classpath/gnu/java/security/provider/MD5.java
deleted file mode 100644
index 1534eb91089..00000000000
--- a/libjava/classpath/gnu/java/security/provider/MD5.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/* MD5.java -- Class implementing the MD5 algorithm as specified in RFC1321.
- Copyright (C) 1999, 2002 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.java.security.provider;
-import java.security.MessageDigest;
-
-/**
- This class implements the MD5 algorithm as described in RFC1321.
-
- @see java.security.MessageDigest
-*/
-public class MD5 extends MessageDigest implements Cloneable
-{
- private final int W[] = new int[16];
- private long bytecount;
- private int A;
- private int B;
- private int C;
- private int D;
-
- public MD5()
- {
- super("MD5");
- engineReset ();
- }
-
- public Object clone()
- {
- return new MD5 (this);
- }
-
- private MD5 (MD5 copy)
- {
- this ();
- bytecount = copy.bytecount;
- A = copy.A;
- B = copy.B;
- C = copy.C;
- D = copy.D;
- System.arraycopy (copy.W, 0, W, 0, 16);
- }
-
- public int engineGetDigestLength()
- {
- return 16;
- }
-
- // Intialize the A,B,C,D needed for the hash
- public void engineReset()
- {
- bytecount = 0;
- A = 0x67452301;
- B = 0xefcdab89;
- C = 0x98badcfe;
- D = 0x10325476;
- for(int i = 0; i < 16; i++)
- W[i] = 0;
- }
-
- public void engineUpdate (byte b)
- {
- int i = (int)bytecount % 64;
- int shift = (3 - i % 4) * 8;
- int idx = i / 4;
-
- // if you could index ints, this would be: W[idx][shift/8] = b
- W[idx] = (W[idx] & ~(0xff << shift)) | ((b & 0xff) << shift);
-
- // if we've filled up a block, then process it
- if ((++ bytecount) % 64 == 0)
- munch ();
- }
-
- public void engineUpdate (byte bytes[], int off, int len)
- {
- if (len < 0)
- throw new ArrayIndexOutOfBoundsException ();
-
- int end = off + len;
- while (off < end)
- engineUpdate (bytes[off++]);
- }
-
- public byte[] engineDigest()
- {
- long bitcount = bytecount * 8;
- engineUpdate ((byte)0x80); // 10000000 in binary; the start of the padding
-
- // add the rest of the padding to fill this block out, but leave 8
- // bytes to put in the original bytecount
- while ((int)bytecount % 64 != 56)
- engineUpdate ((byte)0);
-
- // add the length of the original, unpadded block to the end of
- // the padding
- W[14] = SWAP((int)(0xffffffff & bitcount));
- W[15] = SWAP((int)(0xffffffff & (bitcount >>> 32)));
- bytecount += 8;
-
- // digest the fully padded block
- munch ();
-
- A = SWAP(A);
- B = SWAP(B);
- C = SWAP(C);
- D = SWAP(D);
- byte[] result = new byte[] {(byte)(A >>> 24), (byte)(A >>> 16),
- (byte)(A >>> 8), (byte)A,
- (byte)(B >>> 24), (byte)(B >>> 16),
- (byte)(B >>> 8), (byte)B,
- (byte)(C >>> 24), (byte)(C >>> 16),
- (byte)(C >>> 8), (byte)C,
- (byte)(D >>> 24), (byte)(D >>> 16),
- (byte)(D >>> 8), (byte)D};
-
- engineReset ();
- return result;
- }
-
- private int F( int X, int Y, int Z)
- {
- return ((X & Y) | (~X & Z));
- }
-
- private int G( int X, int Y, int Z)
- {
- return ((X & Z) | (Y & ~Z));
- }
-
- private int H( int X, int Y, int Z)
- {
- return (X ^ Y ^ Z);
- }
-
- private int I( int X, int Y, int Z)
- {
- return (Y ^ (X | ~Z));
- }
-
- private int rotateLeft( int i, int count)
- {
- //Taken from FIPS 180-1
- return ( (i << count) | (i >>> (32 - count)) ) ;
- }
-
- /* Round 1. */
- private int FF( int a, int b, int c, int d, int k, int s, int i)
- {
- /* Let [abcd k s i] denote the operation */
- a += F(b,c,d) + k + i;
- return b + rotateLeft(a, s);
- }
- /* Round 2. */
- private int GG( int a, int b, int c, int d, int k, int s, int i)
- {
- /* Let [abcd k s i] denote the operation */
- a += G(b,c,d) + k + i;
- return b + rotateLeft(a, s);
- }
- /* Round 3. */
- private int HH( int a, int b, int c, int d, int k, int s, int i)
- {
- /* Let [abcd k s t] denote the operation */
- a += H(b,c,d) + k + i;
- return b + rotateLeft(a, s);
- }
-
- /* Round 4. */
- private int II( int a, int b, int c, int d, int k, int s, int i)
- {
- /* Let [abcd k s t] denote the operation */
- a += I(b,c,d) + k + i;
- return b + rotateLeft(a, s);
- }
-
- private int SWAP(int n)
- {
- //Copied from md5.c in FSF Gnu Privacy Guard 0.9.2
- return (( (0xff & n) << 24) | ((n & 0xff00) << 8) | ((n >>> 8) & 0xff00) | (n >>> 24));
- }
-
- private void munch()
- {
- int AA,BB,CC,DD, j;
- int X[] = new int[16];
-
- /* Copy block i into X. */
- for(j = 0; j < 16; j++)
- X[j] = SWAP(W[j]);
-
- /* Save A as AA, B as BB, C as CC, and D as DD. */
- AA = A;
- BB = B;
- CC = C;
- DD = D;
-
- /* The hex constants are from md5.c
- in FSF Gnu Privacy Guard 0.9.2 */
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- A = FF(A,B,C,D, X[0], 7, 0xd76aa478);
- D = FF(D,A,B,C, X[1], 12, 0xe8c7b756);
- C = FF(C,D,A,B, X[2], 17, 0x242070db);
- B = FF(B,C,D,A, X[3], 22, 0xc1bdceee);
-
- A = FF(A,B,C,D, X[4], 7, 0xf57c0faf);
- D = FF(D,A,B,C, X[5], 12, 0x4787c62a);
- C = FF(C,D,A,B, X[6], 17, 0xa8304613);
- B = FF(B,C,D,A, X[7], 22, 0xfd469501);
-
- A = FF(A,B,C,D, X[8], 7, 0x698098d8);
- D = FF(D,A,B,C, X[9], 12, 0x8b44f7af);
- C = FF(C,D,A,B, X[10], 17, 0xffff5bb1);
- B = FF(B,C,D,A, X[11], 22, 0x895cd7be);
-
- A = FF(A,B,C,D, X[12], 7, 0x6b901122);
- D = FF(D,A,B,C, X[13], 12, 0xfd987193);
- C = FF(C,D,A,B, X[14], 17, 0xa679438e);
- B = FF(B,C,D,A, X[15], 22, 0x49b40821);
-
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- A = GG(A,B,C,D, X[1], 5, 0xf61e2562);
- D = GG(D,A,B,C, X[6], 9, 0xc040b340);
- C = GG(C,D,A,B, X[11], 14, 0x265e5a51);
- B = GG(B,C,D,A, X[0], 20, 0xe9b6c7aa);
-
- A = GG(A,B,C,D, X[5], 5, 0xd62f105d);
- D = GG(D,A,B,C, X[10], 9, 0x02441453);
- C = GG(C,D,A,B, X[15], 14, 0xd8a1e681);
- B = GG(B,C,D,A, X[4], 20, 0xe7d3fbc8);
-
- A = GG(A,B,C,D, X[9], 5, 0x21e1cde6);
- D = GG(D,A,B,C, X[14], 9, 0xc33707d6);
- C = GG(C,D,A,B, X[3], 14, 0xf4d50d87);
- B = GG(B,C,D,A, X[8], 20, 0x455a14ed);
-
- A = GG(A,B,C,D, X[13], 5, 0xa9e3e905);
- D = GG(D,A,B,C, X[2], 9, 0xfcefa3f8);
- C = GG(C,D,A,B, X[7], 14, 0x676f02d9);
- B = GG(B,C,D,A, X[12], 20, 0x8d2a4c8a);
-
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- A = HH(A,B,C,D, X[5], 4, 0xfffa3942);
- D = HH(D,A,B,C, X[8], 11, 0x8771f681);
- C = HH(C,D,A,B, X[11], 16, 0x6d9d6122);
- B = HH(B,C,D,A, X[14], 23, 0xfde5380c);
-
- A = HH(A,B,C,D, X[1], 4, 0xa4beea44);
- D = HH(D,A,B,C, X[4], 11, 0x4bdecfa9);
- C = HH(C,D,A,B, X[7], 16, 0xf6bb4b60);
- B = HH(B,C,D,A, X[10], 23, 0xbebfbc70);
-
- A = HH(A,B,C,D, X[13], 4, 0x289b7ec6);
- D = HH(D,A,B,C, X[0], 11, 0xeaa127fa);
- C = HH(C,D,A,B, X[3], 16, 0xd4ef3085);
- B = HH(B,C,D,A, X[6], 23, 0x04881d05);
-
- A = HH(A,B,C,D, X[9], 4, 0xd9d4d039);
- D = HH(D,A,B,C, X[12], 11, 0xe6db99e5);
- C = HH(C,D,A,B, X[15], 16, 0x1fa27cf8);
- B = HH(B,C,D,A, X[2], 23, 0xc4ac5665);
-
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- A = II(A,B,C,D, X[0], 6, 0xf4292244);
- D = II(D,A,B,C, X[7], 10, 0x432aff97);
- C = II(C,D,A,B, X[14], 15, 0xab9423a7);
- B = II(B,C,D,A, X[5], 21, 0xfc93a039);
-
- A = II(A,B,C,D, X[12], 6, 0x655b59c3);
- D = II(D,A,B,C, X[3], 10, 0x8f0ccc92);
- C = II(C,D,A,B, X[10], 15, 0xffeff47d);
- B = II(B,C,D,A, X[1], 21, 0x85845dd1);
-
- A = II(A,B,C,D, X[8], 6, 0x6fa87e4f);
- D = II(D,A,B,C, X[15], 10, 0xfe2ce6e0);
- C = II(C,D,A,B, X[6], 15, 0xa3014314);
- B = II(B,C,D,A, X[13], 21, 0x4e0811a1);
-
- A = II(A,B,C,D, X[4], 6, 0xf7537e82);
- D = II(D,A,B,C, X[11], 10, 0xbd3af235);
- C = II(C,D,A,B, X[2], 15, 0x2ad7d2bb);
- B = II(B,C,D,A, X[9], 21, 0xeb86d391);
-
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- A = A + AA;
- B = B + BB;
- C = C + CC;
- D = D + DD;
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java b/libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java
index ab8943443ec..880163731f1 100644
--- a/libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java
+++ b/libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package gnu.java.security.provider;
import gnu.java.security.OID;
+import gnu.java.security.Registry;
+import gnu.java.security.key.dss.DSSPublicKey;
import gnu.java.security.x509.GnuPKIExtension;
import gnu.java.security.x509.PolicyNodeImpl;
import gnu.java.security.x509.X509CRLSelectorImpl;
@@ -241,8 +243,11 @@ public class PKIXCertPathValidatorImpl extends CertPathValidatorSpi
if (!(prevKey instanceof DSAPublicKey))
throw new InvalidKeyException("DSA keys not chainable");
dsa = ((DSAPublicKey) prevKey).getParams();
- pubKey = new GnuDSAPublicKey(((DSAPublicKey) pubKey).getY(),
- dsa.getP(), dsa.getQ(), dsa.getG());
+ pubKey = new DSSPublicKey(Registry.X509_ENCODING_ID,
+ dsa.getP(),
+ dsa.getQ(),
+ dsa.getG(),
+ ((DSAPublicKey) pubKey).getY());
}
}
if (sigProvider == null)
diff --git a/libjava/classpath/gnu/java/security/provider/RSA.java b/libjava/classpath/gnu/java/security/provider/RSA.java
deleted file mode 100644
index c3cfbbf79f1..00000000000
--- a/libjava/classpath/gnu/java/security/provider/RSA.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/* RSA.java -- RSA PKCS#1 signatures.
- Copyright (C) 2004 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.java.security.provider;
-
-import gnu.java.security.OID;
-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 java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.MessageDigest;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.SignatureException;
-import java.security.SignatureSpi;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.ArrayList;
-
-public abstract class RSA extends SignatureSpi implements Cloneable
-{
-
- // Constants and fields.
- // -------------------------------------------------------------------------
-
- /**
- * digestAlgorithm OBJECT IDENTIFIER ::=
- * { iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) }
- */
- protected static final OID DIGEST_ALGORITHM = new OID("1.2.840.113549.2");
-
- protected final OID digestAlgorithm;
- protected final MessageDigest md;
- protected RSAPrivateKey signerKey;
- protected RSAPublicKey verifierKey;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- protected RSA(MessageDigest md, OID digestAlgorithm)
- {
- super();
- this.md = md;
- this.digestAlgorithm = digestAlgorithm;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public Object clone() throws CloneNotSupportedException
- {
- return super.clone();
- }
-
- protected Object engineGetParameter(String param)
- {
- throw new UnsupportedOperationException("deprecated");
- }
-
- protected void engineSetParameter(String param, Object value)
- {
- throw new UnsupportedOperationException("deprecated");
- }
-
- protected void engineInitSign(PrivateKey privateKey)
- throws InvalidKeyException
- {
- if (!(privateKey instanceof RSAPrivateKey))
- throw new InvalidKeyException();
- verifierKey = null;
- signerKey = (RSAPrivateKey) privateKey;
- }
-
- protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
- throws InvalidKeyException
- {
- // This class does not need random bytes.
- engineInitSign(privateKey);
- }
-
- protected void engineInitVerify(PublicKey publicKey)
- throws InvalidKeyException
- {
- if (!(publicKey instanceof RSAPublicKey))
- throw new InvalidKeyException();
- signerKey = null;
- verifierKey = (RSAPublicKey) publicKey;
- }
-
- protected void engineUpdate(byte b) throws SignatureException
- {
- if (signerKey == null && verifierKey == null)
- throw new SignatureException("not initialized");
- md.update(b);
- }
-
- protected void engineUpdate(byte[] buf, int off, int len)
- throws SignatureException
- {
- if (signerKey == null && verifierKey == null)
- throw new SignatureException("not initialized");
- md.update(buf, off, len);
- }
-
- protected byte[] engineSign() throws SignatureException
- {
- if (signerKey == null)
- throw new SignatureException("not initialized for signing");
- //
- // The signature will be the RSA encrypted BER representation of
- // the following:
- //
- // DigestInfo ::= SEQUENCE {
- // digestAlgorithm DigestAlgorithmIdentifier,
- // digest Digest }
- //
- // DigestAlgorithmIdentifier ::= AlgorithmIdentifier
- //
- // Digest ::= OCTET STRING
- //
- ArrayList digestAlg = new ArrayList(2);
- digestAlg.add(new DERValue(DER.OBJECT_IDENTIFIER, digestAlgorithm));
- digestAlg.add(new DERValue(DER.NULL, null));
- ArrayList digestInfo = new ArrayList(2);
- digestInfo.add(new DERValue(DER.SEQUENCE, digestAlg));
- digestInfo.add(new DERValue(DER.OCTET_STRING, md.digest()));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- try
- {
- DERWriter.write(out, new DERValue(DER.SEQUENCE, digestInfo));
- }
- catch (IOException ioe)
- {
- throw new SignatureException(ioe.toString());
- }
- byte[] buf = out.toByteArray();
- md.reset();
-
- // k = octect length of the modulus.
- int k = signerKey.getModulus().bitLength();
- k = (k >>> 3) + ((k & 7) == 0 ? 0 : 1);
- if (buf.length < k - 3)
- {
- throw new SignatureException("RSA modulus too small");
- }
- byte[] d = new byte[k];
-
- // Padding type 1:
- // 00 | 01 | FF | ... | FF | 00 | D
- d[1] = 0x01;
- for (int i = 2; i < k - buf.length - 1; i++)
- d[i] = (byte) 0xFF;
- System.arraycopy(buf, 0, d, k - buf.length, buf.length);
-
- BigInteger eb = new BigInteger(d);
-
- byte[] ed = eb.modPow(signerKey.getPrivateExponent(),
- signerKey.getModulus()).toByteArray();
-
- // Ensure output is k octets long.
- if (ed.length < k)
- {
- byte[] b = new byte[k];
- System.arraycopy(eb, 0, b, k - ed.length, ed.length);
- ed = b;
- }
- else if (ed.length > k)
- {
- if (ed.length != k + 1)
- {
- throw new SignatureException("modPow result is larger than the modulus");
- }
- // Maybe an extra 00 octect.
- byte[] b = new byte[k];
- System.arraycopy(ed, 1, b, 0, k);
- ed = b;
- }
-
- return ed;
- }
-
- protected int engineSign(byte[] out, int off, int len)
- throws SignatureException
- {
- if (out == null || off < 0 || len < 0 || off+len > out.length)
- throw new SignatureException("illegal output argument");
- byte[] result = engineSign();
- if (result.length > len)
- throw new SignatureException("not enough space for signature");
- System.arraycopy(result, 0, out, off, result.length);
- return result.length;
- }
-
- protected boolean engineVerify(byte[] sig) throws SignatureException
- {
- if (verifierKey == null)
- throw new SignatureException("not initialized for verifying");
- if (sig == null)
- throw new SignatureException("no signature specified");
- int k = verifierKey.getModulus().bitLength();
- k = (k >>> 3) + ((k & 7) == 0 ? 0 : 1);
- if (sig.length != k)
- throw new SignatureException("signature is the wrong size (expecting "
- + k + " bytes, got " + sig.length + ")");
- BigInteger ed = new BigInteger(1, sig);
- byte[] eb = ed.modPow(verifierKey.getPublicExponent(),
- verifierKey.getModulus()).toByteArray();
-
- int i = 0;
- if (eb[0] == 0x00)
- {
- for (i = 1; i < eb.length && eb[i] == 0x00; i++);
- if (i == 1)
- throw new SignatureException("wrong RSA padding");
- i--;
- }
- else if (eb[0] == 0x01)
- {
- for (i = 1; i < eb.length && eb[i] != 0x00; i++)
- if (eb[i] != (byte) 0xFF)
- throw new IllegalArgumentException("wrong RSA padding");
- }
- else
- throw new SignatureException("wrong RSA padding type");
-
- byte[] d = new byte[eb.length-i-1];
- System.arraycopy(eb, i+1, d, 0, eb.length-i-1);
-
- DERReader der = new DERReader(d);
- try
- {
- DERValue val = der.read();
- if (val.getTag() != DER.SEQUENCE)
- throw new SignatureException("failed to parse DigestInfo");
- val = der.read();
- if (val.getTag() != DER.SEQUENCE)
- throw new SignatureException("failed to parse DigestAlgorithmIdentifier");
- boolean sequenceIsBer = val.getLength() == 0;
- val = der.read();
- if (val.getTag() != DER.OBJECT_IDENTIFIER)
- throw new SignatureException("failed to parse object identifier");
- if (!val.getValue().equals(digestAlgorithm))
- throw new SignatureException("digest algorithms do not match");
- val = der.read();
- // We should never see parameters here, since they are never used.
- if (val.getTag() != DER.NULL)
- throw new SignatureException("cannot handle digest parameters");
- if (sequenceIsBer)
- der.skip(1); // end-of-sequence byte.
- val = der.read();
- if (val.getTag() != DER.OCTET_STRING)
- throw new SignatureException("failed to parse Digest");
- return MessageDigest.isEqual(md.digest(), (byte[]) val.getValue());
- }
- catch (IOException ioe)
- {
- throw new SignatureException(ioe.toString());
- }
- }
-
- protected boolean engineVerify(byte[] sig, int off, int len)
- throws SignatureException
- {
- if (sig == null || off < 0 || len < 0 || off+len > sig.length)
- throw new SignatureException("illegal parameter");
- byte[] buf = new byte[len];
- System.arraycopy(sig, off, buf, 0, len);
- return engineVerify(buf);
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/RSAKeyFactory.java b/libjava/classpath/gnu/java/security/provider/RSAKeyFactory.java
deleted file mode 100644
index d13cbe510a1..00000000000
--- a/libjava/classpath/gnu/java/security/provider/RSAKeyFactory.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/* RSAKeyFactory.java -- RSA key factory.
- Copyright (C) 2004 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.java.security.provider;
-
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.KeyFactorySpi;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.security.spec.RSAPrivateKeySpec;
-import java.security.spec.RSAPublicKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-public class RSAKeyFactory extends KeyFactorySpi
-{
-
- // Default constructor.
- // -------------------------------------------------------------------------
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- protected PrivateKey engineGeneratePrivate(KeySpec spec)
- throws InvalidKeySpecException
- {
- if (spec instanceof RSAPrivateCrtKeySpec)
- {
- return new GnuRSAPrivateKey((RSAPrivateCrtKeySpec) spec);
- }
- if (spec instanceof RSAPrivateKeySpec)
- {
- return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
- ((RSAPrivateKeySpec) spec).getModulus(), null,
- ((RSAPrivateKeySpec) spec).getPrivateExponent(), null,
- null, null, null, null));
- }
- if (spec instanceof PKCS8EncodedKeySpec)
- {
- EncodedKeyFactory ekf = new EncodedKeyFactory();
- PrivateKey pk = ekf.engineGeneratePrivate(spec);
- if (pk instanceof RSAPrivateKey)
- return pk;
- }
- throw new InvalidKeySpecException();
- }
-
- protected PublicKey engineGeneratePublic(KeySpec spec)
- throws InvalidKeySpecException
- {
- if (spec instanceof RSAPublicKeySpec)
- {
- return new GnuRSAPublicKey((RSAPublicKeySpec) spec);
- }
- if (spec instanceof X509EncodedKeySpec)
- {
- EncodedKeyFactory ekf = new EncodedKeyFactory();
- PublicKey pk = ekf.engineGeneratePublic(spec);
- if (pk instanceof RSAPublicKey)
- return pk;
- }
- throw new InvalidKeySpecException();
- }
-
- protected KeySpec engineGetKeySpec(Key key, Class keySpec)
- throws InvalidKeySpecException
- {
- if (keySpec.isAssignableFrom(RSAPrivateCrtKeySpec.class)
- && (key instanceof RSAPrivateCrtKey))
- {
- return new RSAPrivateCrtKeySpec(
- ((RSAPrivateCrtKey) key).getModulus(),
- ((RSAPrivateCrtKey) key).getPublicExponent(),
- ((RSAPrivateCrtKey) key).getPrivateExponent(),
- ((RSAPrivateCrtKey) key).getPrimeP(),
- ((RSAPrivateCrtKey) key).getPrimeQ(),
- ((RSAPrivateCrtKey) key).getPrimeExponentP(),
- ((RSAPrivateCrtKey) key).getPrimeExponentQ(),
- ((RSAPrivateCrtKey) key).getCrtCoefficient());
- }
- if (keySpec.isAssignableFrom(RSAPrivateKeySpec.class)
- && (key instanceof RSAPrivateKey))
- {
- return new RSAPrivateKeySpec(
- ((RSAPrivateCrtKey) key).getModulus(),
- ((RSAPrivateCrtKey) key).getPrivateExponent());
- }
- if (keySpec.isAssignableFrom(RSAPublicKeySpec.class)
- && (key instanceof RSAPublicKey))
- {
- return new RSAPublicKeySpec(
- ((RSAPrivateCrtKey) key).getModulus(),
- ((RSAPrivateCrtKey) key).getPublicExponent());
- }
- if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class)
- && key.getFormat().equalsIgnoreCase("PKCS#8"))
- {
- return new PKCS8EncodedKeySpec(key.getEncoded());
- }
- if (keySpec.isAssignableFrom(X509EncodedKeySpec.class)
- && key.getFormat().equalsIgnoreCase("X.509"))
- {
- return new X509EncodedKeySpec(key.getEncoded());
- }
- throw new InvalidKeySpecException();
- }
-
- protected Key engineTranslateKey(Key key) throws InvalidKeyException
- {
- if (key instanceof RSAPrivateCrtKey)
- {
- return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
- ((RSAPrivateCrtKey) key).getModulus(),
- ((RSAPrivateCrtKey) key).getPublicExponent(),
- ((RSAPrivateCrtKey) key).getPrivateExponent(),
- ((RSAPrivateCrtKey) key).getPrimeP(),
- ((RSAPrivateCrtKey) key).getPrimeQ(),
- ((RSAPrivateCrtKey) key).getPrimeExponentP(),
- ((RSAPrivateCrtKey) key).getPrimeExponentQ(),
- ((RSAPrivateCrtKey) key).getCrtCoefficient()));
- }
- if (key instanceof RSAPrivateKey)
- {
- return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
- ((RSAPrivateKey) key).getModulus(), null,
- ((RSAPrivateKey) key).getPrivateExponent(), null,
- null, null, null, null));
- }
- if (key instanceof RSAPublicKey)
- {
- return new GnuRSAPublicKey(new RSAPublicKeySpec(
- ((RSAPrivateCrtKey) key).getModulus(),
- ((RSAPrivateCrtKey) key).getPublicExponent()));
- }
- throw new InvalidKeyException();
- }
-}
diff --git a/libjava/classpath/gnu/java/security/provider/SHA.java b/libjava/classpath/gnu/java/security/provider/SHA.java
deleted file mode 100644
index e3b09bc5603..00000000000
--- a/libjava/classpath/gnu/java/security/provider/SHA.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/* SHA.java -- Class implementing the SHA-1 algorithm as specified in [1].
- Copyright (C) 1999, 2000, 2002 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.java.security.provider;
-
-import java.security.MessageDigest;
-
-/**
- This class implements the SHA-1 algorithm as described in [1].
-
- [1] Federal Information Processing Standards Publication 180-1.
- Specifications for the Secure Hash Standard. April 17, 1995.
-
- @see java.security.MessageDigest
-*/
-public class SHA extends MessageDigest implements Cloneable
-{
- public SHA ()
- {
- super("SHA");
- engineReset ();
- }
-
- public int engineGetDigestLength()
- {
- return 20;
- }
-
- public void engineUpdate (byte b)
- {
- int i = ((int)bytecount) & 0x3f; //wgs
- int shift = (3 - i % 4) << 3;
- int idx = i / 4;
-
- i = (int)b;
- W[idx] = (W[idx] & ~(0xff << shift)) | ((i & 0xff) << shift);
-
- // if we've filled up a block, then process it
- if (((++bytecount) & 0x3f) == 0)
- munch ();
- }
-
- // This could be optimized.
- public void engineUpdate (byte bytes[], int off, int len)
- {
- if (len < 0)
- throw new ArrayIndexOutOfBoundsException ();
-
- int end = off + len;
- while (off < end)
- engineUpdate (bytes[off++]);
- }
-
- public void engineReset ()
- {
- bytecount = 0;
- // magic numbers from [1] p. 10.
- H0 = 0x67452301;
- H1 = 0xefcdab89;
- H2 = 0x98badcfe;
- H3 = 0x10325476;
- H4 = 0xc3d2e1f0;
- }
-
- public byte[] engineDigest ()
- {
- long bitcount = bytecount << 3;
- engineUpdate ((byte)0x80); // 10000000 in binary; the start of the padding
-
- // add the rest of the padding to fill this block out, but leave 8
- // bytes to put in the original bytecount
- while ((bytecount & 0x3f) != 56)
- engineUpdate ((byte)0);
-
- // add the length of the original, unpadded block to the end of
- // the padding
- W[14] = (int)(bitcount >>> 32);
- W[15] = (int)bitcount;
- bytecount += 8;
-
- // digest the fully padded block
- munch ();
-
- byte[] result
- = new byte[] {(byte)(H0 >>> 24), (byte)(H0 >>> 16),
- (byte)(H0 >>> 8), (byte)H0,
- (byte)(H1 >>> 24), (byte)(H1 >>> 16),
- (byte)(H1 >>> 8), (byte)H1,
- (byte)(H2 >>> 24), (byte)(H2 >>> 16),
- (byte)(H2 >>> 8), (byte)H2,
- (byte)(H3 >>> 24), (byte)(H3 >>> 16),
- (byte)(H3 >>> 8), (byte)H3,
- (byte)(H4 >>> 24), (byte)(H4 >>> 16),
- (byte)(H4 >>> 8), (byte)H4};
-
- engineReset ();
- return result;
- }
-
- // Process a single block. This is pretty much copied verbatim from
- // [1] pp. 9, 10.
- private void munch ()
- {
- for (int t = 16; t < 80; ++ t)
- {
- int Wt = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
- W[t] = Wt << 1 | Wt >>> 31;
- }
-
- int A = H0;
- int B = H1;
- int C = H2;
- int D = H3;
- int E = H4;
-
- for (int t = 0; t < 20; ++ t)
- {
- int TEMP = (A << 5 | A >>> 27) // S^5(A)
- + ((B & C) | (~B & D)) // f_t(B,C,D)
- + E + W[t]
- + 0x5a827999; // K_t
-
- E = D;
- D = C;
- C = B << 30 | B >>> 2; // S^30(B)
- B = A;
- A = TEMP;
- }
-
- for (int t = 20; t < 40; ++ t)
- {
- int TEMP = (A << 5 | A >>> 27) // S^5(A)
- + (B ^ C ^ D) // f_t(B,C,D)
- + E + W[t]
- + 0x6ed9eba1; // K_t
-
- E = D;
- D = C;
- C = B << 30 | B >>> 2; // S^30(B)
- B = A;
- A = TEMP;
- }
-
- for (int t = 40; t < 60; ++ t)
- {
- int TEMP = (A << 5 | A >>> 27) // S^5(A)
- + (B & C | B & D | C & D) // f_t(B,C,D)
- + E + W[t]
- + 0x8f1bbcdc; // K_t
-
- E = D;
- D = C;
- C = B << 30 | B >>> 2; // S^30(B)
- B = A;
- A = TEMP;
- }
-
- for (int t = 60; t < 80; ++ t)
- {
- int TEMP = (A << 5 | A >>> 27) // S^5(A)
- + (B ^ C ^ D) // f_t(B,C,D)
- + E + W[t]
- + 0xca62c1d6; // K_t
-
- E = D;
- D = C;
- C = B << 30 | B >>> 2; // S^30(B)
- B = A;
- A = TEMP;
- }
-
- H0 += A;
- H1 += B;
- H2 += C;
- H3 += D;
- H4 += E;
-
- // Reset W by clearing it.
- for (int t = 0; t < 80; ++ t)
- W[t] = 0;
- }
-
- public Object clone ()
- {
- return new SHA (this);
- }
-
- private SHA (SHA copy)
- {
- this ();
- bytecount = copy.bytecount;
- H0 = copy.H0;
- H1 = copy.H1;
- H2 = copy.H2;
- H3 = copy.H3;
- H4 = copy.H4;
- System.arraycopy (copy.W, 0, W, 0, 80);
- }
-
- private final int W[] = new int[80];
- private long bytecount;
- private int H0;
- private int H1;
- private int H2;
- private int H3;
- private int H4;
-}
diff --git a/libjava/classpath/gnu/java/security/provider/SHA1PRNG.java b/libjava/classpath/gnu/java/security/provider/SHA1PRNG.java
deleted file mode 100644
index e4058e3079b..00000000000
--- a/libjava/classpath/gnu/java/security/provider/SHA1PRNG.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/* SHA1PRNG.java --- Secure Random SPI SHA1PRNG
- Copyright (C) 1999, 2001, 2003, 2005 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.java.security.provider;
-
-import java.io.Serializable;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandomSpi;
-import java.util.Random;
-
-public class SHA1PRNG extends SecureRandomSpi implements Serializable
-{
- MessageDigest digest;
- byte seed[];
- byte data[];
- int seedpos;
- int datapos;
- private boolean seeded = false; // set to true when we seed this
- /**
- * The size of seed.
- */
- private static final int SEED_SIZE = 20;
- /**
- * The size of data.
- */
- private static final int DATA_SIZE = 40;
-
- /**
- * Create a new SHA-1 pseudo-random number generator.
- */
- public SHA1PRNG()
- {
- try {
- digest = MessageDigest.getInstance("SHA");
- } catch ( NoSuchAlgorithmException nsae) {
-// System.out.println("Failed to find SHA Message Digest: " + nsae);
-// nsae.printStackTrace();
- throw new InternalError ("no SHA implementation found");
- }
-
- seed = new byte[SEED_SIZE];
- seedpos = 0;
- data = new byte[DATA_SIZE];
- datapos = SEED_SIZE; // try to force hashing a first block
- }
-
- public void engineSetSeed(byte[] seed)
- {
- for(int i = 0; i < seed.length; i++)
- this.seed[seedpos++ % SEED_SIZE] ^= seed[i];
- seedpos %= SEED_SIZE;
-
- }
-
- public void engineNextBytes(byte[] bytes)
- {
- ensureIsSeeded ();
- int loc = 0;
- while (loc < bytes.length)
- {
- int copy = Math.min (bytes.length - loc, SEED_SIZE - datapos);
-
- if (copy > 0)
- {
- System.arraycopy (data, datapos, bytes, loc, copy);
- datapos += copy;
- loc += copy;
- }
- else
- {
- // No data ready for copying, so refill our buffer.
- System.arraycopy( seed, 0, data, SEED_SIZE, SEED_SIZE);
- byte[] digestdata = digest.digest( data );
- System.arraycopy( digestdata, 0, data, 0, SEED_SIZE);
- datapos = 0;
- }
- }
- }
-
- public byte[] engineGenerateSeed(int numBytes)
- {
- byte tmp[] = new byte[numBytes];
-
- engineNextBytes( tmp );
- return tmp;
- }
-
- private void ensureIsSeeded()
- {
- if (!seeded)
- {
- new Random(0L).nextBytes(seed);
-
- byte[] digestdata = digest.digest(data);
- System.arraycopy(digestdata, 0, data, 0, SEED_SIZE);
-
- seeded = true;
- }
- }
-
-}
diff --git a/libjava/classpath/gnu/java/security/sig/BaseSignature.java b/libjava/classpath/gnu/java/security/sig/BaseSignature.java
new file mode 100644
index 00000000000..dd964d4819d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/BaseSignature.java
@@ -0,0 +1,261 @@
+/* BaseSignature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig;
+
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.PRNG;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * <p>A base abstract class to facilitate implementations of concrete
+ * Signatures.</p>
+ */
+public abstract class BaseSignature implements ISignature
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The canonical name of this signature scheme. */
+ protected String schemeName;
+
+ /** The underlying message digest instance for this signature scheme. */
+ protected IMessageDigest md;
+
+ /** The public key to use when verifying signatures. */
+ protected PublicKey publicKey;
+
+ /** The private key to use when generating signatures (signing). */
+ protected PrivateKey privateKey;
+
+ /** The optional {@link Random} instance to use. */
+ private Random rnd;
+
+ /** The optional {@link IRandom} instance to use. */
+ private IRandom irnd;
+
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Trivial constructor.
+ *
+ * @param schemeName the name of this signature scheme.
+ * @param md the underlying instance of the message digest algorithm.
+ * @throws IllegalArgumentException if the designated hash instance is
+ * <code>null</code>.
+ */
+ protected BaseSignature(String schemeName, IMessageDigest md)
+ {
+ super();
+
+ this.schemeName = schemeName;
+ if (md == null)
+ throw new IllegalArgumentException("Message digest MUST NOT be null");
+
+ this.md = md;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.sig.ISignature interface implementation ----------------------
+
+ public String name()
+ {
+ return schemeName + "-" + md.name();
+ }
+
+ public void setupVerify(Map attributes) throws IllegalArgumentException
+ {
+ setup(attributes);
+
+ // do we have a public key?
+ PublicKey key = (PublicKey) attributes.get(VERIFIER_KEY);
+ if (key != null)
+ {
+ setupForVerification(key);
+ }
+ }
+
+ public void setupSign(Map attributes) throws IllegalArgumentException
+ {
+ setup(attributes);
+
+ // do we have a private key?
+ PrivateKey key = (PrivateKey) attributes.get(SIGNER_KEY);
+ if (key != null)
+ {
+ setupForSigning(key);
+ }
+ }
+
+ public void update(byte b)
+ {
+ if (md == null)
+ {
+ throw new IllegalStateException();
+ }
+ md.update(b);
+ }
+
+ public void update(byte[] b, int off, int len)
+ {
+ if (md == null)
+ {
+ throw new IllegalStateException();
+ }
+ md.update(b, off, len);
+ }
+
+ public Object sign()
+ {
+ if (md == null || privateKey == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ return generateSignature();
+ }
+
+ public boolean verify(Object sig)
+ {
+ if (md == null || publicKey == null)
+ {
+ throw new IllegalStateException();
+ }
+
+ return verifySignature(sig);
+ }
+
+ // abstract methods to be implemented by concrete subclasses ---------------
+
+ public abstract Object clone();
+
+ protected abstract void setupForVerification(PublicKey key)
+ throws IllegalArgumentException;
+
+ protected abstract void setupForSigning(PrivateKey key)
+ throws IllegalArgumentException;
+
+ protected abstract Object generateSignature() throws IllegalStateException;
+
+ protected abstract boolean verifySignature(Object signature)
+ throws IllegalStateException;
+
+ // Other instance methods --------------------------------------------------
+
+ /** Initialises the internal fields of this instance. */
+ protected void init()
+ {
+ md.reset();
+ rnd = null;
+ irnd = null;
+ publicKey = null;
+ privateKey = null;
+ }
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ protected void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else if (irnd != null)
+ {
+ try
+ {
+ irnd.nextBytes(buffer, 0, buffer.length);
+ }
+ catch (IllegalStateException x)
+ {
+ throw new RuntimeException("nextRandomBytes(): "
+ + String.valueOf(x));
+ }
+ catch (LimitReachedException x)
+ {
+ throw new RuntimeException("nextRandomBytes(): "
+ + String.valueOf(x));
+ }
+ }
+ else
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private void setup(Map attributes)
+ {
+ init();
+
+ // do we have a Random or SecureRandom, or should we use our own?
+ Object obj = attributes.get(SOURCE_OF_RANDOMNESS);
+ if (obj instanceof Random)
+ {
+ rnd = (Random) obj;
+ }
+ else if (obj instanceof IRandom)
+ {
+ irnd = (IRandom) obj;
+ }
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/ISignature.java b/libjava/classpath/gnu/java/security/sig/ISignature.java
new file mode 100644
index 00000000000..77653ee3722
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/ISignature.java
@@ -0,0 +1,169 @@
+/* ISignature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig;
+
+import java.util.Map;
+
+/**
+ * <p>The visible methods of every signature-with-appendix scheme.</p>
+ *
+ * <p>The Handbook of Applied Cryptography (HAC), by A. Menezes &amp; al. states:
+ * "Digital signature schemes which require the message as input to the
+ * verification algorithm are called <i>digital signature schemes with
+ * appendix</i>. ... They rely on cryptographic hash functions rather than
+ * customised redundancy functions, and are less prone to existential forgery
+ * attacks."</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cacr.math.uwaterloo.ca/hac/">Handbook of Applied
+ * Cryptography</a>, Alfred J. Menezes, Paul C. van Oorschot and Scott A.
+ * Vanstone. Section 11.2.2 Digital signature schemes with appendix.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface ISignature extends Cloneable
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** Property name of the verifier's public key. */
+ public static final String VERIFIER_KEY = "gnu.crypto.sig.public.key";
+
+ /** Property name of the signer's private key. */
+ public static final String SIGNER_KEY = "gnu.crypto.sig.private.key";
+
+ /**
+ * Property name of an optional {@link java.security.SecureRandom},
+ * {@link java.util.Random}, or {@link gnu.crypto.prng.IRandom} instance to
+ * use. The default is to use a classloader singleton from
+ * {@link gnu.crypto.util.PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.sig.prng";
+
+ // Methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns the canonical name of this signature scheme.</p>
+ *
+ * @return the canonical name of this instance.
+ */
+ String name();
+
+ /**
+ * <p>Initialises this instance for signature verification.</p>
+ *
+ * @param attributes the attributes to use for setting up this instance.
+ * @throws IllegalArgumentException if the designated public key is not
+ * appropriate for this signature scheme.
+ * @see #SOURCE_OF_RANDOMNESS
+ * @see #VERIFIER_KEY
+ */
+ void setupVerify(Map attributes) throws IllegalArgumentException;
+
+ /**
+ * <p>Initialises this instance for signature generation.</p>
+ *
+ * @param attributes the attributes to use for setting up this instance.
+ * @throws IllegalArgumentException if the designated private key is not
+ * appropriate for this signature scheme.
+ * @see #SOURCE_OF_RANDOMNESS
+ * @see #SIGNER_KEY
+ */
+ void setupSign(Map attributes) throws IllegalArgumentException;
+
+ /**
+ * <p>Digests one byte of a message for signing or verification purposes.</p>
+ *
+ * @param b the message byte to digest.
+ * @throws IllegalStateException if this instance was not setup for
+ * signature generation/verification.
+ */
+ void update(byte b) throws IllegalStateException;
+
+ /**
+ * <p>Digests a sequence of bytes from a message for signing or verification
+ * purposes.</p>
+ *
+ * @param buffer the byte sequence to consider.
+ * @param offset the byte poisition in <code>buffer</code> of the first byte
+ * to consider.
+ * @param length the number of bytes in <code>buffer</code> starting from the
+ * byte at index <code>offset</code> to digest.
+ * @throws IllegalStateException if this instance was not setup for
+ * signature generation/verification.
+ */
+ void update(byte[] buffer, int offset, int length)
+ throws IllegalStateException;
+
+ /**
+ * <p>Terminates a signature generation phase by digesting and processing the
+ * context of the underlying message digest algorithm instance.</p>
+ *
+ * @return a {@link Object} representing the native output of the signature
+ * scheme implementation.
+ * @throws IllegalStateException if this instance was not setup for
+ * signature generation.
+ */
+ Object sign() throws IllegalStateException;
+
+ /**
+ * <p>Terminates a signature verification phase by digesting and processing
+ * the context of the underlying message digest algorithm instance.</p>
+ *
+ * @param signature a native signature object previously generated by an
+ * invocation of the <code>sign()</code> method.
+ * @return <code>true</code> iff the outpout of the verification phase
+ * confirms that the designated signature object has been generated using the
+ * corresponding public key of the recepient.
+ * @throws IllegalStateException if this instance was not setup for
+ * signature verification.
+ */
+ boolean verify(Object signature) throws IllegalStateException;
+
+ /**
+ * <p>Returns a clone copy of this instance.</p>
+ *
+ * @return a clone copy of this instance.
+ */
+ Object clone();
+}
diff --git a/libjava/classpath/gnu/java/security/sig/ISignatureCodec.java b/libjava/classpath/gnu/java/security/sig/ISignatureCodec.java
new file mode 100644
index 00000000000..119eca5fd0d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/ISignatureCodec.java
@@ -0,0 +1,68 @@
+/* ISignatureCodec.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig;
+
+import gnu.java.security.Registry;
+
+/**
+ * <p>The visible methods of an object that knows how to encode and decode
+ * cryptographic signatures. Codecs are useful for (a) externalising signature
+ * output data for storage and on-the-wire transmission, as well as (b) re-
+ * creating their internal Java representation from external sources.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public interface ISignatureCodec
+{
+
+ // Constants
+ // -------------------------------------------------------------------------
+
+ /** Constant identifying the <i>Raw</i> encoding format. */
+ int RAW_FORMAT = Registry.RAW_ENCODING_ID;
+
+ // Method(s)
+ // -------------------------------------------------------------------------
+
+ int getFormatID();
+
+ byte[] encodeSignature(Object signature);
+
+ Object decodeSignature(byte[] input);
+}
diff --git a/libjava/classpath/gnu/java/security/sig/SignatureCodecFactory.java b/libjava/classpath/gnu/java/security/sig/SignatureCodecFactory.java
new file mode 100644
index 00000000000..c5b2ccd4bc8
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/SignatureCodecFactory.java
@@ -0,0 +1,226 @@
+/* SignatureCodecFactory.java -- Factory to instantiate Signature codecs
+ 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.java.security.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.sig.dss.DSSSignatureRawCodec;
+import gnu.java.security.sig.dss.DSSSignatureX509Codec;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureRawCodec;
+import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
+import gnu.java.security.sig.rsa.RSAPSSSignatureRawCodec;
+import gnu.java.security.util.FormatUtil;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A <i>Factory</i> class to instantiate Signature codecs.
+ */
+public class SignatureCodecFactory
+{
+ private static Set names;
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private SignatureCodecFactory()
+ {
+ super();
+ }
+
+ /**
+ * Returns the appropriate codec given a composed signature algorithm and an
+ * encoding format. A composed name is formed by the concatenation of the
+ * canonical signature algorithm name, the forward slash character
+ * <code>/</code> and the canonical name of the encoding format.
+ * <p>
+ * When the encoding format name is missing, the Raw encoding format is
+ * assumed. When this is the case the trailing forward slash is discarded from
+ * the name.
+ *
+ * @param name the case-insensitive, possibly composed, signature codec name.
+ * @return an instance of the signaturecodec, or <code>null</code> if none
+ * found.
+ */
+ public static ISignatureCodec getInstance(String name)
+ {
+ if (name == null)
+ return null;
+
+ name = name.trim();
+ if (name.length() == 0)
+ return null;
+
+ if (name.startsWith("/"))
+ return null;
+
+ if (name.endsWith("/"))
+ return getInstance(name.substring(0, name.length() - 1),
+ Registry.RAW_ENCODING_ID);
+
+ int i = name.indexOf("/");
+ if (i == - 1)
+ return getInstance(name, Registry.RAW_ENCODING_ID);
+
+ String sigName = name.substring(0, i);
+ String formatName = name.substring(i + 1);
+ return getInstance(sigName, formatName);
+ }
+
+ /**
+ * Returns an instance of a signature codec given the canonical name of the
+ * signature algorithm, and that of the encoding format.
+ *
+ * @param name the case-insensitive signature algorithm name.
+ * @param format the name of the format to use when encodigng/decoding
+ * signatures generated by the named algorithm.
+ * @return an instance of the signature codec, or <code>null</code> if none
+ * found.
+ */
+ public static ISignatureCodec getInstance(String name, String format)
+ {
+ int formatID = FormatUtil.getFormatID(format);
+ if (formatID == 0)
+ return null;
+
+ return getInstance(name, formatID);
+ }
+
+ /**
+ * Returns an instance of a signature codec given the canonical name of the
+ * signature algorithm, and the identifier of the format to use when
+ * encoding/decoding signatures generated by that algorithm.
+ *
+ * @param name the case-insensitive signature algorithm name.
+ * @param formatID the identifier of the format to use when encoding /
+ * decoding signatures generated by the designated algorithm.
+ * @return an instance of the signature codec, or <code>null</code> if none
+ * found.
+ */
+ public static ISignatureCodec getInstance(String name, int formatID)
+ {
+ if (name == null)
+ return null;
+
+ name = name.trim();
+ switch (formatID)
+ {
+ case Registry.RAW_ENCODING_ID:
+ return getRawCodec(name);
+ case Registry.X509_ENCODING_ID:
+ return getX509Codec(name);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a {@link Set} of supported signature codec names.
+ *
+ * @return a {@link Set} of the names of supported signature codec (Strings).
+ */
+ public static synchronized final Set getNames()
+ {
+ if (names == null)
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.DSS_SIG + "/" + Registry.RAW_ENCODING_SHORT_NAME);
+ hs.add(Registry.DSS_SIG + "/" + Registry.X509_ENCODING_SORT_NAME);
+ Set hashNames = HashFactory.getNames();
+ for (Iterator it = hashNames.iterator(); it.hasNext();)
+ {
+ String mdName = (String) it.next();
+ String name = Registry.RSA_PKCS1_V1_5_SIG + "-" + mdName;
+ hs.add(name + "/" + Registry.RAW_ENCODING_SHORT_NAME);
+ hs.add(name + "/" + Registry.X509_ENCODING_SORT_NAME);
+ name = Registry.RSA_PSS_SIG + "-" + mdName;
+ hs.add(name + "/" + Registry.RAW_ENCODING_SHORT_NAME);
+ }
+
+ names = Collections.unmodifiableSet(hs);
+ }
+
+ return names;
+ }
+
+ /**
+ * @param name the trimmed name of a signature algorithm.
+ * @return a Raw format codec for the designated signature algorithm, or
+ * <code>null</code> if none exists.
+ */
+ private static ISignatureCodec getRawCodec(String name)
+ {
+ ISignatureCodec result = null;
+ if (name.equalsIgnoreCase(Registry.DSA_SIG)
+ || name.equalsIgnoreCase(Registry.DSS_SIG))
+ result = new DSSSignatureRawCodec();
+ else
+ {
+ name = name.toLowerCase();
+ if (name.startsWith(Registry.RSA_PKCS1_V1_5_SIG))
+ result = new RSAPKCS1V1_5SignatureRawCodec();
+ else if (name.startsWith(Registry.RSA_PSS_SIG))
+ result = new RSAPSSSignatureRawCodec();
+ }
+
+ return result;
+ }
+
+ /**
+ * @param name the trimmed name of a signature algorithm.
+ * @return a X.509 format codec for the designated signature algorithm, or
+ * <code>null</code> if none exists.
+ */
+ private static ISignatureCodec getX509Codec(String name)
+ {
+ ISignatureCodec result = null;
+ if (name.equalsIgnoreCase(Registry.DSA_SIG)
+ || name.equalsIgnoreCase(Registry.DSS_SIG))
+ result = new DSSSignatureX509Codec();
+ else
+ {
+ name = name.toLowerCase();
+ if (name.startsWith(Registry.RSA_PKCS1_V1_5_SIG))
+ result = new RSAPKCS1V1_5SignatureX509Codec();
+ }
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/SignatureFactory.java b/libjava/classpath/gnu/java/security/sig/SignatureFactory.java
new file mode 100644
index 00000000000..d5bd728ad8a
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/SignatureFactory.java
@@ -0,0 +1,113 @@
+/* SignatureFactory.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.dss.DSSSignature;
+import gnu.java.security.sig.rsa.RSASignatureFactory;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A Factory to instantiate signature-with-appendix handlers.
+ */
+public class SignatureFactory
+{
+ private static Set names;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private SignatureFactory()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns an instance of a signature-with-appendix scheme given its name.
+ *
+ * @param ssa the case-insensitive signature-with-appendix scheme name.
+ * @return an instance of the scheme, or <code>null</code> if none found.
+ */
+ public static final ISignature getInstance(String ssa)
+ {
+ if (ssa == null)
+ {
+ return null;
+ }
+
+ ssa = ssa.trim();
+ ssa = ssa.toLowerCase();
+ ISignature result = null;
+ if (ssa.equalsIgnoreCase(Registry.DSA_SIG) || ssa.equals(Registry.DSS_SIG))
+ {
+ result = new DSSSignature();
+ }
+ else if (ssa.startsWith(Registry.RSA_SIG_PREFIX))
+ result = RSASignatureFactory.getInstance(ssa);
+
+ return result;
+ }
+
+ /**
+ * Returns a {@link Set} of signature-with-appendix scheme names supported
+ * by this <i>Factory</i>.
+ *
+ * @return a {@link Set} of signature-with-appendix scheme names (Strings).
+ */
+ public static synchronized final Set getNames()
+ {
+ if (names == null)
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.DSS_SIG);
+ hs.addAll(RSASignatureFactory.getNames());
+
+ names = Collections.unmodifiableSet(hs);
+ }
+
+ return names;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/dss/DSSSignature.java b/libjava/classpath/gnu/java/security/sig/dss/DSSSignature.java
new file mode 100644
index 00000000000..6bedfaefa3a
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/dss/DSSSignature.java
@@ -0,0 +1,347 @@
+/* DSSSignature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.sig.BaseSignature;
+import gnu.java.security.sig.ISignature;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * <p>The DSS (Digital Signature Standard) algorithm makes use of the following
+ * parameters:</p>
+ *
+ * <ol>
+ * <li>p: A prime modulus, where <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup>
+ * </code> for <code>512 &lt;= L &lt;= 1024</code> and <code>L</code> a
+ * multiple of <code>64</code>.</li>
+ * <li>q: A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup>
+ * &lt; q &lt; 2<sup>160</sup></code>.</li>
+ * <li>g: Where <code>g = h<sup>(p-1)</sup>/q mod p</code>, where
+ * <code>h</code> is any integer with <code>1 &lt; h &lt; p - 1</code> such
+ * that <code>h<sup> (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order
+ * <code>q mod p</code>).</li>
+ * <li>x: A randomly or pseudorandomly generated integer with <code>0 &lt; x
+ * &lt; q</code>.</li>
+ * <li>y: <code>y = g<sup>x</sup> mod p</code>.</li>
+ * <li>k: A randomly or pseudorandomly generated integer with <code>0 &lt; k
+ * &lt; q</code>.</li>
+ * </ol>
+ *
+ * <p>The integers <code>p</code>, <code>q</code>, and <code>g</code> can be
+ * public and can be common to a group of users. A user's private and public
+ * keys are <code>x</code> and <code>y</code>, respectively. They are normally
+ * fixed for a period of time. Parameters <code>x</code> and <code>k</code> are
+ * used for signature generation only, and must be kept secret. Parameter
+ * <code>k</code> must be regenerated for each signature.</p>
+ *
+ * <p>The signature of a message <code>M</code> is the pair of numbers <code>r</code>
+ * and <code>s</code> computed according to the equations below:</p>
+ *
+ * <ul>
+ * <li><code>r = (g<sup>k</sup> mod p) mod q</code> and</li>
+ * <li><code>s = (k<sup>-1</sup>(SHA(M) + xr)) mod q</code>.</li>
+ * </ul>
+ *
+ * <p>In the above, <code>k<sup>-1</sup></code> is the multiplicative inverse of
+ * <code>k</code>, <code>mod q</code>; i.e., <code>(k<sup>-1</sup> k) mod q = 1
+ * </code> and <code>0 &lt; k-1 &lt; q</code>. The value of <code>SHA(M)</code>
+ * is a 160-bit string output by the Secure Hash Algorithm specified in FIPS 180.
+ * For use in computing <code>s</code>, this string must be converted to an
+ * integer.</p>
+ *
+ * <p>As an option, one may wish to check if <code>r == 0</code> or <code>s == 0
+ * </code>. If either <code>r == 0</code> or <code>s == 0</code>, a new value
+ * of <code>k</code> should be generated and the signature should be
+ * recalculated (it is extremely unlikely that <code>r == 0</code> or <code>s ==
+ * 0</code> if signatures are generated properly).</p>
+ *
+ * <p>The signature is transmitted along with the message to the verifier.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital
+ * Signature Standard (DSS)</a>, Federal Information Processing Standards
+ * Publication 186. National Institute of Standards and Technology.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSSignature extends BaseSignature
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial 0-arguments constructor. */
+ public DSSSignature()
+ {
+ super(Registry.DSS_SIG, new Sha160());
+ }
+
+ /** Private constructor for cloning purposes. */
+ private DSSSignature(DSSSignature that)
+ {
+ this();
+
+ this.publicKey = that.publicKey;
+ this.privateKey = that.privateKey;
+ this.md = (IMessageDigest) that.md.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h)
+ {
+ final DSSSignature sig = new DSSSignature();
+ final Map attributes = new HashMap();
+ attributes.put(ISignature.SIGNER_KEY, k);
+ sig.setupSign(attributes);
+
+ return sig.computeRS(h);
+ }
+
+ public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h,
+ Random rnd)
+ {
+ final DSSSignature sig = new DSSSignature();
+ final Map attributes = new HashMap();
+ attributes.put(ISignature.SIGNER_KEY, k);
+ if (rnd != null)
+ {
+ attributes.put(ISignature.SOURCE_OF_RANDOMNESS, rnd);
+ }
+ sig.setupSign(attributes);
+
+ return sig.computeRS(h);
+ }
+
+ public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h,
+ IRandom irnd)
+ {
+ final DSSSignature sig = new DSSSignature();
+ final Map attributes = new HashMap();
+ attributes.put(ISignature.SIGNER_KEY, k);
+ if (irnd != null)
+ {
+ attributes.put(ISignature.SOURCE_OF_RANDOMNESS, irnd);
+ }
+ sig.setupSign(attributes);
+
+ return sig.computeRS(h);
+ }
+
+ public static final boolean verify(final DSAPublicKey k, final byte[] h,
+ final BigInteger[] rs)
+ {
+ final DSSSignature sig = new DSSSignature();
+ final Map attributes = new HashMap();
+ attributes.put(ISignature.VERIFIER_KEY, k);
+ sig.setupVerify(attributes);
+
+ return sig.checkRS(rs, h);
+ }
+
+ // Implementation of abstract methods in superclass
+ // -------------------------------------------------------------------------
+
+ public Object clone()
+ {
+ return new DSSSignature(this);
+ }
+
+ protected void setupForVerification(PublicKey k)
+ throws IllegalArgumentException
+ {
+ if (!(k instanceof DSAPublicKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ this.publicKey = k;
+ }
+
+ protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
+ {
+ if (!(k instanceof DSAPrivateKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ this.privateKey = k;
+ }
+
+ protected Object generateSignature() throws IllegalStateException
+ {
+ // BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP();
+ // BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ();
+ // BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG();
+ // BigInteger x = ((DSAPrivateKey) privateKey).getX();
+ // BigInteger m = new BigInteger(1, md.digest());
+ // BigInteger k, r, s;
+ //
+ // byte[] kb = new byte[20]; // we'll use 159 bits only
+ // while (true) {
+ // this.nextRandomBytes(kb);
+ // k = new BigInteger(1, kb);
+ // k.clearBit(159);
+ // r = g.modPow(k, p).mod(q);
+ // if (r.equals(BigInteger.ZERO)) {
+ // continue;
+ // }
+ // s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
+ // if (s.equals(BigInteger.ZERO)) {
+ // continue;
+ // }
+ // break;
+ // }
+ final BigInteger[] rs = computeRS(md.digest());
+
+ // return encodeSignature(r, s);
+ return encodeSignature(rs[0], rs[1]);
+ }
+
+ protected boolean verifySignature(Object sig) throws IllegalStateException
+ {
+ final BigInteger[] rs = decodeSignature(sig);
+ // BigInteger r = rs[0];
+ // BigInteger s = rs[1];
+ //
+ // BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
+ // BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
+ // BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
+ // BigInteger y = ((DSAPublicKey) publicKey).getY();
+ // BigInteger w = s.modInverse(q);
+ //
+ // byte bytes[] = md.digest();
+ // BigInteger u1 = w.multiply(new BigInteger(1, bytes)).mod(q);
+ // BigInteger u2 = r.multiply(w).mod(q);
+ //
+ // BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
+ // return v.equals(r);
+ return checkRS(rs, md.digest());
+ }
+
+ // Other instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Returns the output of a signature generation phase.<p>
+ *
+ * @return an object encapsulating the DSS signature pair <code>r</code> and
+ * <code>s</code>.
+ */
+ private Object encodeSignature(BigInteger r, BigInteger s)
+ {
+ return new BigInteger[] { r, s };
+ }
+
+ /**
+ * Returns the output of a previously generated signature object as a pair
+ * of {@link java.math.BigInteger}.<p>
+ *
+ * @return the DSS signature pair <code>r</code> and <code>s</code>.
+ */
+ private BigInteger[] decodeSignature(Object signature)
+ {
+ return (BigInteger[]) signature;
+ }
+
+ private BigInteger[] computeRS(final byte[] digestBytes)
+ {
+ final BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP();
+ final BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ();
+ final BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG();
+ final BigInteger x = ((DSAPrivateKey) privateKey).getX();
+ final BigInteger m = new BigInteger(1, digestBytes);
+ BigInteger k, r, s;
+
+ final byte[] kb = new byte[20]; // we'll use 159 bits only
+ while (true)
+ {
+ this.nextRandomBytes(kb);
+ k = new BigInteger(1, kb);
+ k.clearBit(159);
+ r = g.modPow(k, p).mod(q);
+ if (r.equals(BigInteger.ZERO))
+ {
+ continue;
+ }
+ s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
+ if (s.equals(BigInteger.ZERO))
+ {
+ continue;
+ }
+ break;
+ }
+
+ return new BigInteger[] { r, s };
+ }
+
+ private boolean checkRS(final BigInteger[] rs, final byte[] digestBytes)
+ {
+ final BigInteger r = rs[0];
+ final BigInteger s = rs[1];
+
+ final BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
+ final BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
+ final BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
+ final BigInteger y = ((DSAPublicKey) publicKey).getY();
+ final BigInteger w = s.modInverse(q);
+
+ final BigInteger u1 = w.multiply(new BigInteger(1, digestBytes)).mod(q);
+ final BigInteger u2 = r.multiply(w).mod(q);
+
+ final BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
+ return v.equals(r);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/dss/DSSSignatureRawCodec.java b/libjava/classpath/gnu/java/security/sig/dss/DSSSignatureRawCodec.java
new file mode 100644
index 00000000000..02f6b1ddc41
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/dss/DSSSignatureRawCodec.java
@@ -0,0 +1,191 @@
+/* DSSSignatureRawCodec.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.ISignatureCodec;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+
+/**
+ * <p>An object that implements the {@link ISignatureCodec} operations for the
+ * <i>Raw</i> format to use with DSS signatures.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class DSSSignatureRawCodec implements ISignatureCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.sig.ISignatureCodec interface implementation -----------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated DSS (Digital Signature
+ * Standard) signature object according to the <i>Raw</i> format supported by
+ * this library.</p>
+ *
+ * <p>The <i>Raw</i> format for a DSA signature, in this implementation, is a
+ * byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_DSS_SIGNATURE},</li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the DSS parameter
+ * <code>r</code> in internet order,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSS parameter <code>r</code>,</li>
+ * <li>4-byte count of following bytes representing the DSS parameter
+ * <code>s</code>,</li>
+ * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
+ * the <code>toByteArray()</code> method on the DSS parameter <code>s</code>.</li>
+ * </ol>
+ *
+ * @param signature the signature to encode, consisting of the two DSS
+ * parameters <code>r</code> and <code>s</code> as a {@link java.math.BigInteger}
+ * array.
+ * @return the <i>Raw</i> format encoding of the designated signature.
+ * @exception IllegalArgumentException if the designated signature is not a
+ * DSS (Digital Signature Standard) one.
+ */
+ public byte[] encodeSignature(Object signature)
+ {
+ BigInteger r, s;
+ try
+ {
+ BigInteger[] sig = (BigInteger[]) signature;
+ r = sig[0];
+ s = sig[1];
+ }
+ catch (Exception x)
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[0]);
+ baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[1]);
+ baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[2]);
+ baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[3]);
+
+ // version
+ baos.write(0x01);
+
+ // r
+ byte[] buffer = r.toByteArray();
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ // s
+ buffer = s.toByteArray();
+ length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public Object decodeSignature(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_DSS_SIGNATURE[0]
+ || k[1] != Registry.MAGIC_RAW_DSS_SIGNATURE[1]
+ || k[2] != Registry.MAGIC_RAW_DSS_SIGNATURE[2]
+ || k[3] != Registry.MAGIC_RAW_DSS_SIGNATURE[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+
+ int i = 5;
+ int l;
+ byte[] buffer;
+
+ // r
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger r = new BigInteger(1, buffer);
+
+ // s
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ buffer = new byte[l];
+ System.arraycopy(k, i, buffer, 0, l);
+ i += l;
+ BigInteger s = new BigInteger(1, buffer);
+
+ return new BigInteger[] { r, s };
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/dss/DSSSignatureX509Codec.java b/libjava/classpath/gnu/java/security/sig/dss/DSSSignatureX509Codec.java
new file mode 100644
index 00000000000..0fdb754a982
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/dss/DSSSignatureX509Codec.java
@@ -0,0 +1,193 @@
+/* DSSSignatureX509Codec.java -- X.509 encoder/decoder for DSS signatures
+ 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.java.security.sig.dss;
+
+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.sig.ISignatureCodec;
+import gnu.java.security.util.DerUtil;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidParameterException;
+import java.util.ArrayList;
+
+/**
+ * An implementation of an {@link ISignatureCodec} that knows to encode and
+ * decode DSS signatures into the raw bytes which would constitute a DER-encoded
+ * form of the ASN.1 structure defined in RFC-2459, and RFC-2313 as described in
+ * the next paragraphs.
+ * <p>
+ * Digital signatures when transmitted in an X.509 certificates are encoded
+ * in DER (Distinguished Encoding Rules) as a BIT STRING; i.e.
+ *
+ * <pre>
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ * </pre>
+ * <p>
+ * The output of the encoder, and the input of the decoder, of this codec are
+ * then the <i>raw</i> bytes of such a BIT STRING; i.e. not the DER-encoded
+ * form itself.
+ * <p>
+ * RFC-2459 states that, for the Digital Signature Standard (DSS), which
+ * generates two MPIs, commonly called <code>r</code> and <code>s</code>, as the
+ * result of digitally signing a message, these two numbers will be transferred
+ * as the following ASN.1 structure:
+ *
+ * <pre>
+ * Dss-Sig-Value ::= SEQUENCE {
+ * r INTEGER,
+ * s INTEGER
+ * }
+ * </pre>
+ * <p>
+ * Client code that needs to build a DER BIT STRING <b>MUST</b> construct such
+ * an ASN.1 value. The following is an example of how to do this:
+ * <p>
+ * <pre>
+ * ...
+ * import gnu.java.security.der.BitString;
+ * import gnu.java.security.der.DER;
+ * import gnu.java.security.der.DERValue;
+ * ...
+ * DERValue bitString = new DERValue(DER.BIT_STRING, new BitString(sigBytes));
+ * ...
+ * </pre>
+ */
+public class DSSSignatureX509Codec
+ implements ISignatureCodec
+{
+ // implicit 0-arguments constructor
+
+ public int getFormatID()
+ {
+ return Registry.X509_ENCODING_ID;
+ }
+
+ /**
+ * Encodes a DSS Signature output as the <i>signature</i> raw bytes which can
+ * be used to construct an ASN.1 DER-encoded BIT STRING as defined in the
+ * documentation of this class.
+ *
+ * @param signature the output of the DSS signature algorithm; i.e. the value
+ * returned by the invocation of
+ * {@link gnu.java.security.sig.ISignature#sign()} method. In the
+ * case of a DSS signature this is an array of two MPIs called
+ * <code>r</code> and <code>s</code>.
+ * @return the raw bytes of a DSS signature which could be then used as the
+ * contents of a BIT STRING as per rfc-2459.
+ * @throws InvalidParameterException if an exception occurs during the
+ * marshalling process.
+ */
+ public byte[] encodeSignature(Object signature)
+ {
+ BigInteger[] rs = (BigInteger[]) signature;
+
+ DERValue derR = new DERValue(DER.INTEGER, rs[0]);
+ DERValue derS = new DERValue(DER.INTEGER, rs[1]);
+
+ ArrayList dssSigValue = new ArrayList(2);
+ dssSigValue.add(derR);
+ dssSigValue.add(derS);
+ DERValue derDssSigValue = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ dssSigValue);
+ byte[] result;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try
+ {
+ DERWriter.write(baos, derDssSigValue);
+ result = baos.toByteArray();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ return result;
+ }
+
+ /**
+ * Decodes a <i>signature</i> as defined in the documentation of this class.
+ *
+ * @param input the byte array to unmarshall into a valid DSS signature
+ * instance; i.e. an array of two MPIs. MUST NOT be null.
+ * @return an array of two MPIs, <code>r</code> and <code>s</code> in this
+ * order, decoded from the designated <code>input</code>.
+ * @throw InvalidParameterException if an exception occurs during the
+ * unmarshalling process.
+ */
+ public Object decodeSignature(byte[] input)
+ {
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ BigInteger r, s;
+ DERReader der = new DERReader(input);
+ try
+ {
+ DERValue derDssSigValue = der.read();
+ DerUtil.checkIsConstructed(derDssSigValue, "Wrong Dss-Sig-Value field");
+
+ DERValue val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong R field");
+ r = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong S field");
+ s = (BigInteger) val.getValue();
+ }
+ catch (IOException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+
+ return new BigInteger[] { r, s };
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java b/libjava/classpath/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java
new file mode 100644
index 00000000000..efe580d5167
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java
@@ -0,0 +1,306 @@
+/* EME_PKCS1_V1_5.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.PRNG;
+
+import java.io.ByteArrayOutputStream;
+import java.security.interfaces.RSAKey;
+import java.util.Random;
+
+/**
+ * <p>An implementation of the EME-PKCS1-V1.5 encoding and decoding methods.</p>
+ *
+ * <p>EME-PKCS1-V1.5 is parameterised by the entity <code>k</code> which is the
+ * byte count of an RSA public shared modulus.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ */
+public class EME_PKCS1_V1_5
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private int k;
+
+ private ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ /** Our default source of randomness. */
+ private PRNG prng = PRNG.getInstance();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ private EME_PKCS1_V1_5(final int k)
+ {
+ super();
+
+ this.k = k;
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ public static final EME_PKCS1_V1_5 getInstance(final int k)
+ {
+ if (k < 0)
+ {
+ throw new IllegalArgumentException("k must be a positive integer");
+ }
+ return new EME_PKCS1_V1_5(k);
+ }
+
+ public static final EME_PKCS1_V1_5 getInstance(final RSAKey key)
+ {
+ final int modBits = key.getModulus().bitLength();
+ final int k = (modBits + 7) / 8;
+ return EME_PKCS1_V1_5.getInstance(k);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Generates an octet string <code>PS</code> of length <code>k - mLen -
+ * 3</code> consisting of pseudo-randomly generated nonzero octets. The
+ * length of <code>PS</code> will be at least eight octets.</p>
+ *
+ * <p>The method then concatenates <code>PS</code>, the message <code>M</code>,
+ * and other padding to form an encoded message <code>EM</code> of length
+ * <code>k</code> octets as:</p>
+ *
+ * <pre>
+ * EM = 0x00 || 0x02 || PS || 0x00 || M.
+ * </pre>
+ *
+ * <p>This method uses a default PRNG to obtain the padding bytes.</p>
+ *
+ * @param M the message to encode.
+ * @return the encoded message <code>EM</code>.
+ */
+ public byte[] encode(final byte[] M)
+ {
+ // a. Generate an octet string PS of length k - mLen - 3 consisting
+ // of pseudo-randomly generated nonzero octets. The length of PS
+ // will be at least eight octets.
+ final byte[] PS = new byte[k - M.length - 3];
+
+ // FIXME. This should be configurable, somehow.
+ prng.nextBytes(PS);
+ int i = 0;
+ for (; i < PS.length; i++)
+ {
+ if (PS[i] == 0)
+ PS[i] = 1;
+ }
+ // b. Concatenate PS, the message M, and other padding to form an
+ // encoded message EM of length k octets as
+ //
+ // EM = 0x00 || 0x02 || PS || 0x00 || M.
+ return assembleEM(PS, M);
+ }
+
+ /**
+ * <p>Similar to {@link #encode(byte[])} method, except that the source of
+ * randomness to use for obtaining the padding bytes (an instance of
+ * {@link IRandom}) is given as a parameter.</p>
+ *
+ * @param M the message to encode.
+ * @param irnd the {@link IRandom} instance to use as a source of randomness.
+ * @return the encoded message <code>EM</code>.
+ */
+ public byte[] encode(final byte[] M, final IRandom irnd)
+ {
+ final byte[] PS = new byte[k - M.length - 3];
+ try
+ {
+ irnd.nextBytes(PS, 0, PS.length);
+ int i = 0;
+ outer: while (true)
+ {
+ for (; i < PS.length; i++)
+ {
+ if (PS[i] == 0x00)
+ {
+ System.arraycopy(PS, i + 1, PS, i, PS.length - i - 1);
+ irnd.nextBytes(PS, PS.length - 1, 1);
+ continue outer;
+ }
+ }
+ break;
+ }
+ }
+ catch (IllegalStateException x)
+ {
+ throw new RuntimeException("encode(): " + String.valueOf(x));
+ }
+ catch (LimitReachedException x)
+ {
+ throw new RuntimeException("encode(): " + String.valueOf(x));
+ }
+
+ return assembleEM(PS, M);
+ }
+
+ /**
+ * <p>Similar to the {@link #encode(byte[], IRandom)} method, except that
+ * the source of randmoness is an instance of {@link Random}.
+ *
+ * @param M the message to encode.
+ * @param rnd the {@link Random} instance to use as a source of randomness.
+ * @return the encoded message <code>EM</code>.
+ */
+ public byte[] encode(final byte[] M, final Random rnd)
+ {
+ final byte[] PS = new byte[k - M.length - 3];
+ rnd.nextBytes(PS);
+ int i = 0;
+ outer: while (true)
+ {
+ for (; i < PS.length; i++)
+ {
+ if (PS[i] == 0x00)
+ {
+ System.arraycopy(PS, i + 1, PS, i, PS.length - i - 1);
+ PS[PS.length - 1] = (byte) rnd.nextInt();
+ continue outer;
+ }
+ }
+ break;
+ }
+
+ return assembleEM(PS, M);
+ }
+
+ /**
+ * <p>Separate the encoded message <code>EM</code> into an octet string
+ * <code>PS</code> consisting of nonzero octets and a message <code>M</code>
+ * as:</p>
+ *
+ * <pre>
+ * EM = 0x00 || 0x02 || PS || 0x00 || M.
+ * </pre>
+ *
+ * <p>If the first octet of <code>EM</code> does not have hexadecimal value
+ * <code>0x00</code>, if the second octet of <code>EM</code> does not have
+ * hexadecimal value <code>0x02</code>, if there is no octet with hexadecimal
+ * value <code>0x00</code> to separate <code>PS</code> from <code>M</code>,
+ * or if the length of <code>PS</code> is less than <code>8</code> octets,
+ * output "decryption error" and stop.</p>
+
+ * @param EM the designated encoded message.
+ * @return the decoded message <code>M</code> framed in the designated
+ * <code>EM</code> value.
+ * @throws IllegalArgumentException if the length of the designated entity
+ * <code>EM</code> is different than <code>k</code> (the length in bytes of
+ * the public shared modulus), or if any of the conditions described above
+ * is detected.
+ */
+ public byte[] decode(final byte[] EM)
+ {
+ // Separate the encoded message EM into an
+ // octet string PS consisting of nonzero octets and a message M as
+ //
+ // EM = 0x00 || 0x02 || PS || 0x00 || M.
+ //
+ // If the first octet of EM does not have hexadecimal value 0x00, if
+ // the second octet of EM does not have hexadecimal value 0x02, if
+ // there is no octet with hexadecimal value 0x00 to separate PS from
+ // M, or if the length of PS is less than 8 octets, output
+ // "decryption error" and stop. (See the note below.)
+ final int emLen = EM.length;
+ if (emLen != k)
+ {
+ throw new IllegalArgumentException("decryption error");
+ }
+ if (EM[0] != 0x00)
+ {
+ throw new IllegalArgumentException("decryption error");
+ }
+ if (EM[1] != 0x02)
+ {
+ throw new IllegalArgumentException("decryption error");
+ }
+ int i = 2;
+ for (; i < emLen; i++)
+ {
+ if (EM[i] == 0x00)
+ {
+ break;
+ }
+ }
+ if (i >= emLen || i < 11)
+ {
+ throw new IllegalArgumentException("decryption error");
+ }
+ i++;
+ final byte[] result = new byte[emLen - i];
+ System.arraycopy(EM, i, result, 0, result.length);
+ return result;
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ private byte[] assembleEM(final byte[] PS, final byte[] M)
+ {
+ // b. Concatenate PS, the message M, and other padding to form an
+ // encoded message EM of length k octets as
+ //
+ // EM = 0x00 || 0x02 || PS || 0x00 || M.
+ baos.reset();
+ baos.write(0x00);
+ baos.write(0x02);
+ baos.write(PS, 0, PS.length);
+ baos.write(0x00);
+ baos.write(M, 0, M.length);
+ final byte[] result = baos.toByteArray();
+ baos.reset();
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java b/libjava/classpath/gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java
new file mode 100644
index 00000000000..2ea8a304a9c
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/EMSA_PKCS1_V1_5.java
@@ -0,0 +1,299 @@
+/* EMSA_PKCS1_V1_5.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * <p>An implementation of the EMSA-PKCS1-V1.5 encoding scheme.</p>
+ *
+ * <p>EMSA-PKCS1-V1.5 is parameterised by the choice of hash function Hash and
+ * hLen which denotes the length in octets of the hash function output.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.2 $
+ */
+public class EMSA_PKCS1_V1_5 implements Cloneable
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /* Notes.
+ 1. For the six hash functions mentioned in Appendix B.1, the DER encoding
+ T of the DigestInfo value is equal to the following:
+
+ MD2: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10 || H
+ MD5: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H
+ SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H
+ SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H
+ SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H
+ SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H
+ */
+ private static final byte[] MD2_PREFIX = { (byte) 0x30, (byte) 0x20,
+ (byte) 0x30, (byte) 0x0c,
+ (byte) 0x06, (byte) 0x08,
+ (byte) 0x2a, (byte) 0x86,
+ (byte) 0x48, (byte) 0x86,
+ (byte) 0xf7, (byte) 0x0d,
+ (byte) 0x02, (byte) 0x02,
+ (byte) 0x05, (byte) 0x00,
+ (byte) 0x04, (byte) 0x10 };
+
+ private static final byte[] MD5_PREFIX = { (byte) 0x30, (byte) 0x20,
+ (byte) 0x30, (byte) 0x0c,
+ (byte) 0x06, (byte) 0x08,
+ (byte) 0x2a, (byte) 0x86,
+ (byte) 0x48, (byte) 0x86,
+ (byte) 0xf7, (byte) 0x0d,
+ (byte) 0x02, (byte) 0x05,
+ (byte) 0x05, (byte) 0x00,
+ (byte) 0x04, (byte) 0x10 };
+
+ private static final byte[] SHA160_PREFIX = { (byte) 0x30, (byte) 0x21,
+ (byte) 0x30, (byte) 0x09,
+ (byte) 0x06, (byte) 0x05,
+ (byte) 0x2b, (byte) 0x0e,
+ (byte) 0x03, (byte) 0x02,
+ (byte) 0x1a, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04,
+ (byte) 0x14 };
+
+ private static final byte[] SHA256_PREFIX = { (byte) 0x30, (byte) 0x31,
+ (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09,
+ (byte) 0x60, (byte) 0x86,
+ (byte) 0x48, (byte) 0x01,
+ (byte) 0x65, (byte) 0x03,
+ (byte) 0x04, (byte) 0x02,
+ (byte) 0x01, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04,
+ (byte) 0x20 };
+
+ private static final byte[] SHA384_PREFIX = { (byte) 0x30, (byte) 0x41,
+ (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09,
+ (byte) 0x60, (byte) 0x86,
+ (byte) 0x48, (byte) 0x01,
+ (byte) 0x65, (byte) 0x03,
+ (byte) 0x04, (byte) 0x02,
+ (byte) 0x02, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04,
+ (byte) 0x30 };
+
+ private static final byte[] SHA512_PREFIX = { (byte) 0x30, (byte) 0x51,
+ (byte) 0x30, (byte) 0x0d,
+ (byte) 0x06, (byte) 0x09,
+ (byte) 0x60, (byte) 0x86,
+ (byte) 0x48, (byte) 0x01,
+ (byte) 0x65, (byte) 0x03,
+ (byte) 0x04, (byte) 0x02,
+ (byte) 0x03, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04,
+ (byte) 0x40 };
+
+ /** The underlying hash function to use with this instance. */
+ private IMessageDigest hash;
+
+ /** The output size of the hash function in octets. */
+ private int hLen; // TODO: field not used!!! investigate
+
+ /** The DER part of DigestInfo not containing the hash value itself. */
+ private byte[] prefix;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial private constructor to enforce use through Factory method.</p>
+ *
+ * @param hash the message digest instance to use with this scheme instance.
+ */
+ private EMSA_PKCS1_V1_5(final IMessageDigest hash)
+ {
+ super();
+
+ this.hash = hash;
+ hLen = hash.hashSize();
+ final String name = hash.name();
+ if (name.equals(Registry.MD2_HASH))
+ {
+ prefix = MD2_PREFIX;
+ }
+ else if (name.equals(Registry.MD5_HASH))
+ {
+ prefix = MD5_PREFIX;
+ }
+ else if (name.equals(Registry.SHA160_HASH))
+ {
+ prefix = SHA160_PREFIX;
+ }
+ else if (name.equals(Registry.SHA256_HASH))
+ {
+ prefix = SHA256_PREFIX;
+ }
+ else if (name.equals(Registry.SHA384_HASH))
+ {
+ prefix = SHA384_PREFIX;
+ }
+ else if (name.equals(Registry.SHA512_HASH))
+ {
+ prefix = SHA512_PREFIX;
+ }
+ else
+ {
+ throw new UnsupportedOperationException(); // should not happen
+ }
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of this object given a designated name of a hash
+ * function.</p>
+ *
+ * @param mdName the canonical name of a hash function.
+ * @return an instance of this object configured for use with the designated
+ * options.
+ * @throws UnsupportedOperationException if the hash function is not
+ * implemented or does not have an ID listed in RFC-3447.
+ */
+ public static final EMSA_PKCS1_V1_5 getInstance(final String mdName)
+ {
+ final IMessageDigest hash = HashFactory.getInstance(mdName);
+ final String name = hash.name();
+ if (!(name.equals(Registry.MD2_HASH) || name.equals(Registry.MD5_HASH)
+ || name.equals(Registry.SHA160_HASH)
+ || name.equals(Registry.SHA256_HASH)
+ || name.equals(Registry.SHA384_HASH) || name.equals(Registry.SHA512_HASH)))
+ {
+ throw new UnsupportedOperationException("hash with no OID: " + name);
+ }
+ return new EMSA_PKCS1_V1_5(hash);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Cloneable interface implementation --------------------------------------
+
+ public Object clone()
+ {
+ return getInstance(hash.name());
+ }
+
+ // own methods -------------------------------------------------------------
+
+ /**
+ * <p>Frames the hash of a message, along with an ID of the hash function in
+ * a DER sequence according to the specifications of EMSA-PKCS1-V1.5 as
+ * described in RFC-3447 (see class documentation).</p>
+ *
+ * @param mHash the byte sequence resulting from applying the message digest
+ * algorithm Hash to the message <i>M</i>.
+ * @param emLen intended length in octets of the encoded message, at least
+ * <code>tLen + 11</code>, where <code>tLen</code> is the octet length of the
+ * DER encoding <code>T</code> of a certain value computed during the
+ * encoding operation.
+ * @return encoded message, an octet string of length <code>emLen</code>.
+ * @throws IllegalArgumentException if the message is too long, or if the
+ * intended encoded message length is too short.
+ */
+ public byte[] encode(final byte[] mHash, final int emLen)
+ {
+ // 1. Apply the hash function to the message M to produce a hash value
+ // H: H = Hash(M).
+ // If the hash function outputs "message too long," output "message
+ // too long" and stop.
+ // 2. Encode the algorithm ID for the hash function and the hash value
+ // into an ASN.1 value of type DigestInfo (see Appendix A.2.4) with
+ // the Distinguished Encoding Rules (DER), where the type DigestInfo
+ // has the syntax
+ // DigestInfo ::= SEQUENCE {
+ // digestAlgorithm AlgorithmIdentifier,
+ // digest OCTET STRING
+ // }
+ // The first field identifies the hash function and the second contains
+ // the hash value. Let T be the DER encoding of the DigestInfo value
+ // (see the notes below) and let tLen be the length in octets of T.
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ baos.write(prefix, 0, prefix.length);
+ baos.write(mHash, 0, mHash.length);
+ final byte[] T = baos.toByteArray();
+ final int tLen = T.length;
+ // 3. If emLen < tLen + 11, output "intended encoded message length too
+ // short" and stop.
+ if (emLen < tLen + 11)
+ {
+ throw new IllegalArgumentException("emLen too short");
+ }
+ // 4. Generate an octet string PS consisting of emLen - tLen - 3 octets
+ // with hexadecimal value 0xff. The length of PS will be at least 8
+ // octets.
+ final byte[] PS = new byte[emLen - tLen - 3];
+ for (int i = 0; i < PS.length; i++)
+ {
+ PS[i] = (byte) 0xFF;
+ }
+ // 5. Concatenate PS, the DER encoding T, and other padding to form the
+ // encoded message EM as: EM = 0x00 || 0x01 || PS || 0x00 || T.
+ baos.reset();
+ baos.write(0x00);
+ baos.write(0x01);
+ baos.write(PS, 0, PS.length);
+ baos.write(0x00);
+ baos.write(T, 0, tLen);
+ final byte[] result = baos.toByteArray();
+ baos.reset();
+ // 6. Output EM.
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/EMSA_PSS.java b/libjava/classpath/gnu/java/security/sig/rsa/EMSA_PSS.java
new file mode 100644
index 00000000000..d11a861b52e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/EMSA_PSS.java
@@ -0,0 +1,432 @@
+/* EMSA_PSS.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.util.Util;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * <p>An implementation of the EMSA-PSS encoding/decoding scheme.</p>
+ *
+ * <p>EMSA-PSS coincides with EMSA4 in IEEE P1363a D5 except that EMSA-PSS acts
+ * on octet strings and not on bit strings. In particular, the bit lengths of
+ * the hash and the salt must be multiples of 8 in EMSA-PSS. Moreover, EMSA4
+ * outputs an integer of a desired bit length rather than an octet string.</p>
+ *
+ * <p>EMSA-PSS is parameterized by the choice of hash function Hash and mask
+ * generation function MGF. In this submission, MGF is based on a Hash
+ * definition that coincides with the corresponding definitions in IEEE Std
+ * 1363-2000, PKCS #1 v2.0, and the draft ANSI X9.44. In PKCS #1 v2.0 and the
+ * draft ANSI X9.44, the recommended hash function is SHA-1, while IEEE Std
+ * 1363-2000 recommends SHA-1 and RIPEMD-160.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class EMSA_PSS implements Cloneable
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "emsa-pss";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The underlying hash function to use with this instance. */
+ private IMessageDigest hash;
+
+ /** The output size of the hash function in octets. */
+ private int hLen;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trivial private constructor to enforce use through Factory method.</p>
+ *
+ * @param hash the message digest instance to use with this scheme instance.
+ */
+ private EMSA_PSS(IMessageDigest hash)
+ {
+ super();
+
+ this.hash = hash;
+ hLen = hash.hashSize();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns an instance of this object given a designated name of a hash
+ * function.</p>
+ *
+ * @param mdName the canonical name of a hash function.
+ * @return an instance of this object configured for use with the designated
+ * options.
+ */
+ public static EMSA_PSS getInstance(String mdName)
+ {
+ IMessageDigest hash = HashFactory.getInstance(mdName);
+ return new EMSA_PSS(hash);
+ }
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Cloneable interface implementation --------------------------------------
+
+ public Object clone()
+ {
+ return getInstance(hash.name());
+ }
+
+ // own methods -------------------------------------------------------------
+
+ /**
+ * <p>The encoding operation EMSA-PSS-Encode computes the hash of a message
+ * <code>M</code> using a hash function and maps the result to an encoded
+ * message <code>EM</code> of a specified length using a mask generation
+ * function.</p>
+ *
+ * @param mHash the byte sequence resulting from applying the message digest
+ * algorithm Hash to the message <i>M</i>.
+ * @param emBits the maximal bit length of the integer OS2IP(EM), at least
+ * <code>8.hLen + 8.sLen + 9</code>.
+ * @param salt the salt to use when encoding the output.
+ * @return the encoded message <code>EM</code>, an octet string of length
+ * <code>emLen = CEILING(emBits / 8)</code>.
+ * @exception IllegalArgumentException if an exception occurs.
+ *
+ */
+ public byte[] encode(byte[] mHash, int emBits, byte[] salt)
+ {
+ int sLen = salt.length;
+
+ // 1. If the length of M is greater than the input limitation for the hash
+ // function (2**61 - 1 octets for SHA-1) then output "message too long"
+ // and stop.
+ // 2. Let mHash = Hash(M), an octet string of length hLen.
+ if (hLen != mHash.length)
+ {
+ throw new IllegalArgumentException("wrong hash");
+ }
+ // 3. If emBits < 8.hLen + 8.sLen + 9, output 'encoding error' and stop.
+ if (emBits < (8 * hLen + 8 * sLen + 9))
+ {
+ throw new IllegalArgumentException("encoding error");
+ }
+ int emLen = (emBits + 7) / 8;
+ // 4. Generate a random octet string salt of length sLen; if sLen = 0,
+ // then salt is the empty string.
+ // ...passed as argument to accomodate JCE
+ // 5. Let M0 = 00 00 00 00 00 00 00 00 || mHash || salt;
+ // M0 is an octet string of length 8 + hLen + sLen with eight initial zero
+ // octets.
+ // 6. Let H = Hash(M0), an octet string of length hLen.
+ byte[] H;
+ int i;
+ synchronized (hash)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ hash.update((byte) 0x00);
+ }
+ hash.update(mHash, 0, hLen);
+ hash.update(salt, 0, sLen);
+ H = hash.digest();
+ }
+ // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2
+ // zero octets. The length of PS may be 0.
+ // 8. Let DB = PS || 01 || salt.
+ byte[] DB = new byte[emLen - sLen - hLen - 2 + 1 + sLen];
+ DB[emLen - sLen - hLen - 2] = 0x01;
+ System.arraycopy(salt, 0, DB, emLen - sLen - hLen - 1, sLen);
+ // 9. Let dbMask = MGF(H, emLen - hLen - 1).
+ byte[] dbMask = MGF(H, emLen - hLen - 1);
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("dbMask (encode): " + Util.toString(dbMask));
+ debug("DB (encode): " + Util.toString(DB));
+ }
+ // 10. Let maskedDB = DB XOR dbMask.
+ for (i = 0; i < DB.length; i++)
+ {
+ DB[i] = (byte) (DB[i] ^ dbMask[i]);
+ }
+ // 11. Set the leftmost 8emLen - emBits bits of the leftmost octet in
+ // maskedDB to zero.
+ DB[0] &= (0xFF >>> (8 * emLen - emBits));
+ // 12. Let EM = maskedDB || H || bc, where bc is the single octet with
+ // hexadecimal value 0xBC.
+ byte[] result = new byte[emLen];
+ System.arraycopy(DB, 0, result, 0, emLen - hLen - 1);
+ System.arraycopy(H, 0, result, emLen - hLen - 1, hLen);
+ result[emLen - 1] = (byte) 0xBC;
+ // 13. Output EM.
+ return result;
+ }
+
+ /**
+ * <p>The decoding operation EMSA-PSS-Decode recovers the message hash from
+ * an encoded message <code>EM</code> and compares it to the hash of
+ * <code>M</code>.</p>
+ *
+ * @param mHash the byte sequence resulting from applying the message digest
+ * algorithm Hash to the message <i>M</i>.
+ * @param EM the <i>encoded message</i>, an octet string of length
+ * <code>emLen = CEILING(emBits/8).
+ * @param emBits the maximal bit length of the integer OS2IP(EM), at least
+ * <code>8.hLen + 8.sLen + 9</code>.
+ * @param sLen the length, in octets, of the expected salt.
+ * @return <code>true</code> if the result of the verification was
+ * <i>consistent</i> with the expected reseult; and <code>false</code> if the
+ * result was <i>inconsistent</i>.
+ * @exception IllegalArgumentException if an exception occurs.
+ */
+ public boolean decode(byte[] mHash, byte[] EM, int emBits, int sLen)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("mHash: " + Util.toString(mHash));
+ debug("EM: " + Util.toString(EM));
+ debug("emBits: " + String.valueOf(emBits));
+ debug("sLen: " + String.valueOf(sLen));
+ }
+ if (sLen < 0)
+ {
+ throw new IllegalArgumentException("sLen");
+ }
+
+ // 1. If the length of M is greater than the input limitation for the hash
+ // function (2**61 ? 1 octets for SHA-1) then output 'inconsistent' and
+ // stop.
+ // 2. Let mHash = Hash(M), an octet string of length hLen.
+ if (hLen != mHash.length)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("hLen != mHash.length; hLen: " + String.valueOf(hLen));
+ }
+ throw new IllegalArgumentException("wrong hash");
+ }
+ // 3. If emBits < 8.hLen + 8.sLen + 9, output 'decoding error' and stop.
+ if (emBits < (8 * hLen + 8 * sLen + 9))
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("emBits < (8hLen + 8sLen + 9); sLen: " + String.valueOf(sLen));
+ }
+ throw new IllegalArgumentException("decoding error");
+ }
+ int emLen = (emBits + 7) / 8;
+ // 4. If the rightmost octet of EM does not have hexadecimal value bc,
+ // output 'inconsistent' and stop.
+ if ((EM[EM.length - 1] & 0xFF) != 0xBC)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("EM does not end with 0xBC");
+ }
+ return false;
+ }
+ // 5. Let maskedDB be the leftmost emLen ? hLen ? 1 octets of EM, and let
+ // H be the next hLen octets.
+ // 6. If the leftmost 8.emLen ? emBits bits of the leftmost octet in
+ // maskedDB are not all equal to zero, output 'inconsistent' and stop.
+ if ((EM[0] & (0xFF << (8 - (8 * emLen - emBits)))) != 0)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("Leftmost 8emLen - emBits bits of EM are not 0s");
+ }
+ return false;
+ }
+ byte[] DB = new byte[emLen - hLen - 1];
+ byte[] H = new byte[hLen];
+ System.arraycopy(EM, 0, DB, 0, emLen - hLen - 1);
+ System.arraycopy(EM, emLen - hLen - 1, H, 0, hLen);
+ // 7. Let dbMask = MGF(H, emLen ? hLen ? 1).
+ byte[] dbMask = MGF(H, emLen - hLen - 1);
+ // 8. Let DB = maskedDB XOR dbMask.
+ int i;
+ for (i = 0; i < DB.length; i++)
+ {
+ DB[i] = (byte) (DB[i] ^ dbMask[i]);
+ }
+ // 9. Set the leftmost 8.emLen ? emBits bits of DB to zero.
+ DB[0] &= (0xFF >>> (8 * emLen - emBits));
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("dbMask (decode): " + Util.toString(dbMask));
+ debug("DB (decode): " + Util.toString(DB));
+ }
+ // 10. If the emLen -hLen -sLen -2 leftmost octets of DB are not zero or
+ // if the octet at position emLen -hLen -sLen -1 is not equal to 0x01,
+ // output 'inconsistent' and stop.
+ // IMPORTANT (rsn): this is an error in the specs, the index of the 0x01
+ // byte should be emLen -hLen -sLen -2 and not -1! authors have been
+ // advised
+ for (i = 0; i < (emLen - hLen - sLen - 2); i++)
+ {
+ if (DB[i] != 0)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("DB[" + String.valueOf(i) + "] != 0x00");
+ }
+ return false;
+ }
+ }
+ if (DB[i] != 0x01)
+ { // i == emLen -hLen -sLen -2
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("DB's byte at position (emLen -hLen -sLen -2); i.e. "
+ + String.valueOf(i) + " is not 0x01");
+ }
+ return false;
+ }
+ // 11. Let salt be the last sLen octets of DB.
+ byte[] salt = new byte[sLen];
+ System.arraycopy(DB, DB.length - sLen, salt, 0, sLen);
+ // 12. Let M0 = 00 00 00 00 00 00 00 00 || mHash || salt;
+ // M0 is an octet string of length 8 + hLen + sLen with eight initial
+ // zero octets.
+ // 13. Let H0 = Hash(M0), an octet string of length hLen.
+ byte[] H0;
+ synchronized (hash)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ hash.update((byte) 0x00);
+ }
+ hash.update(mHash, 0, hLen);
+ hash.update(salt, 0, sLen);
+ H0 = hash.digest();
+ }
+ // 14. If H = H0, output 'consistent.' Otherwise, output 'inconsistent.'
+ return Arrays.equals(H, H0);
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ /**
+ * <p>A mask generation function takes an octet string of variable length
+ * and a desired output length as input, and outputs an octet string of the
+ * desired length. There may be restrictions on the length of the input and
+ * output octet strings, but such bounds are generally very large. Mask
+ * generation functions are deterministic; the octet string output is
+ * completely determined by the input octet string. The output of a mask
+ * generation function should be pseudorandom, that is, it should be
+ * infeasible to predict, given one part of the output but not the input,
+ * another part of the output. The provable security of RSA-PSS relies on
+ * the random nature of the output of the mask generation function, which in
+ * turn relies on the random nature of the underlying hash function.</p>
+ *
+ * @param Z a seed.
+ * @param l the desired output length in octets.
+ * @return the mask.
+ * @exception IllegalArgumentException if the desired output length is too
+ * long.
+ */
+ private byte[] MGF(byte[] Z, int l)
+ {
+ // 1. If l > (2**32).hLen, output 'mask too long' and stop.
+ if (l < 1 || (l & 0xFFFFFFFFL) > ((hLen & 0xFFFFFFFFL) << 32L))
+ {
+ throw new IllegalArgumentException("mask too long");
+ }
+ // 2. Let T be the empty octet string.
+ byte[] result = new byte[l];
+ // 3. For i = 0 to CEILING(l/hLen) ? 1, do
+ int limit = ((l + hLen - 1) / hLen) - 1;
+ IMessageDigest hashZ = null;
+ hashZ = (IMessageDigest) hash.clone();
+ hashZ.digest();
+ hashZ.update(Z, 0, Z.length);
+ IMessageDigest hashZC = null;
+ byte[] t;
+ int sofar = 0;
+ int length;
+ for (int i = 0; i < limit; i++)
+ {
+ // 3.1 Convert i to an octet string C of length 4 with the primitive
+ // I2OSP: C = I2OSP(i, 4).
+ // 3.2 Concatenate the hash of the seed Z and C to the octet string T:
+ // T = T || Hash(Z || C)
+ hashZC = (IMessageDigest) hashZ.clone();
+ hashZC.update((byte) (i >>> 24));
+ hashZC.update((byte) (i >>> 16));
+ hashZC.update((byte) (i >>> 8));
+ hashZC.update((byte) i);
+ t = hashZC.digest();
+ length = l - sofar;
+ length = (length > hLen ? hLen : length);
+ System.arraycopy(t, 0, result, sofar, length);
+ sofar += length;
+ }
+ // 4. Output the leading l octets of T as the octet string mask.
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/RSA.java b/libjava/classpath/gnu/java/security/sig/rsa/RSA.java
new file mode 100644
index 00000000000..7d1707e195d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/RSA.java
@@ -0,0 +1,356 @@
+/* RSA.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Properties;
+import gnu.java.security.util.PRNG;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * <p>Utility methods related to the RSA algorithm.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ *
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ *
+ * <li><a href="http://crypto.stanford.edu/~dabo/abstracts/ssl-timing.html">
+ * Remote timing attacks are practical</a><br>
+ * D. Boneh and D. Brumley.</li>
+ * </ol>
+ */
+public class RSA
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final BigInteger ZERO = BigInteger.ZERO;
+
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ /** Our default source of randomness. */
+ private static final PRNG prng = PRNG.getInstance();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial private constructor to enforce Singleton pattern. */
+ private RSA()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Signature and verification methods --------------------------------------
+
+ /**
+ * <p>An implementation of the <b>RSASP</b> method: Assuming that the
+ * designated RSA private key is a valid one, this method computes a
+ * <i>signature representative</i> for a designated <i>message
+ * representative</i> signed by the holder of the designated RSA private
+ * key.<p>
+ *
+ * @param K the RSA private key.
+ * @param m the <i>message representative</i>: an integer between
+ * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
+ * <i>modulus</i>.
+ * @return the <i>signature representative</i>, an integer between
+ * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
+ * <i>modulus</i>.
+ * @throws ClassCastException if <code>K</code> is not an RSA one.
+ * @throws IllegalArgumentException if <code>m</code> (the <i>message
+ * representative</i>) is out of range.
+ */
+ public static final BigInteger sign(final PrivateKey K, final BigInteger m)
+ {
+ try
+ {
+ return RSADP((RSAPrivateKey) K, m);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new IllegalArgumentException(
+ "message representative out of range");
+ }
+ }
+
+ /**
+ * <p>An implementation of the <b>RSAVP</b> method: Assuming that the
+ * designated RSA public key is a valid one, this method computes a
+ * <i>message representative</i> for the designated <i>signature
+ * representative</i> generated by an RSA private key, for a message
+ * intended for the holder of the designated RSA public key.</p>
+ *
+ * @param K the RSA public key.
+ * @param s the <i>signature representative</i>, an integer between
+ * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
+ * <i>modulus</i>.
+ * @return a <i>message representative</i>: an integer between <code>0</code>
+ * and <code>n - 1</code>, where <code>n</code> is the RSA <i>modulus</i>.
+ * @throws ClassCastException if <code>K</code> is not an RSA one.
+ * @throws IllegalArgumentException if <code>s</code> (the <i>signature
+ * representative</i>) is out of range.
+ */
+ public static final BigInteger verify(final PublicKey K, final BigInteger s)
+ {
+ try
+ {
+ return RSAEP((RSAPublicKey) K, s);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new IllegalArgumentException(
+ "signature representative out of range");
+ }
+ }
+
+ // Encryption and decryption methods ---------------------------------------
+
+ /**
+ * <p>An implementation of the <code>RSAEP</code> algorithm.</p>
+ *
+ * @param K the recipient's RSA public key.
+ * @param m the message representative as an MPI.
+ * @return the resulting MPI --an MPI between <code>0</code> and
+ * <code>n - 1</code> (<code>n</code> being the public shared modulus)-- that
+ * will eventually be padded with an appropriate framing/padding scheme.
+ * @throws ClassCastException if <code>K</code> is not an RSA one.
+ * @throws IllegalArgumentException if <code>m</code>, the message
+ * representative is not between <code>0</code> and <code>n - 1</code>
+ * (<code>n</code> being the public shared modulus).
+ */
+ public static final BigInteger encrypt(final PublicKey K, final BigInteger m)
+ {
+ try
+ {
+ return RSAEP((RSAPublicKey) K, m);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new IllegalArgumentException(
+ "message representative out of range");
+ }
+ }
+
+ /**
+ * <p>An implementation of the <code>RSADP</code> algorithm.</p>
+ *
+ * @param K the recipient's RSA private key.
+ * @param c the ciphertext representative as an MPI.
+ * @return the message representative, an MPI between <code>0</code> and
+ * <code>n - 1</code> (<code>n</code> being the shared public modulus).
+ * @throws ClassCastException if <code>K</code> is not an RSA one.
+ * @throws IllegalArgumentException if <code>c</code>, the ciphertext
+ * representative is not between <code>0</code> and <code>n - 1</code>
+ * (<code>n</code> being the shared public modulus).
+ */
+ public static final BigInteger decrypt(final PrivateKey K, final BigInteger c)
+ {
+ try
+ {
+ return RSADP((RSAPrivateKey) K, c);
+ }
+ catch (IllegalArgumentException x)
+ {
+ throw new IllegalArgumentException(
+ "ciphertext representative out of range");
+ }
+ }
+
+ // Conversion methods ------------------------------------------------------
+
+ /**
+ * <p>Converts a <i>multi-precision integer</i> (MPI) <code>s</code> into an
+ * octet sequence of length <code>k</code>.</p>
+ *
+ * @param s the multi-precision integer to convert.
+ * @param k the length of the output.
+ * @return the result of the transform.
+ * @exception IllegalArgumentException if the length in octets of meaningful
+ * bytes of <code>s</code> is greater than <code>k</code>.
+ */
+ public static final byte[] I2OSP(final BigInteger s, final int k)
+ {
+ byte[] result = s.toByteArray();
+ if (result.length < k)
+ {
+ final byte[] newResult = new byte[k];
+ System.arraycopy(result, 0, newResult, k - result.length, result.length);
+ result = newResult;
+ }
+ else if (result.length > k)
+ { // leftmost extra bytes should all be 0
+ final int limit = result.length - k;
+ for (int i = 0; i < limit; i++)
+ {
+ if (result[i] != 0x00)
+ {
+ throw new IllegalArgumentException("integer too large");
+ }
+ }
+ final byte[] newResult = new byte[k];
+ System.arraycopy(result, limit, newResult, 0, k);
+ result = newResult;
+ }
+ return result;
+ }
+
+ // helper methods ----------------------------------------------------------
+
+ private static final BigInteger RSAEP(final RSAPublicKey K, final BigInteger m)
+ {
+ // 1. If the representative m is not between 0 and n - 1, output
+ // "representative out of range" and stop.
+ final BigInteger n = K.getModulus();
+ if (m.compareTo(ZERO) < 0 || m.compareTo(n.subtract(ONE)) > 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ // 2. Let c = m^e mod n.
+ final BigInteger e = K.getPublicExponent();
+ final BigInteger result = m.modPow(e, n);
+ // 3. Output c.
+ return result;
+ }
+
+ private static final BigInteger RSADP(final RSAPrivateKey K, BigInteger c)
+ {
+ // 1. If the representative c is not between 0 and n - 1, output
+ // "representative out of range" and stop.
+ final BigInteger n = K.getModulus();
+ if (c.compareTo(ZERO) < 0 || c.compareTo(n.subtract(ONE)) > 0)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ // 2. The representative m is computed as follows.
+ BigInteger result;
+ if (!(K instanceof RSAPrivateCrtKey))
+ {
+ // a. If the first form (n, d) of K is used, let m = c^d mod n.
+ final BigInteger d = K.getPrivateExponent();
+ result = c.modPow(d, n);
+ }
+ else
+ {
+ // from [3] p.13 --see class docs:
+ // The RSA blinding operation calculates x = (r^e) * g mod n before
+ // decryption, where r is random, e is the RSA encryption exponent, and
+ // g is the ciphertext to be decrypted. x is then decrypted as normal,
+ // followed by division by r, i.e. (x^e) / r mod n. Since r is random,
+ // x is random and timing the decryption should not reveal information
+ // about the key. Note that r should be a new random number for every
+ // decryption.
+ final boolean rsaBlinding = Properties.doRSABlinding();
+ BigInteger r = null;
+ BigInteger e = null;
+ if (rsaBlinding)
+ { // pre-decryption
+ r = newR(n);
+ e = ((RSAPrivateCrtKey) K).getPublicExponent();
+ final BigInteger x = r.modPow(e, n).multiply(c).mod(n);
+ c = x;
+ }
+
+ // b. If the second form (p, q, dP, dQ, qInv) and (r_i, d_i, t_i)
+ // of K is used, proceed as follows:
+ final BigInteger p = ((RSAPrivateCrtKey) K).getPrimeP();
+ final BigInteger q = ((RSAPrivateCrtKey) K).getPrimeQ();
+ final BigInteger dP = ((RSAPrivateCrtKey) K).getPrimeExponentP();
+ final BigInteger dQ = ((RSAPrivateCrtKey) K).getPrimeExponentQ();
+ final BigInteger qInv = ((RSAPrivateCrtKey) K).getCrtCoefficient();
+
+ // i. Let m_1 = c^dP mod p and m_2 = c^dQ mod q.
+ final BigInteger m_1 = c.modPow(dP, p);
+ final BigInteger m_2 = c.modPow(dQ, q);
+ // ii. If u > 2, let m_i = c^(d_i) mod r_i, i = 3, ..., u.
+ // iii. Let h = (m_1 - m_2) * qInv mod p.
+ final BigInteger h = m_1.subtract(m_2).multiply(qInv).mod(p);
+ // iv. Let m = m_2 + q * h.
+ result = m_2.add(q.multiply(h));
+
+ if (rsaBlinding)
+ { // post-decryption
+ result = result.multiply(r.modInverse(n)).mod(n);
+ }
+ }
+
+ // 3. Output m
+ return result;
+ }
+
+ /**
+ * <p>Returns a random MPI with a random bit-length of the form <code>8b</code>,
+ * where <code>b</code> is in the range <code>[32..64]</code>.</p>
+ *
+ * @return a random MPI whose length in bytes is between 32 and 64 inclusive.
+ */
+ private static final BigInteger newR(final BigInteger N)
+ {
+ final int upper = (N.bitLength() + 7) / 8;
+ final int lower = upper / 2;
+ final byte[] bl = new byte[1];
+ int b;
+ do
+ {
+ prng.nextBytes(bl);
+ b = bl[0] & 0xFF;
+ }
+ while (b < lower || b > upper);
+ final byte[] buffer = new byte[b]; // 256-bit MPI
+ prng.nextBytes(buffer);
+ return new BigInteger(1, buffer);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java b/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java
new file mode 100644
index 00000000000..d4b69a7a18f
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5Signature.java
@@ -0,0 +1,247 @@
+/* RSAPKCS1V1_5Signature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.sig.BaseSignature;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+
+/**
+ * <p>The RSA-PKCS1-V1.5 signature scheme is a digital signature scheme with
+ * appendix (SSA) combining the RSA algorithm with the EMSA-PKCS1-v1_5 encoding
+ * method.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ *
+ * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
+ * Standards (PKCS) #1:</a><br>
+ * RSA Cryptography Specifications Version 2.1.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.2 $
+ */
+public class RSAPKCS1V1_5Signature extends BaseSignature
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The underlying EMSA-PKCS1-v1.5 instance for this object. */
+ private EMSA_PKCS1_V1_5 pkcs1;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Default 0-arguments constructor. Uses SHA-1 as the default hash.
+ */
+ public RSAPKCS1V1_5Signature()
+ {
+ this(Registry.SHA160_HASH);
+ }
+
+ /**
+ * <p>Constructs an instance of this object using the designated message
+ * digest algorithm as its underlying hash function.</p>
+ *
+ * @param mdName the canonical name of the underlying hash function.
+ */
+ public RSAPKCS1V1_5Signature(final String mdName)
+ {
+ this(HashFactory.getInstance(mdName));
+ }
+
+ public RSAPKCS1V1_5Signature(IMessageDigest md)
+ {
+ super(Registry.RSA_PKCS1_V1_5_SIG, md);
+
+ pkcs1 = EMSA_PKCS1_V1_5.getInstance(md.name());
+ }
+
+ /** Private constructor for cloning purposes. */
+ private RSAPKCS1V1_5Signature(final RSAPKCS1V1_5Signature that)
+ {
+ this(that.md.name());
+
+ this.publicKey = that.publicKey;
+ this.privateKey = that.privateKey;
+ this.md = (IMessageDigest) that.md.clone();
+ this.pkcs1 = (EMSA_PKCS1_V1_5) that.pkcs1.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in superclass ------------------------
+
+ public Object clone()
+ {
+ return new RSAPKCS1V1_5Signature(this);
+ }
+
+ protected void setupForVerification(final PublicKey k)
+ throws IllegalArgumentException
+ {
+ if (!(k instanceof RSAPublicKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ publicKey = k;
+ }
+
+ protected void setupForSigning(final PrivateKey k)
+ throws IllegalArgumentException
+ {
+ if (!(k instanceof RSAPrivateKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ privateKey = k;
+ }
+
+ protected Object generateSignature() throws IllegalStateException
+ {
+ // 1. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
+ // operation (Section 9.2) to the message M to produce an encoded
+ // message EM of length k octets:
+ //
+ // EM = EMSA-PKCS1-V1_5-ENCODE (M, k).
+ //
+ // If the encoding operation outputs "message too long," output
+ // "message too long" and stop. If the encoding operation outputs
+ // "intended encoded message length too short," output "RSA modulus
+ // too short" and stop.
+ final int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
+ final int k = (modBits + 7) / 8;
+ final byte[] EM = pkcs1.encode(md.digest(), k);
+
+ // 2. RSA signature:
+ // a. Convert the encoded message EM to an integer message epresentative
+ // m (see Section 4.2): m = OS2IP (EM).
+ final BigInteger m = new BigInteger(1, EM);
+ // b. Apply the RSASP1 signature primitive (Section 5.2.1) to the RSA
+ // private key K and the message representative m to produce an
+ // integer signature representative s: s = RSASP1 (K, m).
+ final BigInteger s = RSA.sign(privateKey, m);
+ // c. Convert the signature representative s to a signature S of length
+ // k octets (see Section 4.1): S = I2OSP (s, k).
+ // 3. Output the signature S.
+ return RSA.I2OSP(s, k);
+ }
+
+ protected boolean verifySignature(final Object sig)
+ throws IllegalStateException
+ {
+ if (publicKey == null)
+ {
+ throw new IllegalStateException();
+ }
+ final byte[] S = (byte[]) sig;
+ // 1. Length checking: If the length of the signature S is not k octets,
+ // output "invalid signature" and stop.
+ final int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
+ final int k = (modBits + 7) / 8;
+ if (S.length != k)
+ {
+ return false;
+ }
+ // 2. RSA verification:
+ // a. Convert the signature S to an integer signature representative
+ // s (see Section 4.2): s = OS2IP (S).
+ final BigInteger s = new BigInteger(1, S);
+ // b. Apply the RSAVP1 verification primitive (Section 5.2.2) to the
+ // RSA public key (n, e) and the signature representative s to
+ // produce an integer message representative m:
+ // m = RSAVP1 ((n, e), s).
+ // If RSAVP1 outputs "signature representative out of range,"
+ // output "invalid signature" and stop.
+ final BigInteger m;
+ try
+ {
+ m = RSA.verify(publicKey, s);
+ }
+ catch (IllegalArgumentException x)
+ {
+ return false;
+ }
+ // c. Convert the message representative m to an encoded message EM
+ // of length k octets (see Section 4.1): EM = I2OSP (m, k).
+ // If I2OSP outputs "integer too large," output "invalid signature"
+ // and stop.
+ final byte[] EM;
+ try
+ {
+ EM = RSA.I2OSP(m, k);
+ }
+ catch (IllegalArgumentException x)
+ {
+ return false;
+ }
+ // 3. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
+ // operation (Section 9.2) to the message M to produce a second
+ // encoded message EM' of length k octets:
+ // EM' = EMSA-PKCS1-V1_5-ENCODE (M, k).
+ // If the encoding operation outputs "message too long," output
+ // "message too long" and stop. If the encoding operation outputs
+ // "intended encoded message length too short," output "RSA modulus
+ // too short" and stop.
+ final byte[] EMp = pkcs1.encode(md.digest(), k);
+ // 4. Compare the encoded message EM and the second encoded message EM'.
+ // If they are the same, output "valid signature"; otherwise, output
+ // "invalid signature."
+ return Arrays.equals(EM, EMp);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5SignatureRawCodec.java b/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5SignatureRawCodec.java
new file mode 100644
index 00000000000..68c1edaa6b1
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5SignatureRawCodec.java
@@ -0,0 +1,153 @@
+/* RSAPKCS1V1_5SignatureRawCodec.java -- Raw RSA PKCS1 v1.5 signature codeec
+ 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.java.security.sig.rsa;
+
+import java.io.ByteArrayOutputStream;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.ISignatureCodec;
+
+/**
+ * An object that implements the {@link ISignatureCodec} operations for the
+ * <i>Raw</i> format to use with RSA-PKCS#1 v1.5 signatures.
+ */
+public class RSAPKCS1V1_5SignatureRawCodec
+ implements ISignatureCodec
+{
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * Returns the encoded form of the designated RSA-PKCS#1 (v1.5) signature
+ * object according to the <i>Raw</i> format supported by this library.
+ * <p>
+ * The <i>Raw</i> format for such a signature, in this implementation, is a
+ * byte sequence consisting of the following:
+ * <p>
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE},
+ * <li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the RSA-PKCS#1 (v1.5)
+ * signature bytes in internet order,</li>
+ * <li>the RSA-PKCS#1 (v1.5) signature bytes in internet order.</li>
+ * </ol>
+ *
+ * @param signature the signature to encode, consisting of the output of the
+ * <code>sign()</code> method of a {@link RSAPKCS1V1_5Signature}
+ * instance --a byte array.
+ * @return the <i>Raw</i> format encoding of the designated signature.
+ * @exception IllegalArgumentException if the designated signature is not an
+ * RSA-PKCS#1 (v1.5) one.
+ */
+ public byte[] encodeSignature(Object signature)
+ {
+ byte[] buffer;
+ try
+ {
+ buffer = (byte[]) signature;
+ }
+ catch (Exception x)
+ {
+ throw new IllegalArgumentException("Signature/codec mismatch");
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE[0]);
+ baos.write(Registry.MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE[1]);
+ baos.write(Registry.MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE[2]);
+ baos.write(Registry.MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE[3]);
+
+ // version
+ baos.write(0x01);
+
+ // signature bytes
+ int length = buffer.length;
+ baos.write( length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write( length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ /**
+ * Returns the decoded object from a designated input assumed to have been
+ * generated by the {@link #encodeSignature(Object)} method.
+ *
+ * @param input the input bytes of a previously Raw-encoded RSA PKCS1 (v1.5)
+ * signature.
+ * @return the signature object.
+ * @throws IllegalArgumentException if the designated input does not start
+ * with the right <i>magic</i> characters, or if the <i>version</i>
+ * is not supported.
+ */
+ public Object decodeSignature(byte[] input)
+ {
+ // magic
+ if (input[0] != Registry.MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE[0]
+ || input[1] != Registry.MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE[1]
+ || input[2] != Registry.MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE[2]
+ || input[3] != Registry.MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE[3])
+ throw new IllegalArgumentException("Signature/codec mismatch");
+
+ // version
+ if (input[4] != 0x01)
+ throw new IllegalArgumentException("Wrong or unsupported format version");
+
+ int i = 5;
+ int l;
+
+ // signature bytes
+ l = input[i++] << 24
+ | (input[i++] & 0xFF) << 16
+ | (input[i++] & 0xFF) << 8
+ | (input[i++] & 0xFF);
+ byte[] result = new byte[l];
+ System.arraycopy(input, i, result, 0, l);
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5SignatureX509Codec.java b/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5SignatureX509Codec.java
new file mode 100644
index 00000000000..3cb375602a0
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/RSAPKCS1V1_5SignatureX509Codec.java
@@ -0,0 +1,128 @@
+/* RSAPSSSignatureX509Codec.java -- X.509 encoder/decoder for RSA signatures
+ 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.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.ISignatureCodec;
+
+import java.security.InvalidParameterException;
+
+/**
+ * An implementation of an {@link ISignatureCodec} that knows to encode and
+ * decode RSA PKCS1 (v1.5) signatures into the raw bytes which would constitute
+ * a DER-encoded form of the ASN.1 structure defined in RFC-2459, and RFC-2313
+ * as described in the next paragraphs.
+ * <p>
+ * Digital signatures when transmitted in an X.509 certificates are encoded
+ * in DER (Distinguished Encoding Rules) as a BIT STRING; i.e.
+ *
+ * <pre>
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ * </pre>
+ * <p>
+ * The output of the encoder, and the input of the decoder, of this codec are
+ * then the <i>raw</i> bytes of such a BIT STRING; i.e. not the DER-encoded
+ * form itself.
+ * <p>
+ * Our implementation of the RSA PKCS1 signature algorithm outputs a byte array
+ * as the result of generating a digital signature, in accordance with RFC-2313.
+ * As a consequence, the encoder and decoder of this codec, simply pass through
+ * such a byte array.
+ * <p>
+ * Client code that needs to build a DER BIT STRING <b>MUST</b> construct such
+ * an ASN.1 value. The following is an example of how to do this:
+ * <p>
+ * <pre>
+ * ...
+ * import gnu.java.security.der.BitString;
+ * import gnu.java.security.der.DER;
+ * import gnu.java.security.der.DERValue;
+ * ...
+ * DERValue bitString = new DERValue(DER.BIT_STRING, new BitString(sigBytes));
+ * ...
+ * </pre>
+ */
+public class RSAPKCS1V1_5SignatureX509Codec
+ implements ISignatureCodec
+{
+ // default 0-arguments constructor
+
+ public int getFormatID()
+ {
+ return Registry.X509_ENCODING_ID;
+ }
+
+ /**
+ * Encodes an RSA Signature output as a <i>signature</i> BIT STRING as
+ * defined in the documentation of this class.
+ *
+ * @param signature the output of the RSA PKCS1 (v1.5) signature algorithm;
+ * i.e. the value returned by the invocation of
+ * {@link gnu.java.security.sig.ISignature#sign()} method. In the
+ * case of the RSA PKCS1 (v1.5) signature this is an array of bytes.
+ * @return the raw bytes of an RSA signature which could be then used as the
+ * contents of a BIT STRING as per rfc-2459.
+ */
+ public byte[] encodeSignature(Object signature)
+ {
+ byte[] result = (byte[]) signature;
+ return result;
+ }
+
+ /**
+ * Decodes a <i>signature</i> as defined in the documentation of this class.
+ *
+ * @param input the byte array to unmarshall into a valid RSA PKCS1 (v1.5)
+ * signature instance; i.e. a byte array. MUST NOT be null.
+ * @return an array of raw bytes decoded from the designated input. In the
+ * case of RSA PKCS1 (v1.5) this is the same as the input.
+ * @throw InvalidParameterException if the <code>input</code> array is null.
+ */
+ public Object decodeSignature(byte[] input)
+ {
+ if (input == null)
+ throw new InvalidParameterException("Input bytes MUST NOT be null");
+
+ return input;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/RSAPSSSignature.java b/libjava/classpath/gnu/java/security/sig/rsa/RSAPSSSignature.java
new file mode 100644
index 00000000000..95a6653f393
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/RSAPSSSignature.java
@@ -0,0 +1,348 @@
+/* RSAPSSSignature.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.sig.BaseSignature;
+import gnu.java.security.util.Util;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * <p>The RSA-PSS signature scheme is a public-key encryption scheme combining
+ * the RSA algorithm with the Probabilistic Signature Scheme (PSS) encoding
+ * method.</p>
+ *
+ * <p>The inventors of RSA are Ronald L. Rivest, Adi Shamir, and Leonard Adleman,
+ * while the inventors of the PSS encoding method are Mihir Bellare and Phillip
+ * Rogaway. During efforts to adopt RSA-PSS into the P1363a standards effort,
+ * certain adaptations to the original version of RSA-PSS were made by Mihir
+ * Bellare and Phillip Rogaway and also by Burt Kaliski (the editor of IEEE
+ * P1363a) to facilitate implementation and integration into existing protocols.</p>
+ *
+ * <p>References:</pr>
+ * <ol>
+ * <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
+ * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
+ * Primitive specification and supporting documentation.<br>
+ * Jakob Jonsson and Burt Kaliski.</li>
+ * </ol>
+ *
+ * @version $Revision: 1.2 $
+ */
+public class RSAPSSSignature extends BaseSignature
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "rsa-pss";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 1;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The underlying EMSA-PSS instance for this object. */
+ private EMSA_PSS pss;
+
+ /** The desired length in octets of the EMSA-PSS salt. */
+ private int sLen;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Default 0-arguments constructor. Uses SHA-1 as the default hash and a
+ * 0-octet <i>salt</i>.
+ */
+ public RSAPSSSignature()
+ {
+ this(Registry.SHA160_HASH, 0);
+ }
+
+ /**
+ * <p>Constructs an instance of this object using the designated message
+ * digest algorithm as its underlying hash function, and having 0-octet
+ * <i>salt</i>.</p>
+ *
+ * @param mdName the canonical name of the underlying hash function.
+ */
+ public RSAPSSSignature(String mdName)
+ {
+ this(mdName, 0);
+ }
+
+ /**
+ * <p>Constructs an instance of this object using the designated message
+ * digest algorithm as its underlying hash function.</p>
+ *
+ * @param mdName the canonical name of the underlying hash function.
+ * @param sLen the desired length in octets of the salt to use for encoding /
+ * decoding signatures.
+ */
+ public RSAPSSSignature(String mdName, int sLen)
+ {
+ this(HashFactory.getInstance(mdName), sLen);
+ }
+
+ public RSAPSSSignature(IMessageDigest md, int sLen)
+ {
+ super(Registry.RSA_PSS_SIG, md);
+
+ pss = EMSA_PSS.getInstance(md.name());
+ this.sLen = sLen;
+ }
+
+ /** Private constructor for cloning purposes. */
+ private RSAPSSSignature(RSAPSSSignature that)
+ {
+ this(that.md.name(), that.sLen);
+
+ this.publicKey = that.publicKey;
+ this.privateKey = that.privateKey;
+ this.md = (IMessageDigest) that.md.clone();
+ this.pss = (EMSA_PSS) that.pss.clone();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // Implementation of abstract methods in superclass ------------------------
+
+ public Object clone()
+ {
+ return new RSAPSSSignature(this);
+ }
+
+ protected void setupForVerification(PublicKey k)
+ throws IllegalArgumentException
+ {
+ if (!(k instanceof RSAPublicKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ publicKey = (RSAPublicKey) k;
+ }
+
+ protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
+ {
+ if (!(k instanceof RSAPrivateKey))
+ {
+ throw new IllegalArgumentException();
+ }
+ privateKey = (RSAPrivateKey) k;
+ }
+
+ protected Object generateSignature() throws IllegalStateException
+ {
+ // 1. Apply the EMSA-PSS encoding operation to the message M to produce an
+ // encoded message EM of length CEILING((modBits ? 1)/8) octets such
+ // that the bit length of the integer OS2IP(EM) is at most modBits ? 1:
+ // EM = EMSA-PSS-Encode(M,modBits ? 1).
+ // Note that the octet length of EM will be one less than k if
+ // modBits ? 1 is divisible by 8. If the encoding operation outputs
+ // 'message too long' or 'encoding error,' then output 'message too
+ // long' or 'encoding error' and stop.
+ int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
+ byte[] salt = new byte[sLen];
+ this.nextRandomBytes(salt);
+ byte[] EM = pss.encode(md.digest(), modBits - 1, salt);
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("EM (sign): " + Util.toString(EM));
+ }
+ // 2. Convert the encoded message EM to an integer message representative
+ // m (see Section 1.2.2): m = OS2IP(EM).
+ BigInteger m = new BigInteger(1, EM);
+ // 3. Apply the RSASP signature primitive to the public key K and the
+ // message representative m to produce an integer signature
+ // representative s: s = RSASP(K,m).
+ BigInteger s = RSA.sign(privateKey, m);
+ // 4. Convert the signature representative s to a signature S of length k
+ // octets (see Section 1.2.1): S = I2OSP(s, k).
+ // 5. Output the signature S.
+ int k = (modBits + 7) / 8;
+ // return encodeSignature(s, k);
+ return RSA.I2OSP(s, k);
+ }
+
+ protected boolean verifySignature(Object sig) throws IllegalStateException
+ {
+ if (publicKey == null)
+ {
+ throw new IllegalStateException();
+ }
+ // byte[] S = decodeSignature(sig);
+ byte[] S = (byte[]) sig;
+ // 1. If the length of the signature S is not k octets, output 'signature
+ // invalid' and stop.
+ int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
+ int k = (modBits + 7) / 8;
+ if (S.length != k)
+ {
+ return false;
+ }
+ // 2. Convert the signature S to an integer signature representative s:
+ // s = OS2IP(S).
+ BigInteger s = new BigInteger(1, S);
+ // 3. Apply the RSAVP verification primitive to the public key (n, e) and
+ // the signature representative s to produce an integer message
+ // representative m: m = RSAVP((n, e), s).
+ // If RSAVP outputs 'signature representative out of range,' then
+ // output 'signature invalid' and stop.
+ BigInteger m = null;
+ try
+ {
+ m = RSA.verify(publicKey, s);
+ }
+ catch (IllegalArgumentException x)
+ {
+ return false;
+ }
+ // 4. Convert the message representative m to an encoded message EM of
+ // length emLen = CEILING((modBits - 1)/8) octets, where modBits is
+ // equal to the bit length of the modulus: EM = I2OSP(m, emLen).
+ // Note that emLen will be one less than k if modBits - 1 is divisible
+ // by 8. If I2OSP outputs 'integer too large,' then output 'signature
+ // invalid' and stop.
+ int emBits = modBits - 1;
+ int emLen = (emBits + 7) / 8;
+ byte[] EM = m.toByteArray();
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("EM (verify): " + Util.toString(EM));
+ }
+ if (EM.length > emLen)
+ {
+ return false;
+ }
+ else if (EM.length < emLen)
+ {
+ byte[] newEM = new byte[emLen];
+ System.arraycopy(EM, 0, newEM, emLen - EM.length, EM.length);
+ EM = newEM;
+ }
+ // 5. Apply the EMSA-PSS decoding operation to the message M and the
+ // encoded message EM: Result = EMSA-PSS-Decode(M, EM, emBits). If
+ // Result = 'consistent,' output 'signature verified.' Otherwise,
+ // output 'signature invalid.'
+ byte[] mHash = md.digest();
+ boolean result = false;
+ try
+ {
+ result = pss.decode(mHash, EM, emBits, sLen);
+ }
+ catch (IllegalArgumentException x)
+ {
+ result = false;
+ }
+ return result;
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * Converts the <i>signature representative</i> <code>s</code> to a signature
+ * <code>S</code> of length <code>k</code> octets; i.e.
+ * <code>S = I2OSP(s, k)</code>, where <code>k = CEILING(modBits/8)</code>.
+ *
+ * @param s the <i>signature representative</i>.
+ * @param k the length of the output.
+ * @return the signature as an octet sequence.
+ * @exception IllegalArgumentException if the length in octets of meaningful
+ * bytes of <code>s</code> is greater than <code>k</code>, implying that
+ * <code>s</code> is not less than the RSA <i>modulus</i>.
+ */
+ // private Object encodeSignature(BigInteger s, int k) {
+ // if (DEBUG && debuglevel > 8) {
+ // debug("s.bitLength(): "+String.valueOf(s.bitLength()));
+ // debug("k: "+String.valueOf(k));
+ // }
+ // byte[] result = s.toByteArray();
+ // if (DEBUG && debuglevel > 8) {
+ // debug("s: "+Util.toString(result));
+ // debug("s (bytes): "+String.valueOf(result.length));
+ // }
+ // if (result.length < k) {
+ // byte[] newResult = new byte[k];
+ // System.arraycopy(result, 0, newResult, k-result.length, result.length);
+ // result = newResult;
+ // } else if (result.length > k) { // leftmost extra bytes should all be 0
+ // int limit = result.length - k;
+ // for (int i = 0; i < limit; i++) {
+ // if (result[i] != 0x00) {
+ // throw new IllegalArgumentException("integer too large");
+ // }
+ // }
+ // byte[] newResult = new byte[k];
+ // System.arraycopy(result, limit, newResult, 0, k);
+ // result = newResult;
+ // }
+ // return result;
+ // }
+ /**
+ * Returns the output of a previously generated signature object as an octet
+ * sequence.<p>
+ *
+ * @return the octet sequence <code>S</code>.
+ */
+ // private byte[] decodeSignature(Object signature) {
+ // return (byte[]) signature;
+ // }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java b/libjava/classpath/gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java
new file mode 100644
index 00000000000..64a972ca366
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/RSAPSSSignatureRawCodec.java
@@ -0,0 +1,159 @@
+/* RSAPSSSignatureRawCodec.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.sig.rsa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.sig.ISignatureCodec;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * <p>An object that implements the {@link gnu.crypto.sig.ISignatureCodec}
+ * operations for the <i>Raw</i> format to use with RSA-PSS signatures.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class RSAPSSSignatureRawCodec implements ISignatureCodec
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.keys.IKeyPairCodec interface implementation
+ // -------------------------------------------------------------------------
+
+ public int getFormatID()
+ {
+ return RAW_FORMAT;
+ }
+
+ /**
+ * <p>Returns the encoded form of the designated RSA-PSS signature object
+ * according to the <i>Raw</i> format supported by this library.</p>
+ *
+ * <p>The <i>Raw</i> format for an RSA-PSS signature, in this implementation,
+ * is a byte sequence consisting of the following:</p>
+ *
+ * <ol>
+ * <li>4-byte magic consisting of the value of the literal
+ * {@link Registry#MAGIC_RAW_RSA_PSS_SIGNATURE},<li>
+ * <li>1-byte version consisting of the constant: 0x01,</li>
+ * <li>4-byte count of following bytes representing the RSA-PSS signature
+ * bytes in internet order,</li>
+ * <li>the RSA-PSS signature bytes in internet order.</li>
+ * </ol>
+ *
+ * @param signature the signature to encode, consisting of the output of the
+ * <code>sign()</code> method of a {@link RSAPSSSignature} instance --a byte
+ * array.
+ * @return the <i>Raw</i> format encoding of the designated signature.
+ * @exception IllegalArgumentException if the designated signature is not an
+ * RSA-PSS one.
+ */
+ public byte[] encodeSignature(Object signature)
+ {
+ byte[] buffer;
+ try
+ {
+ buffer = (byte[]) signature;
+ }
+ catch (Exception x)
+ {
+ throw new IllegalArgumentException("key");
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // magic
+ baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[0]);
+ baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]);
+ baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]);
+ baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3]);
+
+ // version
+ baos.write(0x01);
+
+ // signature bytes
+ int length = buffer.length;
+ baos.write(length >>> 24);
+ baos.write((length >>> 16) & 0xFF);
+ baos.write((length >>> 8) & 0xFF);
+ baos.write(length & 0xFF);
+ baos.write(buffer, 0, length);
+
+ return baos.toByteArray();
+ }
+
+ public Object decodeSignature(byte[] k)
+ {
+ // magic
+ if (k[0] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[0]
+ || k[1] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]
+ || k[2] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]
+ || k[3] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3])
+ {
+ throw new IllegalArgumentException("magic");
+ }
+
+ // version
+ if (k[4] != 0x01)
+ {
+ throw new IllegalArgumentException("version");
+ }
+
+ int i = 5;
+ int l;
+
+ // signature bytes
+ l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
+ | (k[i++] & 0xFF);
+ byte[] result = new byte[l];
+ System.arraycopy(k, i, result, 0, l);
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/sig/rsa/RSASignatureFactory.java b/libjava/classpath/gnu/java/security/sig/rsa/RSASignatureFactory.java
new file mode 100644
index 00000000000..b8e12caf769
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/sig/rsa/RSASignatureFactory.java
@@ -0,0 +1,176 @@
+/* RSASignatureFactory.java -- A Factory class to instantiate RSA Signatures
+ 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.java.security.sig.rsa;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.HashFactory;
+import gnu.java.security.hash.IMessageDigest;
+import gnu.java.security.sig.ISignature;
+
+/**
+ * A Factory class to instantiate RSA Signature classes.
+ */
+public class RSASignatureFactory
+{
+ private static Set names;
+
+ /**
+ * Private constructor to enforce usage through Factory (class) methods.
+ */
+ private RSASignatureFactory()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new instance of an RSA Signature given its name. The name of an
+ * RSA Signature always starts with <code>rsa-</code>, followed by either
+ * <code>pss</code> or <code>pkcs1_v1.5</code>. An optional message digest
+ * name, to be used with the RSA signature may be specified by appending the
+ * hyphen chanaracter <code>-</code> followed by the canonical message digest
+ * algorithm name. When no message digest algorithm name is given, SHA-160 is
+ * used.
+ *
+ * @param name the composite RSA signature name.
+ * @return a new instance of an RSA Signature algorithm implementation.
+ * Returns <code>null</code> if the given name does not correspond to any
+ * supported RSA Signature encoding and message digest combination.
+ */
+ public static final ISignature getInstance(String name)
+ {
+ if (name == null)
+ return null;
+
+ name = name.trim();
+ if (name.length() == 0)
+ return null;
+
+ name = name.toLowerCase();
+ if (! name.startsWith(Registry.RSA_SIG_PREFIX))
+ return null;
+
+ name = name.substring(Registry.RSA_SIG_PREFIX.length()).trim();
+ if (name.startsWith(Registry.RSA_PSS_ENCODING))
+ return getPSSSignature(name);
+ else if (name.startsWith(Registry.RSA_PKCS1_V1_5_ENCODING))
+ return getPKCS1Signature(name);
+ else
+ return null;
+ }
+
+ /**
+ * Returns a {@link Set} of names of <i>RSA</i> signatures supported by this
+ * <i>Factory</i>.
+ *
+ * @return a {@link Set} of RSA Signature algorithm names (Strings).
+ */
+ public static synchronized final Set getNames()
+ {
+ if (names == null)
+ {
+ Set hashNames = HashFactory.getNames();
+ HashSet hs = new HashSet();
+ for (Iterator it = hashNames.iterator(); it.hasNext();)
+ {
+ String mdName = (String) it.next();
+ hs.add(Registry.RSA_PSS_SIG + "-" + mdName);
+ }
+
+ hs.add(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.MD2_HASH);
+ hs.add(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.MD5_HASH);
+ hs.add(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.SHA160_HASH);
+ hs.add(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.SHA256_HASH);
+ hs.add(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.SHA384_HASH);
+ hs.add(Registry.RSA_PKCS1_V1_5_SIG + "-" + Registry.SHA512_HASH);
+
+ names = Collections.unmodifiableSet(hs);
+ }
+
+ return names;
+ }
+
+ private static final ISignature getPSSSignature(String name)
+ {
+ name = name.substring(Registry.RSA_PSS_ENCODING.length()).trim();
+ // remove the hyphen if found at the beginning
+ if (name.startsWith("-"))
+ name = name.substring(1).trim();
+
+ IMessageDigest md;
+ if (name.length() == 0)
+ md = HashFactory.getInstance(Registry.SHA160_HASH);
+ else
+ {
+ // check if there is such a hash
+ md = HashFactory.getInstance(name);
+ if (md == null)
+ return null;
+ }
+
+ ISignature result = new RSAPSSSignature(md, 0);
+ return result;
+ }
+
+ private static final ISignature getPKCS1Signature(String name)
+ {
+ name = name.substring(Registry.RSA_PKCS1_V1_5_ENCODING.length()).trim();
+ // remove the hyphen if found at the beginning
+ if (name.startsWith("-"))
+ name = name.substring(1).trim();
+
+ IMessageDigest md;
+ if (name.length() == 0)
+ md = HashFactory.getInstance(Registry.SHA160_HASH);
+ else
+ {
+ // check if there is such a hash
+ md = HashFactory.getInstance(name);
+ if (md == null)
+ return null;
+ }
+
+ ISignature result = new RSAPKCS1V1_5Signature(md);
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/Base64.java b/libjava/classpath/gnu/java/security/util/Base64.java
new file mode 100644
index 00000000000..f9998c38f48
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/Base64.java
@@ -0,0 +1,396 @@
+/* Base64.java --
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Most of this implementation is from Robert Harder's public domain Base64
+ * code (version 1.4.1 available from &lt;http://iharder.net/xmlizable>).
+ */
+public class Base64
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "Base64";
+
+ private static final boolean DEBUG = true;
+
+ private static final int debuglevel = 9;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** Maximum line length (76) of Base64 output. */
+ private static final int MAX_LINE_LENGTH = 76;
+
+ /** The new line character (\n) as one byte. */
+ private static final byte NEW_LINE = (byte) '\n';
+
+ /** The equals sign (=) as a byte. */
+ private static final byte EQUALS_SIGN = (byte) '=';
+
+ private static final byte WHITE_SPACE_ENC = -5; // white space in encoding
+
+ private static final byte EQUALS_SIGN_ENC = -1; // equals sign in encoding
+
+ /** The 64 valid Base64 values. */
+ private static final byte[] ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C',
+ (byte) 'D', (byte) 'E', (byte) 'F',
+ (byte) 'G', (byte) 'H', (byte) 'I',
+ (byte) 'J', (byte) 'K', (byte) 'L',
+ (byte) 'M', (byte) 'N', (byte) 'O',
+ (byte) 'P', (byte) 'Q', (byte) 'R',
+ (byte) 'S', (byte) 'T', (byte) 'U',
+ (byte) 'V', (byte) 'W', (byte) 'X',
+ (byte) 'Y', (byte) 'Z', (byte) 'a',
+ (byte) 'b', (byte) 'c', (byte) 'd',
+ (byte) 'e', (byte) 'f', (byte) 'g',
+ (byte) 'h', (byte) 'i', (byte) 'j',
+ (byte) 'k', (byte) 'l', (byte) 'm',
+ (byte) 'n', (byte) 'o', (byte) 'p',
+ (byte) 'q', (byte) 'r', (byte) 's',
+ (byte) 't', (byte) 'u', (byte) 'v',
+ (byte) 'w', (byte) 'x', (byte) 'y',
+ (byte) 'z', (byte) '0', (byte) '1',
+ (byte) '2', (byte) '3', (byte) '4',
+ (byte) '5', (byte) '6', (byte) '7',
+ (byte) '8', (byte) '9', (byte) '+',
+ (byte) '/' };
+
+ /**
+ * Translates a Base64 value to either its 6-bit reconstruction value or a
+ * negative number indicating some other meaning.
+ */
+ private static final byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
+ -5, -5, // Whitespace: Tab and Linefeed
+ -9, -9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9, -9, -9, -9, -9, -9, -9, -9, -9,
+ -9, -9, -9, -9, // Decimal 14 - 26
+ -9, -9, -9, -9, -9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9, -9, -9, -9, -9, -9, -9, -9, -9,
+ -9, // Decimal 33 - 42
+ 62, // Plus sign at decimal 43
+ -9, -9, -9, // Decimal 44 - 46
+ 63, // Slash at decimal 47
+ 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, // Numbers zero through nine
+ -9, -9, -9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9, -9, -9, // Decimal 62 - 64
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, // Letters 'A' through 'N'
+ 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, // Letters 'O' through 'Z'
+ -9, -9, -9, -9, -9, -9, // Decimal 91 - 96
+ 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, // Letters 'a' through 'm'
+ 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, // Letters 'n' through 'z'
+ -9, -9, -9, -9 // Decimal 123 - 126
+ };
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial private ctor to enfore Singleton pattern. */
+ private Base64()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Encodes a byte array into Base64 notation. Equivalent to calling
+ * <code>encode(source, 0, source.length)</code>.
+ *
+ * @param src the data to convert.
+ */
+ public static final String encode(final byte[] src)
+ {
+ return encode(src, 0, src.length, true);
+ }
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ *
+ * @param src the data to convert.
+ * @param off offset in array where conversion should begin.
+ * @param len length of data to convert.
+ * @param breakLines break lines at 80 characters or less.
+ */
+ public static final String encode(final byte[] src, final int off,
+ final int len, final boolean breakLines)
+ {
+ final int len43 = len * 4 / 3;
+ final byte[] outBuff = new byte[len43 // Main 4:3
+ + ((len % 3) > 0 ? 4 : 0) // Account for padding
+ + (breakLines ? (len43 / MAX_LINE_LENGTH)
+ : 0)]; // New lines
+ int d = 0;
+ int e = 0;
+ final int len2 = len - 2;
+ int lineLength = 0;
+ for (; d < len2; d += 3, e += 4)
+ {
+ encode3to4(src, d + off, 3, outBuff, e);
+ lineLength += 4;
+ if (breakLines && lineLength == MAX_LINE_LENGTH)
+ {
+ outBuff[e + 4] = NEW_LINE;
+ e++;
+ lineLength = 0;
+ }
+ }
+
+ if (d < len)
+ { // padding needed
+ encode3to4(src, d + off, len - d, outBuff, e);
+ e += 4;
+ }
+
+ return new String(outBuff, 0, e);
+ }
+
+ /**
+ * Decodes data from Base64 notation.
+ *
+ * @param s the string to decode.
+ * @return the decoded data.
+ */
+ public static final byte[] decode(final String s)
+ throws UnsupportedEncodingException
+ {
+ final byte[] bytes;
+ bytes = s.getBytes("US-ASCII");
+ return decode(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Decodes Base64 content in byte array format and returns the decoded byte
+ * array.
+ *
+ * @param src the Base64 encoded data.
+ * @param off the offset of where to begin decoding.
+ * @param len the length of characters to decode.
+ * @return the decoded data.
+ * @throws IllegalArgumentException if <code>src</code> contains an illegal
+ * Base-64 character.
+ */
+ public static byte[] decode(final byte[] src, final int off, final int len)
+ {
+ final int len34 = len * 3 / 4;
+ final byte[] outBuff = new byte[len34]; // Upper limit on size of output
+ int outBuffPosn = 0;
+ final byte[] b4 = new byte[4];
+ int b4Posn = 0;
+ int i;
+ byte sbiCrop, sbiDecode;
+ for (i = off; i < off + len; i++)
+ {
+ sbiCrop = (byte) (src[i] & 0x7F); // Only the low seven bits
+ sbiDecode = DECODABET[sbiCrop];
+ if (sbiDecode >= WHITE_SPACE_ENC)
+ { // White space, Equals sign or better
+ if (sbiDecode >= EQUALS_SIGN_ENC)
+ {
+ b4[b4Posn++] = sbiCrop;
+ if (b4Posn > 3)
+ {
+ outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
+ b4Posn = 0;
+ // If that was the equals sign, break out of 'for' loop
+ if (sbiCrop == EQUALS_SIGN)
+ break;
+ } // end if: quartet built
+ } // end if: equals sign or better
+ }
+ else
+ {
+ throw new IllegalArgumentException("Illegal BASE-64 character at #"
+ + i + ": " + src[i]
+ + "(decimal)");
+ }
+ }
+
+ final byte[] result = new byte[outBuffPosn];
+ System.arraycopy(outBuff, 0, result, 0, outBuffPosn);
+ return result;
+ }
+
+ /**
+ * <p>Encodes up to three bytes of the array <code>src</code> and writes
+ * the resulting four Base64 bytes to <code>dest</code>. The source and
+ * destination arrays can be manipulated anywhere along their length by
+ * specifying <code>sOffset</code> and <code>dOffset</code>.</p>
+ *
+ * <p>This method does not check to make sure the arrays are large enough to
+ * accomodate <code>sOffset + 3</code> for the <code>src</code> array or
+ * <code>dOffset + 4</code> for the <code>dest</code> array. The actual
+ * number of significant bytes in the input array is given by
+ * <code>numBytes</code>.</p>
+ *
+ * @param src the array to convert.
+ * @param sOffset the index where conversion begins.
+ * @param numBytes the number of significant bytes in your array.
+ * @param dest the array to hold the conversion.
+ * @param dOffset the index where output will be put.
+ * @return the <code>destination</code> array.
+ */
+ private static final byte[] encode3to4(final byte[] src, final int sOffset,
+ final int numBytes, final byte[] dest,
+ final int dOffset)
+ {
+ // 1 2 3
+ // 01234567890123456789012345678901 Bit position
+ // --------000000001111111122222222 Array position from threeBytes
+ // --------| || || || | Six bit groups to index ALPHABET
+ // >>18 >>12 >> 6 >> 0 Right shift necessary
+ // 0x3F 0x3F 0x3F Additional AND
+
+ // Create buffer with zero-padding if there are only one or two
+ // significant bytes passed in the array.
+ // We have to shift left 24 in order to flush out the 1's that appear
+ // when Java treats a value as negative that is cast from a byte to an int.
+ final int inBuff = (numBytes > 0 ? ((src[sOffset] << 24) >>> 8) : 0)
+ | (numBytes > 1 ? ((src[sOffset + 1] << 24) >>> 16) : 0)
+ | (numBytes > 2 ? ((src[sOffset + 2] << 24) >>> 24) : 0);
+ switch (numBytes)
+ {
+ case 3:
+ dest[dOffset] = ALPHABET[(inBuff >>> 18)];
+ dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
+ dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F];
+ dest[dOffset + 3] = ALPHABET[(inBuff) & 0x3F];
+ break;
+ case 2:
+ dest[dOffset] = ALPHABET[(inBuff >>> 18)];
+ dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
+ dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F];
+ dest[dOffset + 3] = EQUALS_SIGN;
+ break;
+ case 1:
+ dest[dOffset] = ALPHABET[(inBuff >>> 18)];
+ dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
+ dest[dOffset + 2] = EQUALS_SIGN;
+ dest[dOffset + 3] = EQUALS_SIGN;
+ break;
+ }
+ return dest;
+ }
+
+ /**
+ * <p>Decodes four bytes from array <code>src</code> and writes the
+ * resulting bytes (up to three of them) to <code>dest</code>.</p>
+ *
+ * <p>The source and destination arrays can be manipulated anywhere along
+ * their length by specifying <code>sOffset</code> and <code>dOffset</code>.
+ * </p>
+ *
+ * <p>This method does not check to make sure your arrays are large enough
+ * to accomodate <code>sOffset + 4</code> for the <code>src</code> array or
+ * <code>dOffset + 3</code> for the <code>dest</code> array. This method
+ * returns the actual number of bytes that were converted from the Base64
+ * encoding.</p>
+ *
+ * @param src the array to convert.
+ * @param sOffset the index where conversion begins.
+ * @param dest the array to hold the conversion.
+ * @param dOffset the index where output will be put.
+ * @return the number of decoded bytes converted.
+ */
+ private static final int decode4to3(final byte[] src, final int sOffset,
+ final byte[] dest, final int dOffset)
+ {
+ if (src[sOffset + 2] == EQUALS_SIGN)
+ { // Example: Dk==
+ final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
+ | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12);
+ dest[dOffset] = (byte) (outBuff >>> 16);
+ return 1;
+ }
+
+ if (src[sOffset + 3] == EQUALS_SIGN)
+ { // Example: DkL=
+ final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
+ | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
+ | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6);
+ dest[dOffset] = (byte) (outBuff >>> 16);
+ dest[dOffset + 1] = (byte) (outBuff >>> 8);
+ return 2;
+ }
+
+ try
+ { // Example: DkLE
+ final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
+ | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
+ | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6)
+ | ((DECODABET[src[sOffset + 3]] & 0xFF));
+ dest[dOffset] = (byte) (outBuff >> 16);
+ dest[dOffset + 1] = (byte) (outBuff >> 8);
+ dest[dOffset + 2] = (byte) outBuff;
+ return 3;
+ }
+ catch (Exception x)
+ {
+ if (DEBUG && debuglevel > 8)
+ {
+ debug("" + src[sOffset] + ": " + (DECODABET[src[sOffset]]));
+ debug("" + src[sOffset + 1] + ": " + (DECODABET[src[sOffset + 1]]));
+ debug("" + src[sOffset + 2] + ": " + (DECODABET[src[sOffset + 2]]));
+ debug("" + src[sOffset + 3] + ": " + (DECODABET[src[sOffset + 3]]));
+ }
+ return -1;
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/DerUtil.java b/libjava/classpath/gnu/java/security/util/DerUtil.java
new file mode 100644
index 00000000000..26232ba9843
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/DerUtil.java
@@ -0,0 +1,64 @@
+/* DerUtil.java -- Utility methods for DER read/write operations
+ 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.java.security.util;
+
+import gnu.java.security.der.DEREncodingException;
+import gnu.java.security.der.DERValue;
+
+import java.math.BigInteger;
+
+/**
+ * Utility methods for DER encoding handling.
+ */
+public abstract class DerUtil
+{
+ public static final void checkIsConstructed(DERValue v, String msg)
+ throws DEREncodingException
+ {
+ if (! v.isConstructed())
+ throw new DEREncodingException(msg);
+ }
+
+ public static final void checkIsBigInteger(DERValue v, String msg)
+ throws DEREncodingException
+ {
+ if (! (v.getValue() instanceof BigInteger))
+ throw new DEREncodingException(msg);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/ExpirableObject.java b/libjava/classpath/gnu/java/security/util/ExpirableObject.java
new file mode 100644
index 00000000000..2d4452015af
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/ExpirableObject.java
@@ -0,0 +1,172 @@
+/* ExpirableObject.java -- an object that is automatically destroyed.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.security.auth.DestroyFailedException;
+import javax.security.auth.Destroyable;
+
+/**
+ * The base class for objects with sensitive data that are automatically
+ * destroyed after a timeout elapses. On creation, an object that extends
+ * this class will automatically be added to a {@link Timer} object that,
+ * once a timeout elapses, will automatically call the {@link
+ * Destroyable#destroy()} method.
+ *
+ * <p>Concrete subclasses must implement the {@link doDestroy()} method
+ * instead of {@link Destroyable#destroy()}; the behavior of that method
+ * should match exactly the behavior desired of <code>destroy()</code>.
+ *
+ * <p>Note that if a {@link DestroyFailedException} occurs when the timeout
+ * expires, it will not be reported.
+ *
+ * @see Destroyable
+ */
+public abstract class ExpirableObject implements Destroyable
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The default timeout, used in the default constructor.
+ */
+ public static final long DEFAULT_TIMEOUT = 3600000L;
+
+ /**
+ * The timer that expires instances.
+ */
+ private static final Timer EXPIRER = new Timer(true);
+
+ /**
+ * A reference to the task that will destroy this object when the timeout
+ * expires.
+ */
+ private final Destroyer destroyer;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Create a new expirable object that will expire after one hour.
+ */
+ protected ExpirableObject()
+ {
+ this(DEFAULT_TIMEOUT);
+ }
+
+ /**
+ * Create a new expirable object that will expire after the specified
+ * timeout.
+ *
+ * @param delay The delay before expiration.
+ * @throws IllegalArgumentException If <i>delay</i> is negative, or if
+ * <code>delay + System.currentTimeMillis()</code> is negative.
+ */
+ protected ExpirableObject(final long delay)
+ {
+ destroyer = new Destroyer(this);
+ EXPIRER.schedule(destroyer, delay);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Destroys this object. This method calls {@link doDestroy}, then, if
+ * no exception is thrown, cancels the task that would destroy this object
+ * when the timeout is reached.
+ *
+ * @throws DestroyFailedException If this operation fails.
+ */
+ public final void destroy() throws DestroyFailedException
+ {
+ doDestroy();
+ destroyer.cancel();
+ }
+
+ /**
+ * Subclasses must implement this method instead of the {@link
+ * Destroyable#destroy()} method.
+ *
+ * @throws DestroyFailedException If this operation fails.
+ */
+ protected abstract void doDestroy() throws DestroyFailedException;
+
+ // Inner classes.
+ // -------------------------------------------------------------------------
+
+ /**
+ * The task that destroys the target when the timeout elapses.
+ */
+ private final class Destroyer extends TimerTask
+ {
+
+ // Fields.
+ // -----------------------------------------------------------------------
+
+ private final ExpirableObject target;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ Destroyer(final ExpirableObject target)
+ {
+ super();
+ this.target = target;
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public void run()
+ {
+ try
+ {
+ if (!target.isDestroyed())
+ target.doDestroy();
+ }
+ catch (DestroyFailedException dfe)
+ {
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/FormatUtil.java b/libjava/classpath/gnu/java/security/util/FormatUtil.java
new file mode 100644
index 00000000000..eed669cc3a4
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/FormatUtil.java
@@ -0,0 +1,140 @@
+/* FormatUtil.java -- Encoding and decoding format utility methods
+ 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.java.security.util;
+
+import gnu.java.security.Registry;
+
+/**
+ * Encoding and decoding format utility methods.
+ */
+public class FormatUtil
+{
+ /** Trivial constructor to enforce Singleton pattern. */
+ private FormatUtil()
+ {
+ super();
+ }
+
+ /**
+ * Returns the fully qualified name of the designated encoding ID.
+ *
+ * @param formatID the unique identifier of the encoding format.
+ * @return the fully qualified name of the designated format. Returns
+ * <code>null</code> if no such encoding format is known.
+ */
+ public static final String getEncodingName(int formatID)
+ {
+ String result = null;
+ switch (formatID)
+ {
+ case Registry.RAW_ENCODING_ID:
+ result = Registry.RAW_ENCODING;
+ break;
+ case Registry.X509_ENCODING_ID:
+ result = Registry.X509_ENCODING;
+ break;
+ case Registry.PKCS8_ENCODING_ID:
+ result = Registry.PKCS8_ENCODING;
+ break;
+ case Registry.ASN1_ENCODING_ID:
+ result = Registry.ASN1_ENCODING;
+ break;
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the short name of the designated encoding ID. This is used by the
+ * JCE Adapters.
+ *
+ * @param formatID the unique identifier of the encoding format.
+ * @return the short name of the designated format. Returns <code>null</code>
+ * if no such encoding format is known.
+ */
+ public static final String getEncodingShortName(int formatID)
+ {
+ String result = null;
+ switch (formatID)
+ {
+ case Registry.RAW_ENCODING_ID:
+ result = Registry.RAW_ENCODING_SHORT_NAME;
+ break;
+ case Registry.X509_ENCODING_ID:
+ result = Registry.X509_ENCODING_SORT_NAME;
+ break;
+ case Registry.PKCS8_ENCODING_ID:
+ result = Registry.PKCS8_ENCODING_SHORT_NAME;
+ break;
+ case Registry.ASN1_ENCODING_ID:
+ result = Registry.ASN1_ENCODING_SHORT_NAME;
+ break;
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the identifier of the encoding format given its short name.
+ *
+ * @param name the case-insensitive canonical short name of an encoding
+ * format.
+ * @return the identifier of the designated encoding format, or <code>0</code>
+ * if the name does not correspond to any known format.
+ */
+ public static final int getFormatID(String name)
+ {
+ if (name == null)
+ return 0;
+
+ name = name.trim();
+ if (name.length() == 0)
+ return 0;
+
+ int result = 0;
+ if (name.equalsIgnoreCase(Registry.RAW_ENCODING_SHORT_NAME))
+ result = Registry.RAW_ENCODING_ID;
+ else if (name.equalsIgnoreCase(Registry.X509_ENCODING_SORT_NAME))
+ result = Registry.X509_ENCODING_ID;
+ else if (name.equalsIgnoreCase(Registry.PKCS8_ENCODING_SHORT_NAME))
+ result = Registry.PKCS8_ENCODING_ID;
+
+ return result;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/PRNG.java b/libjava/classpath/gnu/java/security/util/PRNG.java
new file mode 100644
index 00000000000..138cc6bcb0c
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/PRNG.java
@@ -0,0 +1,156 @@
+/* PRNG.java -- A Utility methods for default source of randomness
+ 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.java.security.util;
+
+import java.util.HashMap;
+
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.prng.MDGenerator;
+
+/**
+ * A useful hash-based (SHA) pseudo-random number generator used
+ * throughout this library.
+ *
+ * @see MDGenerator
+ */
+public class PRNG
+{
+ // Constans and fields
+ // --------------------------------------------------------------------------
+
+ /** The underlying {@link IRandom}. */
+ private IRandom delegate;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /**
+ * Private constructor to enforce using the Factory method.
+ *
+ * @param delegate
+ * the undelying {@link IRandom} object used.
+ */
+ private PRNG(IRandom delegate)
+ {
+ super();
+
+ this.delegate = delegate;
+ }
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ public static final PRNG getInstance()
+ {
+ IRandom delegate = new MDGenerator();
+ try
+ {
+ HashMap map = new HashMap();
+ // initialise it with a seed
+ long t = System.currentTimeMillis();
+ byte[] seed = new byte[] {
+ (byte) (t >>> 56), (byte) (t >>> 48),
+ (byte) (t >>> 40), (byte) (t >>> 32),
+ (byte) (t >>> 24), (byte) (t >>> 16),
+ (byte) (t >>> 8), (byte) t};
+ map.put(MDGenerator.SEEED, seed);
+ delegate.init(map); // default is to use SHA-1 hash
+ }
+ catch (Exception x)
+ {
+ throw new ExceptionInInitializerError(x);
+ }
+
+ return new PRNG(delegate);
+ }
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ /**
+ * Completely fills the designated <code>buffer</code> with random data
+ * generated by the underlying delegate.
+ *
+ * @param buffer
+ * the place holder of random bytes generated by the underlying
+ * delegate. On output, the contents of <code>buffer</code> are
+ * replaced with pseudo-random data, iff the <code>buffer</code>
+ * size is not zero.
+ */
+ public void nextBytes(byte[] buffer)
+ {
+ nextBytes(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Fills the designated <code>buffer</code>, starting from byte at position
+ * <code>offset</code> with, at most, <code>length</code> bytes of random
+ * data generated by the underlying delegate.
+ *
+ * @see IRandom#nextBytes
+ */
+ public void nextBytes(byte[] buffer, int offset, int length)
+ {
+ try
+ {
+ delegate.nextBytes(buffer, offset, length);
+ }
+ catch (LimitReachedException x) // re-initialise with a seed
+ {
+ try
+ {
+ HashMap map = new HashMap();
+ long t = System.currentTimeMillis();
+ byte[] seed = new byte[] {
+ (byte)(t >>> 56), (byte)(t >>> 48),
+ (byte)(t >>> 40), (byte)(t >>> 32),
+ (byte)(t >>> 24), (byte)(t >>> 16),
+ (byte)(t >>> 8), (byte) t };
+ map.put(MDGenerator.SEEED, seed);
+ delegate.init(map); // default is to use SHA-1 hash
+ delegate.nextBytes(buffer, offset, length);
+ }
+ catch (Exception y)
+ {
+ throw new ExceptionInInitializerError(y);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/Prime2.java b/libjava/classpath/gnu/java/security/util/Prime2.java
new file mode 100644
index 00000000000..6e46f5fcadc
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/Prime2.java
@@ -0,0 +1,417 @@
+/* Prime2.java --
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * <p>A collection of prime number related utilities used in this library.</p>
+ */
+public class Prime2
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "prime";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ private static final int DEFAULT_CERTAINTY = 20; // XXX is this a good value?
+
+ private static final BigInteger ZERO = BigInteger.ZERO;
+
+ private static final BigInteger ONE = BigInteger.ONE;
+
+ private static final BigInteger TWO = BigInteger.valueOf(2L);
+
+ /**
+ * The first SMALL_PRIME primes: Algorithm P, section 1.3.2, The Art of
+ * Computer Programming, Donald E. Knuth.
+ */
+ private static final int SMALL_PRIME_COUNT = 1000;
+
+ private static final BigInteger[] SMALL_PRIME = new BigInteger[SMALL_PRIME_COUNT];
+ static
+ {
+ long time = -System.currentTimeMillis();
+ SMALL_PRIME[0] = TWO;
+ int N = 3;
+ int J = 0;
+ int prime;
+ P2: while (true)
+ {
+ SMALL_PRIME[++J] = BigInteger.valueOf(N);
+ if (J >= 999)
+ {
+ break P2;
+ }
+ P4: while (true)
+ {
+ N += 2;
+ P6: for (int K = 1; true; K++)
+ {
+ prime = SMALL_PRIME[K].intValue();
+ if ((N % prime) == 0)
+ {
+ continue P4;
+ }
+ else if ((N / prime) <= prime)
+ {
+ continue P2;
+ }
+ }
+ }
+ }
+ time += System.currentTimeMillis();
+ if (DEBUG && debuglevel > 8)
+ {
+ StringBuffer sb;
+ for (int i = 0; i < (SMALL_PRIME_COUNT / 10); i++)
+ {
+ sb = new StringBuffer();
+ for (int j = 0; j < 10; j++)
+ {
+ sb.append(String.valueOf(SMALL_PRIME[i * 10 + j])).append(" ");
+ }
+ debug(sb.toString());
+ }
+ }
+ if (DEBUG && debuglevel > 4)
+ {
+ debug("Generating first " + String.valueOf(SMALL_PRIME_COUNT)
+ + " primes took: " + String.valueOf(time) + " ms.");
+ }
+ }
+
+ private static final Map knownPrimes = new WeakHashMap();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private Prime2()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Trial division for the first 1000 small primes.</p>
+ *
+ * <p>Returns <code>true</code> if at least one small prime, among the first
+ * 1000 ones, was found to divide the designated number. Retuens <code>false</code>
+ * otherwise.</p>
+ *
+ * @param w the number to test.
+ * @return <code>true</code> if at least one small prime was found to divide
+ * the designated number.
+ */
+ public static boolean hasSmallPrimeDivisor(BigInteger w)
+ {
+ BigInteger prime;
+ for (int i = 0; i < SMALL_PRIME_COUNT; i++)
+ {
+ prime = SMALL_PRIME[i];
+ if (w.mod(prime).equals(ZERO))
+ {
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(prime.toString(16) + " | " + w.toString(16) + "...");
+ }
+ return true;
+ }
+ }
+ if (DEBUG && debuglevel > 4)
+ {
+ debug(w.toString(16) + " has no small prime divisors...");
+ }
+ return false;
+ }
+
+ /**
+ * <p>Java port of Colin Plumb primality test (Euler Criterion)
+ * implementation for a base of 2 --from bnlib-1.1 release, function
+ * primeTest() in prime.c. this is his comments.</p>
+ *
+ * <p>"Now, check that bn is prime. If it passes to the base 2, it's prime
+ * beyond all reasonable doubt, and everything else is just gravy, but it
+ * gives people warm fuzzies to do it.</p>
+ *
+ * <p>This starts with verifying Euler's criterion for a base of 2. This is
+ * the fastest pseudoprimality test that I know of, saving a modular squaring
+ * over a Fermat test, as well as being stronger. 7/8 of the time, it's as
+ * strong as a strong pseudoprimality test, too. (The exception being when
+ * <code>bn == 1 mod 8</code> and <code>2</code> is a quartic residue, i.e.
+ * <code>bn</code> is of the form <code>a^2 + (8*b)^2</code>.) The precise
+ * series of tricks used here is not documented anywhere, so here's an
+ * explanation. Euler's criterion states that if <code>p</code> is prime
+ * then <code>a^((p-1)/2)</code> is congruent to <code>Jacobi(a,p)</code>,
+ * modulo <code>p</code>. <code>Jacobi(a, p)</code> is a function which is
+ * <code>+1</code> if a is a square modulo <code>p</code>, and <code>-1</code>
+ * if it is not. For <code>a = 2</code>, this is particularly simple. It's
+ * <code>+1</code> if <code>p == +/-1 (mod 8)</code>, and <code>-1</code> if
+ * <code>m == +/-3 (mod 8)</code>. If <code>p == 3 (mod 4)</code>, then all
+ * a strong test does is compute <code>2^((p-1)/2)</code>. and see if it's
+ * <code>+1</code> or <code>-1</code>. (Euler's criterion says <i>which</i>
+ * it should be.) If <code>p == 5 (mod 8)</code>, then <code>2^((p-1)/2)</code>
+ * is <code>-1</code>, so the initial step in a strong test, looking at
+ * <code>2^((p-1)/4)</code>, is wasted --you're not going to find a
+ * <code>+/-1</code> before then if it <b>is</b> prime, and it shouldn't
+ * have either of those values if it isn't. So don't bother.</p>
+ *
+ * <p>The remaining case is <code>p == 1 (mod 8)</code>. In this case, we
+ * expect <code>2^((p-1)/2) == 1 (mod p)</code>, so we expect that the
+ * square root of this, <code>2^((p-1)/4)</code>, will be <code>+/-1 (mod p)
+ * </code>. Evaluating this saves us a modular squaring 1/4 of the time. If
+ * it's <code>-1</code>, a strong pseudoprimality test would call <code>p</code>
+ * prime as well. Only if the result is <code>+1</code>, indicating that
+ * <code>2</code> is not only a quadratic residue, but a quartic one as well,
+ * does a strong pseudoprimality test verify more things than this test does.
+ * Good enough.</p>
+ *
+ * <p>We could back that down another step, looking at <code>2^((p-1)/8)</code>
+ * if there was a cheap way to determine if <code>2</code> were expected to
+ * be a quartic residue or not. Dirichlet proved that <code>2</code> is a
+ * quadratic residue iff <code>p</code> is of the form <code>a^2 + (8*b^2)</code>.
+ * All primes <code>== 1 (mod 4)</code> can be expressed as <code>a^2 +
+ * (2*b)^2</code>, but I see no cheap way to evaluate this condition."</p>
+ *
+ * @param bn the number to test.
+ * @return <code>true</code> iff the designated number passes Euler criterion
+ * as implemented by Colin Plumb in his <i>bnlib</i> version 1.1.
+ */
+ public static boolean passEulerCriterion(final BigInteger bn)
+ {
+ BigInteger bn_minus_one = bn.subtract(ONE);
+ BigInteger e = bn_minus_one;
+ // l is the 3 least-significant bits of e
+ int l = e.and(BigInteger.valueOf(7L)).intValue();
+ int j = 1; // Where to start in prime array for strong prime tests
+ BigInteger a;
+ int k;
+
+ if (l != 0)
+ {
+ e = e.shiftRight(1);
+ a = TWO.modPow(e, bn);
+ if (l == 6) // bn == 7 mod 8, expect +1
+ {
+ if (a.bitLength() != 1)
+ {
+ debugBI("Fails Euler criterion #1", bn);
+ return false; // Not prime
+ }
+ k = 1;
+ }
+ else // bn == 3 or 5 mod 8, expect -1 == bn-1
+ {
+ a = a.add(ONE);
+ if (a.compareTo(bn) != 0)
+ {
+ debugBI("Fails Euler criterion #2", bn);
+ return false; // Not prime
+ }
+ k = 1;
+ if ((l & 4) != 0) // bn == 5 mod 8, make odd for strong tests
+ {
+ e = e.shiftRight(1);
+ k = 2;
+ }
+ }
+ }
+ else // bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn
+ {
+ e = e.shiftRight(2);
+ a = TWO.modPow(e, bn);
+ if (a.bitLength() == 1)
+ j = 0; // Re-do strong prime test to base 2
+ else
+ {
+ a = a.add(ONE);
+ if (a.compareTo(bn) != 0)
+ {
+ debugBI("Fails Euler criterion #3", bn);
+ return false; // Not prime
+ }
+ }
+ // bnMakeOdd(n) = d * 2^s. Replaces n with d and returns s.
+ k = e.getLowestSetBit();
+ e = e.shiftRight(k);
+ k += 2;
+ }
+ // It's prime! Now go on to confirmation tests
+
+ // Now, e = (bn-1)/2^k is odd. k >= 1, and has a given value with
+ // probability 2^-k, so its expected value is 2. j = 1 in the usual case
+ // when the previous test was as good as a strong prime test, but 1/8 of
+ // the time, j = 0 because the strong prime test to the base 2 needs to
+ // be re-done.
+ for (int i = j; i < 7; i++) // try only the first 7 primes
+ {
+ a = SMALL_PRIME[i];
+ a = a.modPow(e, bn);
+ if (a.bitLength() == 1)
+ continue; // Passed this test
+
+ l = k;
+ while (true)
+ {
+// a = a.add(ONE);
+// if (a.compareTo(w) == 0) { // Was result bn-1?
+ if (a.compareTo(bn_minus_one) == 0) // Was result bn-1?
+ break; // Prime
+
+ if (--l == 0) // Reached end, not -1? luck?
+ {
+ debugBI("Fails Euler criterion #4", bn);
+ return false; // Failed, not prime
+ }
+ // This portion is executed, on average, once
+// a = a.subtract(ONE); // Put a back where it was
+ a = a.modPow(TWO, bn);
+ if (a.bitLength() == 1)
+ {
+ debugBI("Fails Euler criterion #5", bn);
+ return false; // Failed, not prime
+ }
+ }
+ // It worked (to the base primes[i])
+ }
+ debugBI("Passes Euler criterion", bn);
+ return true;
+ }
+
+ public static boolean isProbablePrime(BigInteger w)
+ {
+ return isProbablePrime(w, DEFAULT_CERTAINTY);
+ }
+
+ /**
+ * Wrapper around {@link BigInteger#isProbablePrime(int)} with few pre-checks.
+ *
+ * @param w the integer to test.
+ * @param certainty the certainty with which to compute the test.
+ */
+ public static boolean isProbablePrime(BigInteger w, int certainty)
+ {
+ // Nonnumbers are not prime.
+ if (w == null)
+ return false;
+
+ // eliminate trivial cases when w == 0 or 1
+ if (w.equals(ZERO) || w.equals(ONE))
+ return false;
+
+ // Test if w is a known small prime.
+ for (int i = 0; i < SMALL_PRIME_COUNT; i++)
+ if (w.equals(SMALL_PRIME[i]))
+ {
+ if (DEBUG && debuglevel > 4)
+ debug(w.toString(16) + " is a small prime");
+ return true;
+ }
+
+ // Check if it's already a known prime
+ WeakReference obj = (WeakReference) knownPrimes.get(w);
+ if (obj != null && w.equals(obj.get()))
+ {
+ if (DEBUG && debuglevel > 4)
+ debug("found in known primes");
+ return true;
+ }
+
+ // trial division with first 1000 primes
+ if (hasSmallPrimeDivisor(w))
+ {
+ if (DEBUG && debuglevel > 4)
+ debug(w.toString(16) + " has a small prime divisor. Rejected...");
+ return false;
+ }
+
+// Euler's criterion.
+// if (passEulerCriterion(w)) {
+// if (DEBUG && debuglevel > 4) {
+// debug(w.toString(16)+" passes Euler's criterion...");
+// }
+// } else {
+// if (DEBUG && debuglevel > 4) {
+// debug(w.toString(16)+" fails Euler's criterion. Rejected...");
+// }
+// return false;
+// }
+//
+// if (DEBUG && debuglevel > 4)
+// {
+// debug(w.toString(16) + " is probable prime. Accepted...");
+// }
+
+ boolean result = w.isProbablePrime(certainty);
+ if (result && certainty > 0) // store it in the known primes weak hash-map
+ knownPrimes.put(w, new WeakReference(w));
+
+ return result;
+ }
+
+ // helper methods -----------------------------------------------------------
+
+ private static final void debugBI(String msg, BigInteger bn)
+ {
+ if (DEBUG && debuglevel > 4)
+ debug("*** " + msg + ": 0x" + bn.toString(16));
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/Sequence.java b/libjava/classpath/gnu/java/security/util/Sequence.java
new file mode 100644
index 00000000000..5edc7942ef9
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/Sequence.java
@@ -0,0 +1,149 @@
+/* Sequence.java -- a sequence of integers.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.util.AbstractList;
+import java.util.LinkedList;
+
+/**
+ * A monotonic sequence of integers in the finite field 2<sup>32</sup>.
+ */
+public final class Sequence extends AbstractList
+{
+
+ // Field.
+ // ------------------------------------------------------------------------
+
+ private final Integer[] sequence;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a sequence of integers from 0 to <i>end</i>, with an increment
+ * of 1. If <i>end</i> is less than 0, then the sequence will wrap around
+ * through all positive integers then negative integers until the end
+ * value is reached. Naturally, this will result in an enormous object,
+ * so don't do this.
+ *
+ * @param end The ending value.
+ */
+ public Sequence(int end)
+ {
+ this(0, end, 1);
+ }
+
+ /**
+ * Create a sequence of integers from <i>start</i> to <i>end</i>, with an
+ * increment of 1. If <i>end</i> is less than <i>start</i>, then the sequence
+ * will wrap around until the end value is reached. Naturally, this will
+ * result in an enormous object, so don't do this.
+ *
+ * @param start The starting value.
+ * @param end The ending value.
+ */
+ public Sequence(int start, int end)
+ {
+ this(start, end, 1);
+ }
+
+ /**
+ * Create a sequence of integers from <i>start</i> to <i>end</i>, with an
+ * increment of <i>span</i>. If <i>end</i> is less than <i>start</i>, then
+ * the sequence will wrap around until the end value is reached. Naturally,
+ * this will result in an enormous object, so don't do this.
+ *
+ * <p><i>span</i> can be negative, resulting in a decresing sequence.
+ *
+ * <p>If <i>span</i> is 0, then the sequence will contain {<i>start</i>,
+ * <i>end</i>} if <i>start</i> != <i>end</i>, or just the singleton
+ * <i>start</i> if <i>start</i> == <i>end</i>.
+ *
+ * @param start The starting value.
+ * @param end The ending value.
+ * @param span The increment value.
+ */
+ public Sequence(int start, int end, int span)
+ {
+ if (span == 0)
+ {
+ if (start != end)
+ {
+ sequence = new Integer[] { new Integer(start), new Integer(end) };
+ }
+ else
+ {
+ sequence = new Integer[] { new Integer(start) };
+ }
+ }
+ else
+ {
+ LinkedList l = new LinkedList();
+ for (int i = start; i != end; i += span)
+ {
+ l.add(new Integer(i));
+ }
+ l.add(new Integer(end));
+ sequence = (Integer[]) l.toArray(new Integer[l.size()]);
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public Object get(int index)
+ {
+ if (index < 0 || index >= size())
+ {
+ throw new IndexOutOfBoundsException("index=" + index + ", size="
+ + size());
+ }
+ return sequence[index];
+ }
+
+ public int size()
+ {
+ return sequence.length;
+ }
+
+ public Object[] toArray()
+ {
+ return (Object[]) sequence.clone();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/SimpleList.java b/libjava/classpath/gnu/java/security/util/SimpleList.java
new file mode 100644
index 00000000000..b2525c4b8e2
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/SimpleList.java
@@ -0,0 +1,171 @@
+/* SimpleList.java -- simple way to make tuples.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A simple way to create immutable n-tuples. This class can be created with
+ * up to four elements specified via one of the constructors, or with a
+ * collection of arbitrary size.
+ */
+public final class SimpleList extends AbstractList
+{
+
+ // Fields.
+ // ------------------------------------------------------------------------
+
+ private final Object[] elements;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a singleton list.
+ *
+ * @param e1 The first element.
+ */
+ public SimpleList(final Object element)
+ {
+ elements = new Object[1];
+ elements[0] = element;
+ }
+
+ /**
+ * Create an ordered pair (2-tuple).
+ *
+ * @param e1 The first element.
+ * @param e2 The second element.
+ */
+ public SimpleList(final Object e1, final Object e2)
+ {
+ elements = new Object[2];
+ elements[0] = e1;
+ elements[1] = e2;
+ }
+
+ /**
+ * Create a 3-tuple.
+ *
+ * @param e1 The first element.
+ * @param e2 The second element.
+ * @param e3 The third element.
+ */
+ public SimpleList(final Object e1, final Object e2, final Object e3)
+ {
+ elements = new Object[3];
+ elements[0] = e1;
+ elements[1] = e2;
+ elements[2] = e3;
+ }
+
+ /**
+ * Create a 4-tuple.
+ *
+ * @param e1 The first element.
+ * @param e2 The second element.
+ * @param e3 The third element.
+ * @param e4 The fourth element.
+ */
+ public SimpleList(final Object e1, final Object e2, final Object e3,
+ final Object e4)
+ {
+ elements = new Object[4];
+ elements[0] = e1;
+ elements[1] = e2;
+ elements[2] = e3;
+ elements[3] = e4;
+ }
+
+ /**
+ * Create the empty list.
+ */
+ public SimpleList()
+ {
+ elements = null;
+ }
+
+ /**
+ * Create an n-tuple of arbitrary size. Even if the supplied collection has
+ * no natural order, the created n-tuple will have the order that the
+ * elements are returned by the collection's iterator.
+ *
+ * @param c The collection.
+ */
+ public SimpleList(Collection c)
+ {
+ elements = new Object[c.size()];
+ int i = 0;
+ for (Iterator it = c.iterator(); it.hasNext() && i < elements.length;)
+ {
+ elements[i++] = it.next();
+ }
+ }
+
+ // Instance methods.
+ // ------------------------------------------------------------------------
+
+ public int size()
+ {
+ if (elements == null)
+ return 0;
+ return elements.length;
+ }
+
+ public Object get(int index)
+ {
+ if (elements == null)
+ {
+ throw new IndexOutOfBoundsException("list is empty");
+ }
+ if (index < 0 || index >= elements.length)
+ {
+ throw new IndexOutOfBoundsException("index=" + index + ", size="
+ + size());
+ }
+ return elements[index];
+ }
+
+ public String toString()
+ {
+ return SimpleList.class.getName() + "(" + size() + ") " + super.toString();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/util/Util.java b/libjava/classpath/gnu/java/security/util/Util.java
new file mode 100644
index 00000000000..53f8e3c2cca
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/util/Util.java
@@ -0,0 +1,692 @@
+/* Util.java -- various utility routines.
+ Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.math.BigInteger;
+
+/**
+ * <p>A collection of utility methods used throughout this project.</p>
+ *
+ * @version $Revision: 1.1 $
+ */
+public class Util
+{
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ // Hex charset
+ private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
+
+ // Base-64 charset
+ private static final String BASE64_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
+
+ private static final char[] BASE64_CHARSET = BASE64_CHARS.toCharArray();
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private Util()
+ {
+ super();
+ }
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * <p>Returns a string of hexadecimal digits from a byte array. Each byte is
+ * converted to 2 hex symbols; zero(es) included.</p>
+ *
+ * <p>This method calls the method with same name and three arguments as:</p>
+ *
+ * <pre>
+ * toString(ba, 0, ba.length);
+ * </pre>
+ *
+ * @param ba the byte array to convert.
+ * @return a string of hexadecimal characters (two for each byte)
+ * representing the designated input byte array.
+ */
+ public static String toString(byte[] ba)
+ {
+ return toString(ba, 0, ba.length);
+ }
+
+ /**
+ * <p>Returns a string of hexadecimal digits from a byte array, starting at
+ * <code>offset</code> and consisting of <code>length</code> bytes. Each byte
+ * is converted to 2 hex symbols; zero(es) included.</p>
+ *
+ * @param ba the byte array to convert.
+ * @param offset the index from which to start considering the bytes to
+ * convert.
+ * @param length the count of bytes, starting from the designated offset to
+ * convert.
+ * @return a string of hexadecimal characters (two for each byte)
+ * representing the designated input byte sub-array.
+ */
+ public static final String toString(byte[] ba, int offset, int length)
+ {
+ char[] buf = new char[length * 2];
+ for (int i = 0, j = 0, k; i < length;)
+ {
+ k = ba[offset + i++];
+ buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
+ buf[j++] = HEX_DIGITS[k & 0x0F];
+ }
+ return new String(buf);
+ }
+
+ /**
+ * <p>Returns a string of hexadecimal digits from a byte array. Each byte is
+ * converted to 2 hex symbols; zero(es) included. The argument is
+ * treated as a large little-endian integer and is returned as a
+ * large big-endian integer.</p>
+ *
+ * <p>This method calls the method with same name and three arguments as:</p>
+ *
+ * <pre>
+ * toReversedString(ba, 0, ba.length);
+ * </pre>
+ *
+ * @param ba the byte array to convert.
+ * @return a string of hexadecimal characters (two for each byte)
+ * representing the designated input byte array.
+ */
+ public static String toReversedString(byte[] ba)
+ {
+ return toReversedString(ba, 0, ba.length);
+ }
+
+ /**
+ * <p>Returns a string of hexadecimal digits from a byte array, starting at
+ * <code>offset</code> and consisting of <code>length</code> bytes. Each byte
+ * is converted to 2 hex symbols; zero(es) included.</p>
+ *
+ * <p>The byte array is treated as a large little-endian integer, and
+ * is returned as a large big-endian integer.</p>
+ *
+ * @param ba the byte array to convert.
+ * @param offset the index from which to start considering the bytes to
+ * convert.
+ * @param length the count of bytes, starting from the designated offset to
+ * convert.
+ * @return a string of hexadecimal characters (two for each byte)
+ * representing the designated input byte sub-array.
+ */
+ public static final String toReversedString(byte[] ba, int offset, int length)
+ {
+ char[] buf = new char[length * 2];
+ for (int i = offset + length - 1, j = 0, k; i >= offset;)
+ {
+ k = ba[offset + i--];
+ buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
+ buf[j++] = HEX_DIGITS[k & 0x0F];
+ }
+ return new String(buf);
+ }
+
+ /**
+ * <p>Returns a byte array from a string of hexadecimal digits.</p>
+ *
+ * @param s a string of hexadecimal ASCII characters
+ * @return the decoded byte array from the input hexadecimal string.
+ */
+ public static byte[] toBytesFromString(String s)
+ {
+ int limit = s.length();
+ byte[] result = new byte[((limit + 1) / 2)];
+ int i = 0, j = 0;
+ if ((limit % 2) == 1)
+ {
+ result[j++] = (byte) fromDigit(s.charAt(i++));
+ }
+ while (i < limit)
+ {
+ result[j] = (byte) (fromDigit(s.charAt(i++)) << 4);
+ result[j++] |= (byte) fromDigit(s.charAt(i++));
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns a byte array from a string of hexadecimal digits, interpreting
+ * them as a large big-endian integer and returning it as a large
+ * little-endian integer.</p>
+ *
+ * @param s a string of hexadecimal ASCII characters
+ * @return the decoded byte array from the input hexadecimal string.
+ */
+ public static byte[] toReversedBytesFromString(String s)
+ {
+ int limit = s.length();
+ byte[] result = new byte[((limit + 1) / 2)];
+ int i = 0;
+ if ((limit % 2) == 1)
+ {
+ result[i++] = (byte) fromDigit(s.charAt(--limit));
+ }
+ while (limit > 0)
+ {
+ result[i] = (byte) fromDigit(s.charAt(--limit));
+ result[i++] |= (byte) (fromDigit(s.charAt(--limit)) << 4);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Returns a number from <code>0</code> to <code>15</code> corresponding
+ * to the designated hexadecimal digit.</p>
+ *
+ * @param c a hexadecimal ASCII symbol.
+ */
+ public static int fromDigit(char c)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ return c - '0';
+ }
+ else if (c >= 'A' && c <= 'F')
+ {
+ return c - 'A' + 10;
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ return c - 'a' + 10;
+ }
+ else
+ throw new IllegalArgumentException("Invalid hexadecimal digit: " + c);
+ }
+
+ /**
+ * <p>Returns a string of 8 hexadecimal digits (most significant digit first)
+ * corresponding to the unsigned integer <code>n</code>.</p>
+ *
+ * @param n the unsigned integer to convert.
+ * @return a hexadecimal string 8-character long.
+ */
+ public static String toString(int n)
+ {
+ char[] buf = new char[8];
+ for (int i = 7; i >= 0; i--)
+ {
+ buf[i] = HEX_DIGITS[n & 0x0F];
+ n >>>= 4;
+ }
+ return new String(buf);
+ }
+
+ /**
+ * <p>Returns a string of hexadecimal digits from an integer array. Each int
+ * is converted to 4 hex symbols.</p>
+ */
+ public static String toString(int[] ia)
+ {
+ int length = ia.length;
+ char[] buf = new char[length * 8];
+ for (int i = 0, j = 0, k; i < length; i++)
+ {
+ k = ia[i];
+ buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 8) & 0x0F];
+ buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
+ buf[j++] = HEX_DIGITS[k & 0x0F];
+ }
+ return new String(buf);
+ }
+
+ /**
+ * <p>Returns a string of 16 hexadecimal digits (most significant digit first)
+ * corresponding to the unsigned long <code>n</code>.</p>
+ *
+ * @param n the unsigned long to convert.
+ * @return a hexadecimal string 16-character long.
+ */
+ public static String toString(long n)
+ {
+ char[] b = new char[16];
+ for (int i = 15; i >= 0; i--)
+ {
+ b[i] = HEX_DIGITS[(int) (n & 0x0FL)];
+ n >>>= 4;
+ }
+ return new String(b);
+ }
+
+ /**
+ * <p>Similar to the <code>toString()</code> method except that the Unicode
+ * escape character is inserted before every pair of bytes. Useful to
+ * externalise byte arrays that will be constructed later from such strings;
+ * eg. s-box values.</p>
+ *
+ * @throws ArrayIndexOutOfBoundsException if the length is odd.
+ */
+ public static String toUnicodeString(byte[] ba)
+ {
+ return toUnicodeString(ba, 0, ba.length);
+ }
+
+ /**
+ * <p>Similar to the <code>toString()</code> method except that the Unicode
+ * escape character is inserted before every pair of bytes. Useful to
+ * externalise byte arrays that will be constructed later from such strings;
+ * eg. s-box values.</p>
+ *
+ * @throws ArrayIndexOutOfBoundsException if the length is odd.
+ */
+ public static final String toUnicodeString(byte[] ba, int offset, int length)
+ {
+ StringBuffer sb = new StringBuffer();
+ int i = 0;
+ int j = 0;
+ int k;
+ sb.append('\n').append("\"");
+ while (i < length)
+ {
+ sb.append("\\u");
+
+ k = ba[offset + i++];
+ sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]);
+ sb.append(HEX_DIGITS[k & 0x0F]);
+
+ k = ba[offset + i++];
+ sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]);
+ sb.append(HEX_DIGITS[k & 0x0F]);
+
+ if ((++j % 8) == 0)
+ {
+ sb.append("\"+").append('\n').append("\"");
+ }
+ }
+ sb.append("\"").append('\n');
+ return sb.toString();
+ }
+
+ /**
+ * <p>Similar to the <code>toString()</code> method except that the Unicode
+ * escape character is inserted before every pair of bytes. Useful to
+ * externalise integer arrays that will be constructed later from such
+ * strings; eg. s-box values.</p>
+ *
+ * @throws ArrayIndexOutOfBoundsException if the length is not a multiple of 4.
+ */
+ public static String toUnicodeString(int[] ia)
+ {
+ StringBuffer sb = new StringBuffer();
+ int i = 0;
+ int j = 0;
+ int k;
+ sb.append('\n').append("\"");
+ while (i < ia.length)
+ {
+ k = ia[i++];
+ sb.append("\\u");
+ sb.append(HEX_DIGITS[(k >>> 28) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 24) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 20) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 16) & 0x0F]);
+ sb.append("\\u");
+ sb.append(HEX_DIGITS[(k >>> 12) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 8) & 0x0F]);
+ sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]);
+ sb.append(HEX_DIGITS[k & 0x0F]);
+
+ if ((++j % 4) == 0)
+ {
+ sb.append("\"+").append('\n').append("\"");
+ }
+ }
+ sb.append("\"").append('\n');
+ return sb.toString();
+ }
+
+ public static byte[] toBytesFromUnicode(String s)
+ {
+ int limit = s.length() * 2;
+ byte[] result = new byte[limit];
+ char c;
+ for (int i = 0; i < limit; i++)
+ {
+ c = s.charAt(i >>> 1);
+ result[i] = (byte) (((i & 1) == 0) ? c >>> 8 : c);
+ }
+ return result;
+ }
+
+ /**
+ * <p>Dumps a byte array as a string, in a format that is easy to read for
+ * debugging. The string <code>m</code> is prepended to the start of each
+ * line.</p>
+ *
+ * <p>If <code>offset</code> and <code>length</code> are omitted, the whole
+ * array is used. If <code>m</code> is omitted, nothing is prepended to each
+ * line.</p>
+ *
+ * @param data the byte array to be dumped.
+ * @param offset the offset within <i>data</i> to start from.
+ * @param length the number of bytes to dump.
+ * @param m a string to be prepended to each line.
+ * @return a string containing the result.
+ */
+ public static String dumpString(byte[] data, int offset, int length, String m)
+ {
+ if (data == null)
+ {
+ return m + "null\n";
+ }
+ StringBuffer sb = new StringBuffer(length * 3);
+ if (length > 32)
+ {
+ sb.append(m).append("Hexadecimal dump of ").append(length).append(
+ " bytes...\n");
+ }
+ // each line will list 32 bytes in 4 groups of 8 each
+ int end = offset + length;
+ String s;
+ int l = Integer.toString(length).length();
+ if (l < 4)
+ {
+ l = 4;
+ }
+ for (; offset < end; offset += 32)
+ {
+ if (length > 32)
+ {
+ s = " " + offset;
+ sb.append(m).append(s.substring(s.length() - l)).append(": ");
+ }
+ int i = 0;
+ for (; i < 32 && offset + i + 7 < end; i += 8)
+ {
+ sb.append(toString(data, offset + i, 8)).append(' ');
+ }
+ if (i < 32)
+ {
+ for (; i < 32 && offset + i < end; i++)
+ {
+ sb.append(byteToString(data[offset + i]));
+ }
+ }
+ sb.append('\n');
+ }
+ return sb.toString();
+ }
+
+ public static String dumpString(byte[] data)
+ {
+ return (data == null) ? "null\n" : dumpString(data, 0, data.length, "");
+ }
+
+ public static String dumpString(byte[] data, String m)
+ {
+ return (data == null) ? "null\n" : dumpString(data, 0, data.length, m);
+ }
+
+ public static String dumpString(byte[] data, int offset, int length)
+ {
+ return dumpString(data, offset, length, "");
+ }
+
+ /**
+ * <p>Returns a string of 2 hexadecimal digits (most significant digit first)
+ * corresponding to the lowest 8 bits of <code>n</code>.</p>
+ *
+ * @param n the byte value to convert.
+ * @return a string of 2 hex characters representing the input.
+ */
+ public static String byteToString(int n)
+ {
+ char[] buf = { HEX_DIGITS[(n >>> 4) & 0x0F], HEX_DIGITS[n & 0x0F] };
+ return new String(buf);
+ }
+
+ /**
+ * <p>Converts a designated byte array to a Base-64 representation, with the
+ * exceptions that (a) leading 0-byte(s) are ignored, and (b) the character
+ * '.' (dot) shall be used instead of "+' (plus).</p>
+ *
+ * <p>Used by SASL password file manipulation primitives.</p>
+ *
+ * @param buffer an arbitrary sequence of bytes to represent in Base-64.
+ * @return unpadded (without the '=' character(s)) Base-64 representation of
+ * the input.
+ */
+ public static final String toBase64(byte[] buffer)
+ {
+ int len = buffer.length, pos = len % 3;
+ byte b0 = 0, b1 = 0, b2 = 0;
+ switch (pos)
+ {
+ case 1:
+ b2 = buffer[0];
+ break;
+ case 2:
+ b1 = buffer[0];
+ b2 = buffer[1];
+ break;
+ }
+ StringBuffer sb = new StringBuffer();
+ int c;
+ boolean notleading = false;
+ do
+ {
+ c = (b0 & 0xFC) >>> 2;
+ if (notleading || c != 0)
+ {
+ sb.append(BASE64_CHARSET[c]);
+ notleading = true;
+ }
+ c = ((b0 & 0x03) << 4) | ((b1 & 0xF0) >>> 4);
+ if (notleading || c != 0)
+ {
+ sb.append(BASE64_CHARSET[c]);
+ notleading = true;
+ }
+ c = ((b1 & 0x0F) << 2) | ((b2 & 0xC0) >>> 6);
+ if (notleading || c != 0)
+ {
+ sb.append(BASE64_CHARSET[c]);
+ notleading = true;
+ }
+ c = b2 & 0x3F;
+ if (notleading || c != 0)
+ {
+ sb.append(BASE64_CHARSET[c]);
+ notleading = true;
+ }
+ if (pos >= len)
+ {
+ break;
+ }
+ else
+ {
+ try
+ {
+ b0 = buffer[pos++];
+ b1 = buffer[pos++];
+ b2 = buffer[pos++];
+ }
+ catch (ArrayIndexOutOfBoundsException x)
+ {
+ break;
+ }
+ }
+ }
+ while (true);
+
+ if (notleading)
+ {
+ return sb.toString();
+ }
+ return "0";
+ }
+
+ /**
+ * <p>The inverse function of the above.</p>
+ *
+ * <p>Converts a string representing the encoding of some bytes in Base-64
+ * to their original form.</p>
+ *
+ * @param str the Base-64 encoded representation of some byte(s).
+ * @return the bytes represented by the <code>str</code>.
+ * @throws NumberFormatException if <code>str</code> is <code>null</code>, or
+ * <code>str</code> contains an illegal Base-64 character.
+ * @see #toBase64(byte[])
+ */
+ public static final byte[] fromBase64(String str)
+ {
+ int len = str.length();
+ if (len == 0)
+ {
+ throw new NumberFormatException("Empty string");
+ }
+ byte[] a = new byte[len + 1];
+ int i, j;
+ for (i = 0; i < len; i++)
+ {
+ try
+ {
+ a[i] = (byte) BASE64_CHARS.indexOf(str.charAt(i));
+ }
+ catch (ArrayIndexOutOfBoundsException x)
+ {
+ throw new NumberFormatException("Illegal character at #" + i);
+ }
+ }
+ i = len - 1;
+ j = len;
+ try
+ {
+ while (true)
+ {
+ a[j] = a[i];
+ if (--i < 0)
+ {
+ break;
+ }
+ a[j] |= (a[i] & 0x03) << 6;
+ j--;
+ a[j] = (byte) ((a[i] & 0x3C) >>> 2);
+ if (--i < 0)
+ {
+ break;
+ }
+ a[j] |= (a[i] & 0x0F) << 4;
+ j--;
+ a[j] = (byte) ((a[i] & 0x30) >>> 4);
+ if (--i < 0)
+ {
+ break;
+ }
+ a[j] |= (a[i] << 2);
+ j--;
+ a[j] = 0;
+ if (--i < 0)
+ {
+ break;
+ }
+ }
+ }
+ catch (Exception ignored)
+ {
+ }
+
+ try
+ { // ignore leading 0-bytes
+ while (a[j] == 0)
+ {
+ j++;
+ }
+ }
+ catch (Exception x)
+ {
+ return new byte[1]; // one 0-byte
+ }
+ byte[] result = new byte[len - j + 1];
+ System.arraycopy(a, j, result, 0, len - j + 1);
+ return result;
+ }
+
+ // BigInteger utilities ----------------------------------------------------
+
+ /**
+ * <p>Treats the input as the MSB representation of a number, and discards
+ * leading zero elements. For efficiency, the input is simply returned if no
+ * leading zeroes are found.</p>
+ *
+ * @param n the {@link BigInteger} to trim.
+ * @return the byte array representation of the designated {@link BigInteger}
+ * with no leading 0-bytes.
+ */
+ public static final byte[] trim(BigInteger n)
+ {
+ byte[] in = n.toByteArray();
+ if (in.length == 0 || in[0] != 0)
+ {
+ return in;
+ }
+ int len = in.length;
+ int i = 1;
+ while (in[i] == 0 && i < len)
+ {
+ ++i;
+ }
+ byte[] result = new byte[len - i];
+ System.arraycopy(in, i, result, 0, len - i);
+ return result;
+ }
+
+ /**
+ * <p>Returns a hexadecimal dump of the trimmed bytes of a {@link BigInteger}.
+ * </p>
+ *
+ * @param x the {@link BigInteger} to display.
+ * @return the string representation of the designated {@link BigInteger}.
+ */
+ public static final String dump(BigInteger x)
+ {
+ return dumpString(trim(x));
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/X509Certificate.java b/libjava/classpath/gnu/java/security/x509/X509Certificate.java
index 14ac43a25e6..cf0161701cc 100644
--- a/libjava/classpath/gnu/java/security/x509/X509Certificate.java
+++ b/libjava/classpath/gnu/java/security/x509/X509Certificate.java
@@ -40,7 +40,6 @@ package gnu.java.security.x509;
import gnu.classpath.debug.Component;
import gnu.classpath.debug.SystemLogger;
-
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
@@ -88,8 +87,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
-import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.x500.X500Principal;
@@ -661,10 +658,7 @@ public class X509Certificate extends java.security.cert.X509Certificate
der.skip(spki.getLength());
logger.log (Component.X509, "read subjectPublicKey == {0}", subjectKey);
- if (version > 1)
- {
- val = der.read();
- }
+ val = der.read();
if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1)
{
byte[] b = (byte[]) val.getValue();
diff --git a/libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java b/libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java
index e92aedaefd0..dae94cd9f35 100644
--- a/libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java
+++ b/libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java
@@ -52,6 +52,8 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import javax.security.auth.x500.X500Principal;
+
public class GeneralNames
{
@@ -81,12 +83,14 @@ public class GeneralNames
if (!nameList.isConstructed())
throw new IOException("malformed GeneralNames");
int len = 0;
+ int i = 0;
while (len < nameList.getLength())
{
DERValue name = der.read();
List namePair = new ArrayList(2);
- if (name.getTagClass() != DER.APPLICATION)
- throw new IOException("malformed GeneralName");
+ int tagClass = name.getTagClass();
+ if (tagClass != DER.CONTEXT)
+ throw new IOException("malformed GeneralName: Tag class is " + tagClass);
namePair.add(new Integer(name.getTag()));
DERValue val = null;
switch (name.getTag())
@@ -99,6 +103,15 @@ public class GeneralNames
break;
case OTHER_NAME:
+ // MUST return the encoded bytes of the OID/OctetString sequence
+ byte[] anotherName = name.getEncoded();
+ anotherName[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE);
+ namePair.add(anotherName);
+ // DERReader goes back on Constructed things so we need to skip over them
+ DERValue skip = der.read(); // skip OID
+ skip = der.read(); // skip Octet String
+ break;
+
case EDI_PARTY_NAME:
namePair.add(name.getValue());
break;
@@ -106,7 +119,9 @@ public class GeneralNames
case DIRECTORY_NAME:
byte[] b = name.getEncoded();
b[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE);
- namePair.add(new X500DistinguishedName(b).toString());
+ DERReader r = new DERReader (b);
+ r.read ();
+ namePair.add(new X500Principal(r.read ().getEncoded ()).toString());
break;
case IP_ADDRESS:
diff --git a/libjava/classpath/gnu/java/util/prefs/EventDispatcher.java b/libjava/classpath/gnu/java/util/prefs/EventDispatcher.java
new file mode 100644
index 00000000000..feabe4dce51
--- /dev/null
+++ b/libjava/classpath/gnu/java/util/prefs/EventDispatcher.java
@@ -0,0 +1,112 @@
+/* EventDispatcher.java -- Dispatch events for prefs
+ 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.java.util.prefs;
+
+import java.util.ArrayList;
+
+/**
+ * This is a helper class used for dispatching events for
+ * the prefs package.
+ */
+public class EventDispatcher extends Thread
+{
+ // This is a singleton class. We dispatch all events via a
+ // new Thread which is created on demand.
+ private static final Thread dispatchThread = new EventDispatcher();
+
+ // This is a queue of events to dispatch. This thread waits on
+ // the queue and when notified will remove events until the queue
+ // is empty.
+ private static final ArrayList queue = new ArrayList();
+
+ // FIXME: this thread probably ought to go in some classpath-internal
+ // ThreadGroup. But we don't have that yet.
+ private EventDispatcher()
+ {
+ setDaemon(true);
+ start();
+ }
+
+ public void run()
+ {
+ while (true)
+ {
+ Runnable r;
+ synchronized (queue)
+ {
+ while (queue.size() == 0)
+ {
+ try
+ {
+ wait();
+ }
+ catch (InterruptedException _)
+ {
+ // Ignore.
+ }
+ }
+ r = (Runnable) queue.remove(0);
+ }
+ // Invoke outside the synchronization, so that
+ // we aren't blocking other threads from posting events.
+ try
+ {
+ r.run();
+ }
+ catch (Throwable _)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ /**
+ * Add a new runnable to the event dispatch queue. The
+ * runnable will be invoked in the event dispatch queue
+ * without any locks held.
+ * @param runner the Runnable to dispatch
+ */
+ public static void dispatch(Runnable runner)
+ {
+ synchronized (queue)
+ {
+ queue.add(runner);
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/util/prefs/FileBasedFactory.java b/libjava/classpath/gnu/java/util/prefs/FileBasedFactory.java
index 70f3558fc6f..e5f24efa3a0 100644
--- a/libjava/classpath/gnu/java/util/prefs/FileBasedFactory.java
+++ b/libjava/classpath/gnu/java/util/prefs/FileBasedFactory.java
@@ -47,11 +47,19 @@ import java.util.prefs.*;
*/
public class FileBasedFactory implements PreferencesFactory {
+ // We don't save or read any system preferences for the
+ // time being.
+ private static final Preferences systemPreferences
+ = new MemoryBasedPreferences(null, "", false);
+
+ private static final Preferences userPreferences
+ = new FileBasedPreferences();
+
public Preferences systemRoot() {
- return null;
+ return systemPreferences;
}
public Preferences userRoot() {
- return null;
+ return userPreferences;
}
}
diff --git a/libjava/classpath/gnu/java/util/prefs/FileBasedPreferences.java b/libjava/classpath/gnu/java/util/prefs/FileBasedPreferences.java
new file mode 100644
index 00000000000..f7566dddddf
--- /dev/null
+++ b/libjava/classpath/gnu/java/util/prefs/FileBasedPreferences.java
@@ -0,0 +1,273 @@
+/* FileBasedPreferences.java -- File-based preference implementation
+ 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.java.util.prefs;
+
+import gnu.classpath.SystemProperties;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.util.Properties;
+import java.util.prefs.AbstractPreferences;
+import java.util.prefs.BackingStoreException;
+
+/**
+ * This is a simple file-based preference implementation which writes
+ * the preferences as properties files. A node is represented as a directory
+ * beneath the user's home directory. The preferences for the node are
+ * stored in a single properties file in that directory. Sub-nodes are
+ * stored in subdirectories. This implementation uses file locking to
+ * mediate access to the properties files.
+ */
+public class FileBasedPreferences
+ extends AbstractPreferences
+{
+ /**
+ * Name of the property file storing the data in a given directory.
+ */
+ private static final String DATA_FILE = "data.properties";
+
+ /**
+ * The directory corresponding to this preference node.
+ */
+ private File directory;
+
+ /**
+ * The file holding the data for this node.
+ */
+ private File dataFile;
+
+ /**
+ * The data in this node.
+ */
+ private Properties properties;
+
+ /**
+ * Create the root node for the file-based preferences.
+ */
+ FileBasedPreferences()
+ {
+ super(null, "");
+ String home = SystemProperties.getProperty("user.home");
+ this.directory = new File(new File(home, ".classpath"), "userPrefs");
+ this.dataFile = new File(this.directory, DATA_FILE);
+ load();
+ }
+
+ /**
+ * Create a new file-based preference object with the given parent
+ * and the given name.
+ * @param parent the parent
+ * @param name the name of this node
+ */
+ FileBasedPreferences(FileBasedPreferences parent, String name)
+ {
+ super(parent, name);
+ this.directory = new File(parent.directory, name);
+ this.dataFile = new File(this.directory, DATA_FILE);
+ load();
+ }
+
+ private void load()
+ {
+ this.properties = new Properties();
+ FileInputStream fis = null;
+ FileLock lock = null;
+ try
+ {
+ fis = new FileInputStream(this.dataFile);
+ FileChannel channel = fis.getChannel();
+ lock = channel.lock(0, Long.MAX_VALUE, true);
+ this.properties.load(fis);
+ // We release the lock and close the stream in the 'finally'
+ // clause.
+ }
+ catch (IOException _)
+ {
+ // We don't mind; this means we're making a new node.
+ newNode = true;
+ }
+ finally
+ {
+ try
+ {
+ // Release the lock and close the stream.
+ if (lock != null)
+ lock.release();
+ }
+ catch (IOException ignore)
+ {
+ // Ignore.
+ }
+ try
+ {
+ // Close the stream.
+ if (fis != null)
+ fis.close();
+ }
+ catch (IOException ignore)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ public boolean isUserNode()
+ {
+ // For now file preferences are always user nodes.
+ return true;
+ }
+
+ protected String[] childrenNamesSpi() throws BackingStoreException
+ {
+ // FIXME: security manager.
+ String[] result = directory.list(new FilenameFilter()
+ {
+ public boolean accept(File dir, String name)
+ {
+ return new File(dir, name).isDirectory();
+ }
+ });
+ if (result == null)
+ result = new String[0];
+ return result;
+ }
+
+ protected AbstractPreferences childSpi(String name)
+ {
+ return new FileBasedPreferences(this, name);
+ }
+
+ protected String[] keysSpi() throws BackingStoreException
+ {
+ return (String[]) properties.keySet().toArray(new String[0]);
+ }
+
+ protected String getSpi(String key)
+ {
+ return properties.getProperty(key);
+ }
+
+ protected void putSpi(String key, String value)
+ {
+ properties.put(key, value);
+ }
+
+ protected void removeSpi(String key)
+ {
+ properties.remove(key);
+ }
+
+ protected void flushSpi() throws BackingStoreException
+ {
+ // FIXME: security manager.
+ try
+ {
+ if (isRemoved())
+ {
+ // Delete the underlying file.
+ // FIXME: ideally we would also delete the directory
+ // if it had no subdirectories. This doesn't matter
+ // much though.
+ // FIXME: there's a strange race here if a different VM is
+ // simultaneously updating this node.
+ dataFile.delete();
+ }
+ else
+ {
+ // Write the underlying file.
+ directory.mkdirs();
+
+ FileOutputStream fos = null;
+ FileLock lock = null;
+ try
+ {
+ // Note that we let IOExceptions from the try clause
+ // propagate to the outer 'try'.
+ fos = new FileOutputStream(dataFile);
+ FileChannel channel = fos.getChannel();
+ lock = channel.lock();
+ properties.store(fos, "created by GNU Classpath FileBasedPreferences");
+ // Lock is released and file closed in the finally clause.
+ }
+ finally
+ {
+ try
+ {
+ if (lock != null)
+ lock.release();
+ }
+ catch (IOException _)
+ {
+ // Ignore.
+ }
+ try
+ {
+ if (fos != null)
+ fos.close();
+ }
+ catch (IOException _)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ throw new BackingStoreException(ioe);
+ }
+ }
+
+ protected void syncSpi() throws BackingStoreException
+ {
+ // FIXME: we ought to synchronize but instead we merely flush.
+ flushSpi();
+ }
+
+ protected void removeNodeSpi() throws BackingStoreException
+ {
+ // We can simply delegate.
+ flushSpi();
+ }
+}
diff --git a/libjava/classpath/gnu/java/util/prefs/MemoryBasedFactory.java b/libjava/classpath/gnu/java/util/prefs/MemoryBasedFactory.java
index abaf0016f5b..275b8796ec6 100644
--- a/libjava/classpath/gnu/java/util/prefs/MemoryBasedFactory.java
+++ b/libjava/classpath/gnu/java/util/prefs/MemoryBasedFactory.java
@@ -40,7 +40,7 @@ package gnu.java.util.prefs;
import java.util.prefs.*;
/**
- * Memory based PreferencesFactory usefull for testing.
+ * Memory based PreferencesFactory useful for testing.
* Returns completely empty Preferences for system and user roots.
* All changes are only backed by the current instances in memory.
*
diff --git a/libjava/classpath/gnu/java/util/prefs/MemoryBasedPreferences.java b/libjava/classpath/gnu/java/util/prefs/MemoryBasedPreferences.java
index b2f321c9c7e..cccb9bf2fc2 100644
--- a/libjava/classpath/gnu/java/util/prefs/MemoryBasedPreferences.java
+++ b/libjava/classpath/gnu/java/util/prefs/MemoryBasedPreferences.java
@@ -1,5 +1,5 @@
/* MemoryBasedPreferences - A Preference node which holds all entries in memory
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -79,7 +79,7 @@ public class MemoryBasedPreferences extends AbstractPreferences {
/**
* Returns an empty array since all children names are always already
- * chached.
+ * cached.
*/
protected String[] childrenNamesSpi() throws BackingStoreException {
return new String[0];
diff --git a/libjava/classpath/gnu/java/util/prefs/NodeWriter.java b/libjava/classpath/gnu/java/util/prefs/NodeWriter.java
index 1eed9e66e2d..c3cf8e8188a 100644
--- a/libjava/classpath/gnu/java/util/prefs/NodeWriter.java
+++ b/libjava/classpath/gnu/java/util/prefs/NodeWriter.java
@@ -1,5 +1,5 @@
/* NodeWriter - Writes and exports preferences nodes to files
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,6 +41,7 @@ import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.StringTokenizer;
@@ -67,23 +68,24 @@ public class NodeWriter {
private boolean subtree;
/**
- * Creates a new NodeWriter for the given preferences node and writer.
- */
- public NodeWriter(Preferences prefs, Writer w) {
- this.prefs = prefs;
- if (w instanceof BufferedWriter) {
- this.bw = (BufferedWriter) w;
- } else {
- this.bw = new BufferedWriter(w);
- }
- }
-
- /**
* Creates a new NodeWriter for the given preferences node and
* outputstream. Creates a new OutputStreamWriter.
*/
public NodeWriter(Preferences prefs, OutputStream os) {
- this(prefs, new OutputStreamWriter(os));
+ this.prefs = prefs;
+ Writer w;
+ try
+ {
+ w = new OutputStreamWriter(os, "UTF-8");
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ // Shouldn't happen, since we always have UTF-8 available.
+ InternalError ie = new InternalError("UTF-8 encoding missing");
+ ie.initCause(uee);
+ throw ie;
+ }
+ this.bw = new BufferedWriter(w);
}
/**
@@ -112,6 +114,9 @@ public class NodeWriter {
private void writeHeader() throws BackingStoreException, IOException {
bw.write("<?xml version=\"1.0\"?>");
bw.newLine();
+ bw.write("<!DOCTYPE preferences SYSTEM "
+ + "\"http://java.sun.com/dtd/preferences.dtd\">");
+ bw.newLine();
bw.newLine();
bw.write("<!-- GNU Classpath java.util.prefs Preferences ");
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/java/security/provider/DiffieHellmanKeyPairGeneratorImpl.java b/libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyPairGeneratorSpi.java
index 1b68d274fa8..5b3badc8d83 100644
--- a/libjava/classpath/gnu/java/security/provider/DiffieHellmanKeyPairGeneratorImpl.java
+++ b/libjava/classpath/gnu/javax/crypto/jce/sig/DHKeyPairGeneratorSpi.java
@@ -1,5 +1,5 @@
-/* DiffieHellmanKeyPairGeneratorImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+/* DHKeyPairGeneratorSpi.java -- DH key-pair generator JCE Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -36,51 +36,56 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.java.security.provider;
+package gnu.javax.crypto.jce.sig;
-import gnu.javax.crypto.GnuDHPrivateKey;
-
-import java.math.BigInteger;
-
-import java.security.KeyPair;
-import java.security.KeyPairGeneratorSpi;
+import java.security.InvalidAlgorithmParameterException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
+import java.util.HashMap;
-import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHGenParameterSpec;
-public class DiffieHellmanKeyPairGeneratorImpl extends KeyPairGeneratorSpi
-{
- private SecureRandom random;
- private DHParameterSpec params;
+import gnu.java.security.Registry;
+import gnu.java.security.jce.sig.KeyPairGeneratorAdapter;
+import gnu.javax.crypto.key.dh.GnuDHKeyPairGenerator;
- public KeyPair generateKeyPair ()
+public class DHKeyPairGeneratorSpi
+ extends KeyPairGeneratorAdapter
+{
+ public DHKeyPairGeneratorSpi()
{
- if (params == null || random == null)
- throw new IllegalStateException ("not initialized");
- byte[] buf = new byte[(params.getP ().bitLength() >>> 3)];
- random.nextBytes (buf);
- BigInteger x = new BigInteger (1, buf);
- BigInteger y = params.getG ().modPow (x, params.getP ());
- GnuDHPublicKey pub = new GnuDHPublicKey (params, y, null);
- GnuDHPrivateKey priv = new GnuDHPrivateKey (x, params);
-
- return new KeyPair (pub, priv);
+ super(Registry.DH_KPG);
}
- public void initialize (final int keysize, final SecureRandom random)
+ public void initialize(int keysize, SecureRandom random)
{
- throw new UnsupportedOperationException ("key generation without parameters not supported");
+ 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 (final AlgorithmParameterSpec params,
- final SecureRandom random)
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
{
- if (!(params instanceof DHParameterSpec))
- throw new IllegalArgumentException ("expecting Diffie-Hellman parameters");
- this.params = (DHParameterSpec) params;
- this.random = random;
- if (this.random == null)
- this.random = new SecureRandom ();
+ 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/net/ssl/provider/JessieDHPrivateKey.java b/libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java
new file mode 100644
index 00000000000..1997458dd24
--- /dev/null
+++ b/libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java
@@ -0,0 +1,99 @@
+/* JessieDHPrivateKey.java -- simple DH private key.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.math.BigInteger;
+
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.spec.DHParameterSpec;
+
+class JessieDHPrivateKey implements DHPrivateKey
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private final DHParameterSpec params;
+ private final BigInteger x;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ JessieDHPrivateKey(DHParameterSpec params, BigInteger x)
+ {
+ this.params = params;
+ this.x = x;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String getAlgorithm()
+ {
+ return "Diffie-Hellman";
+ }
+
+ public String getFormat()
+ {
+ return "NONE";
+ }
+
+ public byte[] getEncoded()
+ {
+ return null;
+ }
+
+ public DHParameterSpec getParams()
+ {
+ return params;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ public String toString()
+ {
+ String nl = System.getProperty("line.separator");
+ return "P: " + params.getP() + nl +
+ "G: " + params.getG() + nl +
+ "X: " + x;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/provider/GnuDHPublicKey.java b/libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPublicKey.java
index 6e13f6bf20f..dc6587288e6 100644
--- a/libjava/classpath/gnu/java/security/provider/GnuDHPublicKey.java
+++ b/libjava/classpath/gnu/javax/net/ssl/provider/JessieDHPublicKey.java
@@ -1,12 +1,12 @@
-/* GnuDHPublicKey.java -- A Diffie-Hellman public key.
- Copyright (C) 2004 Free Software Foundation, Inc.
+/* JessieDHPublicKey.java -- simple DH public 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,83 +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.java.security.provider;
-
-import gnu.java.security.OID;
-import gnu.java.security.der.BitString;
-import gnu.java.security.der.DER;
-import gnu.java.security.der.DERValue;
+package gnu.javax.net.ssl.provider;
import java.math.BigInteger;
-import java.util.ArrayList;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
-public class GnuDHPublicKey implements DHPublicKey
+class JessieDHPublicKey implements DHPublicKey
{
// Fields.
// -------------------------------------------------------------------------
- private byte[] encoded;
private final DHParameterSpec params;
- private final BigInteger Y;
- private final BigInteger q;
+ private final BigInteger y;
// Constructor.
// -------------------------------------------------------------------------
- public GnuDHPublicKey(DHParameterSpec params, BigInteger Y, BigInteger q)
+ JessieDHPublicKey(DHParameterSpec params, BigInteger y)
{
this.params = params;
- this.Y = Y;
- this.q = q;
+ this.y = y;
}
// Instance methods.
// -------------------------------------------------------------------------
- public BigInteger getY()
+ public String getAlgorithm()
{
- return Y;
+ return "Diffie-Hellman";
}
- public DHParameterSpec getParams()
+ public String getFormat()
{
- return params;
+ return "NONE";
}
- public String getAlgorithm()
+ public byte[] getEncoded()
+ {
+ return null;
+ }
+
+ public DHParameterSpec getParams()
{
- return "DH";
+ return params;
}
- public String getFormat()
+ public BigInteger getY()
{
- return "X.509";
+ return y;
}
- public byte[] getEncoded()
+ public String toString()
{
- if (encoded != null)
- return (byte[]) encoded.clone();
- ArrayList spki = new ArrayList(2);
- ArrayList alg = new ArrayList(2);
- alg.add(new DERValue(DER.OBJECT_IDENTIFIER, new OID("1.2.840.10046.2.1")));
- ArrayList param = new ArrayList(3);
- param.add(new DERValue(DER.INTEGER, params.getP()));
- param.add(new DERValue(DER.INTEGER, params.getG()));
- param.add(new DERValue(DER.INTEGER, q));
- alg.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, param));
- spki.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, alg));
- spki.add(new DERValue(DER.BIT_STRING, new BitString(Y.toByteArray())));
- encoded = new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, spki).getEncoded();
- if (encoded != null)
- return (byte[]) encoded.clone();
- return null;
+ 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/java/security/provider/GnuRSAPublicKey.java b/libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java
index a35e761c066..19921d98c67 100644
--- a/libjava/classpath/gnu/java/security/provider/GnuRSAPublicKey.java
+++ b/libjava/classpath/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java
@@ -1,12 +1,12 @@
-/* GnuRSAPublicKey.java -- GNU RSA public key.
- Copyright (C) 2004 Free Software Foundation, Inc.
+/* JessieRSAPublicKey.java -- simple RSA public 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,77 +33,66 @@ module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the 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.java.security.provider;
-
-import gnu.java.security.OID;
-import gnu.java.security.der.BitString;
-import gnu.java.security.der.DER;
-import gnu.java.security.der.DERValue;
+package gnu.javax.net.ssl.provider;
import java.math.BigInteger;
import java.security.interfaces.RSAPublicKey;
-import java.security.spec.RSAPublicKeySpec;
-import java.util.ArrayList;
-class GnuRSAPublicKey implements RSAPublicKey
+class JessieRSAPublicKey implements RSAPublicKey
{
// Fields.
// -------------------------------------------------------------------------
- private final RSAPublicKeySpec spec;
- private byte[] encodedKey;
+ private final BigInteger modulus;
+ private final BigInteger exponent;
// Constructor.
// -------------------------------------------------------------------------
- public GnuRSAPublicKey(RSAPublicKeySpec spec)
+ JessieRSAPublicKey(BigInteger modulus, BigInteger exponent)
{
- this.spec = spec;
+ this.modulus = modulus;
+ this.exponent = exponent;
}
// Instance methods.
// -------------------------------------------------------------------------
- public BigInteger getModulus()
+ public String getAlgorithm()
{
- return spec.getModulus();
+ return "RSA";
}
- public BigInteger getPublicExponent()
+ public String getFormat()
{
- return spec.getPublicExponent();
+ return "NONE";
}
- public String getAlgorithm()
+ public byte[] getEncoded()
{
- return "RSA";
+ return null;
}
- public String getFormat()
+ public BigInteger getModulus()
{
- return "X.509";
+ return modulus;
}
- public byte[] getEncoded()
+ public BigInteger getPublicExponent()
+ {
+ return exponent;
+ }
+
+ public String toString()
{
- if (encodedKey != null)
- return (byte[]) encodedKey.clone();
- ArrayList key = new ArrayList(2);
- key.add(new DERValue(DER.INTEGER, getModulus()));
- key.add(new DERValue(DER.INTEGER, getPublicExponent()));
- DERValue rsapk = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, key);
- ArrayList alg = new ArrayList(2);
- alg.add(new DERValue(DER.OBJECT_IDENTIFIER,
- new OID("1.2.840.113549.1.1.1")));
- alg.add(new DERValue(DER.NULL, null));
- ArrayList spki = new ArrayList(2);
- spki.add(new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, alg));
- spki.add(new DERValue(DER.BIT_STRING, new BitString(rsapk.getEncoded())));
- encodedKey = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, spki).getEncoded();
- return (byte[]) encodedKey.clone();
+ 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;
+ }
+}
diff --git a/libjava/classpath/gnu/regexp/CharIndexed.java b/libjava/classpath/gnu/regexp/CharIndexed.java
index a0d7106aefa..df1d8930c6b 100644
--- a/libjava/classpath/gnu/regexp/CharIndexed.java
+++ b/libjava/classpath/gnu/regexp/CharIndexed.java
@@ -1,5 +1,5 @@
/* gnu/regexp/CharIndexed.java
- Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998-2001, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -81,4 +81,16 @@ public interface CharIndexed {
* position at a valid position in the input.
*/
boolean isValid();
+
+ /**
+ * Returns another CharIndexed containing length characters to the left
+ * of the given index. The given length is an expected maximum and
+ * the returned CharIndexed may not necessarily contain so many characters.
+ */
+ CharIndexed lookBehind(int index, int length);
+
+ /**
+ * Returns the effective length of this CharIndexed
+ */
+ int length();
}
diff --git a/libjava/classpath/gnu/regexp/CharIndexedCharArray.java b/libjava/classpath/gnu/regexp/CharIndexedCharArray.java
index 63d858c8709..1388d4729bf 100644
--- a/libjava/classpath/gnu/regexp/CharIndexedCharArray.java
+++ b/libjava/classpath/gnu/regexp/CharIndexedCharArray.java
@@ -1,5 +1,5 @@
/* gnu/regexp/CharIndexedCharArray.java
- Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998-2001, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -59,4 +59,13 @@ class CharIndexedCharArray implements CharIndexed, Serializable {
public boolean move(int index) {
return ((anchor += index) < s.length);
}
+
+ public CharIndexed lookBehind(int index, int length) {
+ if (length > (anchor + index)) length = anchor + index;
+ return new CharIndexedCharArray(s, anchor + index - length);
+ }
+
+ public int length() {
+ return s.length - anchor;
+ }
}
diff --git a/libjava/classpath/gnu/regexp/CharIndexedInputStream.java b/libjava/classpath/gnu/regexp/CharIndexedInputStream.java
index 145fe11b135..d5225a79337 100644
--- a/libjava/classpath/gnu/regexp/CharIndexedInputStream.java
+++ b/libjava/classpath/gnu/regexp/CharIndexedInputStream.java
@@ -1,5 +1,5 @@
/* gnu/regexp/CharIndexedInputStream.java
- Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998-2001, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -145,5 +145,15 @@ class CharIndexedInputStream implements CharIndexed {
public boolean isValid() {
return (cached != OUT_OF_BOUNDS);
}
+
+ public CharIndexed lookBehind(int index, int length) {
+ throw new UnsupportedOperationException(
+ "difficult to look behind for an input stream");
+ }
+
+ public int length() {
+ throw new UnsupportedOperationException(
+ "difficult to tell the length for an input stream");
+ }
}
diff --git a/libjava/classpath/gnu/regexp/CharIndexedString.java b/libjava/classpath/gnu/regexp/CharIndexedString.java
index 05be07ac68c..fe4fa8f7637 100644
--- a/libjava/classpath/gnu/regexp/CharIndexedString.java
+++ b/libjava/classpath/gnu/regexp/CharIndexedString.java
@@ -1,5 +1,5 @@
/* gnu/regexp/CharIndexedString.java
- Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998-2001, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -61,4 +61,13 @@ class CharIndexedString implements CharIndexed, Serializable {
public boolean move(int index) {
return ((anchor += index) < len);
}
+
+ public CharIndexed lookBehind(int index, int length) {
+ if (length > (anchor + index)) length = anchor + index;
+ return new CharIndexedString(s, anchor + index - length);
+ }
+
+ public int length() {
+ return len - anchor;
+ }
}
diff --git a/libjava/classpath/gnu/regexp/CharIndexedStringBuffer.java b/libjava/classpath/gnu/regexp/CharIndexedStringBuffer.java
index 1b88e398571..9c9118dfee2 100644
--- a/libjava/classpath/gnu/regexp/CharIndexedStringBuffer.java
+++ b/libjava/classpath/gnu/regexp/CharIndexedStringBuffer.java
@@ -1,5 +1,5 @@
/* gnu/regexp/CharIndexedStringBuffer.java
- Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998-2001, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -59,4 +59,13 @@ class CharIndexedStringBuffer implements CharIndexed, Serializable {
public boolean move(int index) {
return ((anchor += index) < s.length());
}
+
+ public CharIndexed lookBehind(int index, int length) {
+ if (length > (anchor + index)) length = anchor + index;
+ return new CharIndexedStringBuffer(s, anchor + index - length);
+ }
+
+ public int length() {
+ return s.length() - anchor;
+ }
}
diff --git a/libjava/classpath/gnu/regexp/RE.java b/libjava/classpath/gnu/regexp/RE.java
index 9ac9b53d1a9..ef606a6d8a7 100644
--- a/libjava/classpath/gnu/regexp/RE.java
+++ b/libjava/classpath/gnu/regexp/RE.java
@@ -1,5 +1,5 @@
/* gnu/regexp/RE.java
- Copyright (C) 1998-2001, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -136,12 +136,13 @@ public class RE extends REToken {
/** Minimum length, in characters, of any possible match. */
private int minimumLength;
+ private int maximumLength;
/**
* Compilation flag. Do not differentiate case. Subsequent
* searches using this RE will be case insensitive.
*/
- public static final int REG_ICASE = 2;
+ public static final int REG_ICASE = 0x02;
/**
* Compilation flag. The match-any-character operator (dot)
@@ -149,14 +150,14 @@ public class RE extends REToken {
* bit RE_DOT_NEWLINE (see RESyntax for details). This is equivalent to
* the "/s" operator in Perl.
*/
- public static final int REG_DOT_NEWLINE = 4;
+ public static final int REG_DOT_NEWLINE = 0x04;
/**
* Compilation flag. Use multiline mode. In this mode, the ^ and $
* anchors will match based on newlines within the input. This is
* equivalent to the "/m" operator in Perl.
*/
- public static final int REG_MULTILINE = 8;
+ public static final int REG_MULTILINE = 0x08;
/**
* Execution flag.
@@ -185,14 +186,14 @@ public class RE extends REToken {
* // m4.toString(): "fool"<BR>
* </CODE>
*/
- public static final int REG_NOTBOL = 16;
+ public static final int REG_NOTBOL = 0x10;
/**
* Execution flag.
* The match-end operator ($) does not match at the end
* of the input string. Useful for matching on substrings.
*/
- public static final int REG_NOTEOL = 32;
+ public static final int REG_NOTEOL = 0x20;
/**
* Execution flag.
@@ -206,7 +207,7 @@ public class RE extends REToken {
* the example under REG_NOTBOL. It also affects the use of the \&lt;
* and \b operators.
*/
- public static final int REG_ANCHORINDEX = 64;
+ public static final int REG_ANCHORINDEX = 0x40;
/**
* Execution flag.
@@ -215,7 +216,24 @@ public class RE extends REToken {
* the corresponding subexpressions. For example, you may want to
* replace all matches of "one dollar" with "$1".
*/
- public static final int REG_NO_INTERPOLATE = 128;
+ public static final int REG_NO_INTERPOLATE = 0x80;
+
+ /**
+ * Execution flag.
+ * Try to match the whole input string. An implicit match-end operator
+ * is added to this regexp.
+ */
+ public static final int REG_TRY_ENTIRE_MATCH = 0x0100;
+
+ /**
+ * Execution flag.
+ * The substitute and substituteAll methods will treat the
+ * character '\' in the replacement as an escape to a literal
+ * character. In this case "\n", "\$", "\\", "\x40" and "\012"
+ * will become "n", "$", "\", "x40" and "012" respectively.
+ * This flag has no effect if REG_NO_INTERPOLATE is set on.
+ */
+ public static final int REG_REPLACE_USE_BACKSLASHESCAPE = 0x0200;
/** Returns a string representing the version of the gnu.regexp package. */
public static final String version() {
@@ -273,12 +291,13 @@ public class RE extends REToken {
}
// internal constructor used for alternation
- private RE(REToken first, REToken last,int subs, int subIndex, int minLength) {
+ private RE(REToken first, REToken last,int subs, int subIndex, int minLength, int maxLength) {
super(subIndex);
firstToken = first;
lastToken = last;
numSubs = subs;
minimumLength = minLength;
+ maximumLength = maxLength;
addToken(new RETokenEndSub(subIndex));
}
@@ -333,6 +352,11 @@ public class RE extends REToken {
char ch;
boolean quot = false;
+ // Saved syntax and flags.
+ RESyntax savedSyntax = null;
+ int savedCflags = 0;
+ boolean flagsSaved = false;
+
while (index < pLength) {
// read the next character unit (including backslash escapes)
index = getCharUnit(pattern,index,unit,quot);
@@ -359,8 +383,9 @@ public class RE extends REToken {
&& !syntax.get(RESyntax.RE_LIMITED_OPS)) {
// make everything up to here be a branch. create vector if nec.
addToken(currentToken);
- RE theBranch = new RE(firstToken, lastToken, numSubs, subIndex, minimumLength);
+ RE theBranch = new RE(firstToken, lastToken, numSubs, subIndex, minimumLength, maximumLength);
minimumLength = 0;
+ maximumLength = 0;
if (branches == null) {
branches = new Vector();
}
@@ -402,102 +427,12 @@ public class RE extends REToken {
// [...] | [^...]
else if ((unit.ch == '[') && !(unit.bk || quot)) {
- Vector options = new Vector();
- boolean negative = false;
- char lastChar = 0;
- if (index == pLength) throw new REException(getLocalizedMessage("unmatched.bracket"),REException.REG_EBRACK,index);
-
- // Check for initial caret, negation
- if ((ch = pattern[index]) == '^') {
- negative = true;
- if (++index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
- ch = pattern[index];
- }
-
- // Check for leading right bracket literal
- if (ch == ']') {
- lastChar = ch;
- if (++index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
- }
-
- while ((ch = pattern[index++]) != ']') {
- if ((ch == '-') && (lastChar != 0)) {
- if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
- if ((ch = pattern[index]) == ']') {
- options.addElement(new RETokenChar(subIndex,lastChar,insens));
- lastChar = '-';
- } else {
- options.addElement(new RETokenRange(subIndex,lastChar,ch,insens));
- lastChar = 0;
- index++;
- }
- } else if ((ch == '\\') && syntax.get(RESyntax.RE_BACKSLASH_ESCAPE_IN_LISTS)) {
- if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
- int posixID = -1;
- boolean negate = false;
- char asciiEsc = 0;
- if (("dswDSW".indexOf(pattern[index]) != -1) && syntax.get(RESyntax.RE_CHAR_CLASS_ESC_IN_LISTS)) {
- switch (pattern[index]) {
- case 'D':
- negate = true;
- case 'd':
- posixID = RETokenPOSIX.DIGIT;
- break;
- case 'S':
- negate = true;
- case 's':
- posixID = RETokenPOSIX.SPACE;
- break;
- case 'W':
- negate = true;
- case 'w':
- posixID = RETokenPOSIX.ALNUM;
- break;
- }
- }
- else if ("nrt".indexOf(pattern[index]) != -1) {
- switch (pattern[index]) {
- case 'n':
- asciiEsc = '\n';
- break;
- case 't':
- asciiEsc = '\t';
- break;
- case 'r':
- asciiEsc = '\r';
- break;
- }
- }
- if (lastChar != 0) options.addElement(new RETokenChar(subIndex,lastChar,insens));
-
- if (posixID != -1) {
- options.addElement(new RETokenPOSIX(subIndex,posixID,insens,negate));
- } else if (asciiEsc != 0) {
- lastChar = asciiEsc;
- } else {
- lastChar = pattern[index];
- }
- ++index;
- } else if ((ch == '[') && (syntax.get(RESyntax.RE_CHAR_CLASSES)) && (index < pLength) && (pattern[index] == ':')) {
- StringBuffer posixSet = new StringBuffer();
- index = getPosixSet(pattern,index+1,posixSet);
- int posixId = RETokenPOSIX.intValue(posixSet.toString());
- if (posixId != -1)
- options.addElement(new RETokenPOSIX(subIndex,posixId,insens,false));
- } else {
- if (lastChar != 0) options.addElement(new RETokenChar(subIndex,lastChar,insens));
- lastChar = ch;
- }
- if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
- } // while in list
- // Out of list, index is one past ']'
-
- if (lastChar != 0) options.addElement(new RETokenChar(subIndex,lastChar,insens));
-
// Create a new RETokenOneOf
+ ParseCharClassResult result = parseCharClass(
+ subIndex, pattern, index, pLength, cflags, syntax, 0);
addToken(currentToken);
- options.trimToSize();
- currentToken = new RETokenOneOf(subIndex,options,negative);
+ currentToken = result.token;
+ index = result.index;
}
// SUBEXPRESSIONS
@@ -507,7 +442,10 @@ public class RE extends REToken {
boolean pure = false;
boolean comment = false;
boolean lookAhead = false;
+ boolean lookBehind = false;
+ boolean independent = false;
boolean negativelh = false;
+ boolean negativelb = false;
if ((index+1 < pLength) && (pattern[index] == '?')) {
switch (pattern[index+1]) {
case '!':
@@ -525,6 +463,114 @@ public class RE extends REToken {
index += 2;
}
break;
+ case '<':
+ // We assume that if the syntax supports look-ahead,
+ // it also supports look-behind.
+ if (syntax.get(RESyntax.RE_LOOKAHEAD)) {
+ index++;
+ switch (pattern[index +1]) {
+ case '!':
+ pure = true;
+ negativelb = true;
+ lookBehind = true;
+ index += 2;
+ break;
+ case '=':
+ pure = true;
+ lookBehind = true;
+ index += 2;
+ }
+ }
+ break;
+ case '>':
+ // We assume that if the syntax supports look-ahead,
+ // it also supports independent group.
+ if (syntax.get(RESyntax.RE_LOOKAHEAD)) {
+ pure = true;
+ independent = true;
+ index += 2;
+ }
+ break;
+ case 'i':
+ case 'd':
+ case 'm':
+ case 's':
+ // case 'u': not supported
+ // case 'x': not supported
+ case '-':
+ if (!syntax.get(RESyntax.RE_EMBEDDED_FLAGS)) break;
+ // Set or reset syntax flags.
+ int flagIndex = index + 1;
+ int endFlag = -1;
+ RESyntax newSyntax = new RESyntax(syntax);
+ int newCflags = cflags;
+ boolean negate = false;
+ while (flagIndex < pLength && endFlag < 0) {
+ switch(pattern[flagIndex]) {
+ case 'i':
+ if (negate)
+ newCflags &= ~REG_ICASE;
+ else
+ newCflags |= REG_ICASE;
+ flagIndex++;
+ break;
+ case 'd':
+ if (negate)
+ newSyntax.setLineSeparator(RESyntax.DEFAULT_LINE_SEPARATOR);
+ else
+ newSyntax.setLineSeparator("\n");
+ flagIndex++;
+ break;
+ case 'm':
+ if (negate)
+ newCflags &= ~REG_MULTILINE;
+ else
+ newCflags |= REG_MULTILINE;
+ flagIndex++;
+ break;
+ case 's':
+ if (negate)
+ newCflags &= ~REG_DOT_NEWLINE;
+ else
+ newCflags |= REG_DOT_NEWLINE;
+ flagIndex++;
+ break;
+ // case 'u': not supported
+ // case 'x': not supported
+ case '-':
+ negate = true;
+ flagIndex++;
+ break;
+ case ':':
+ case ')':
+ endFlag = pattern[flagIndex];
+ break;
+ default:
+ throw new REException(getLocalizedMessage("repeat.no.token"), REException.REG_BADRPT, index);
+ }
+ }
+ if (endFlag == ')') {
+ syntax = newSyntax;
+ cflags = newCflags;
+ insens = ((cflags & REG_ICASE) > 0);
+ // This can be treated as though it were a comment.
+ comment = true;
+ index = flagIndex - 1;
+ break;
+ }
+ if (endFlag == ':') {
+ savedSyntax = syntax;
+ savedCflags = cflags;
+ flagsSaved = true;
+ syntax = newSyntax;
+ cflags = newCflags;
+ insens = ((cflags & REG_ICASE) > 0);
+ index = flagIndex -1;
+ // Fall through to the next case.
+ }
+ else {
+ throw new REException(getLocalizedMessage("unmatched.paren"), REException.REG_ESUBREG,index);
+ }
case ':':
if (syntax.get(RESyntax.RE_PURE_GROUPING)) {
pure = true;
@@ -607,15 +653,28 @@ public class RE extends REToken {
numSubs++;
}
- int useIndex = (pure || lookAhead) ? 0 : nextSub + numSubs;
+ int useIndex = (pure || lookAhead || lookBehind || independent) ?
+ 0 : nextSub + numSubs;
currentToken = new RE(String.valueOf(pattern,index,endIndex-index).toCharArray(),cflags,syntax,useIndex,nextSub + numSubs);
numSubs += ((RE) currentToken).getNumSubs();
if (lookAhead) {
currentToken = new RETokenLookAhead(currentToken,negativelh);
}
+ else if (lookBehind) {
+ currentToken = new RETokenLookBehind(currentToken,negativelb);
+ }
+ else if (independent) {
+ currentToken = new RETokenIndependent(currentToken);
+ }
index = nextIndex;
+ if (flagsSaved) {
+ syntax = savedSyntax;
+ cflags = savedCflags;
+ insens = ((cflags & REG_ICASE) > 0);
+ flagsSaved = false;
+ }
} // not a comment
} // subexpression
@@ -715,14 +774,45 @@ public class RE extends REToken {
else
currentToken = setRepeated(currentToken,0,1,index);
}
+
+ // OCTAL CHARACTER
+ // \0377
+ else if (unit.bk && (unit.ch == '0') && syntax.get(RESyntax.RE_OCTAL_CHAR)) {
+ CharExpression ce = getCharExpression(pattern, index - 2, pLength, syntax);
+ if (ce == null)
+ throw new REException("invalid octal character", REException.REG_ESCAPE, index);
+ index = index - 2 + ce.len;
+ addToken(currentToken);
+ currentToken = new RETokenChar(subIndex,ce.ch,insens);
+ }
+
// BACKREFERENCE OPERATOR
- // \1 \2 ... \9
+ // \1 \2 ... \9 and \10 \11 \12 ...
// not available if RE_NO_BK_REFS is set
+ // Perl recognizes \10, \11, and so on only if enough number of
+ // parentheses have opened before it, otherwise they are treated
+ // as aliases of \010, \011, ... (octal characters). In case of
+ // Sun's JDK, octal character expression must always begin with \0.
+ // We will do as JDK does. But FIXME, take a look at "(a)(b)\29".
+ // JDK treats \2 as a back reference to the 2nd group because
+ // there are only two groups. But in our poor implementation,
+ // we cannot help but treat \29 as a back reference to the 29th group.
else if (unit.bk && Character.isDigit(unit.ch) && !syntax.get(RESyntax.RE_NO_BK_REFS)) {
addToken(currentToken);
- currentToken = new RETokenBackRef(subIndex,Character.digit(unit.ch,10),insens);
+ int numBegin = index - 1;
+ int numEnd = pLength;
+ for (int i = index; i < pLength; i++) {
+ if (! Character.isDigit(pattern[i])) {
+ numEnd = i;
+ break;
+ }
+ }
+ int num = parseInt(pattern, numBegin, numEnd-numBegin, 10);
+
+ currentToken = new RETokenBackRef(subIndex,num,insens);
+ index = numEnd;
}
// START OF STRING OPERATOR
@@ -844,6 +934,32 @@ public class RE extends REToken {
currentToken = new RETokenEnd(subIndex,null);
}
+ // HEX CHARACTER, UNICODE CHARACTER
+ // \x1B, \u1234
+
+ else if ((unit.bk && (unit.ch == 'x') && syntax.get(RESyntax.RE_HEX_CHAR)) ||
+ (unit.bk && (unit.ch == 'u') && syntax.get(RESyntax.RE_UNICODE_CHAR))) {
+ CharExpression ce = getCharExpression(pattern, index - 2, pLength, syntax);
+ if (ce == null)
+ throw new REException("invalid hex character", REException.REG_ESCAPE, index);
+ index = index - 2 + ce.len;
+ addToken(currentToken);
+ currentToken = new RETokenChar(subIndex,ce.ch,insens);
+ }
+
+ // NAMED PROPERTY
+ // \p{prop}, \P{prop}
+
+ else if ((unit.bk && (unit.ch == 'p') && syntax.get(RESyntax.RE_NAMED_PROPERTY)) ||
+ (unit.bk && (unit.ch == 'P') && syntax.get(RESyntax.RE_NAMED_PROPERTY))) {
+ NamedProperty np = getNamedProperty(pattern, index - 2, pLength);
+ if (np == null)
+ throw new REException("invalid escape sequence", REException.REG_ESCAPE, index);
+ index = index - 2 + np.len;
+ addToken(currentToken);
+ currentToken = getRETokenNamedProperty(subIndex,np,insens,index);
+ }
+
// NON-SPECIAL CHARACTER (or escape to make literal)
// c | \* for example
@@ -857,9 +973,10 @@ public class RE extends REToken {
addToken(currentToken);
if (branches != null) {
- branches.addElement(new RE(firstToken,lastToken,numSubs,subIndex,minimumLength));
+ branches.addElement(new RE(firstToken,lastToken,numSubs,subIndex,minimumLength, maximumLength));
branches.trimToSize(); // compact the Vector
minimumLength = 0;
+ maximumLength = 0;
firstToken = lastToken = null;
addToken(new RETokenOneOf(subIndex,branches,false));
}
@@ -867,6 +984,199 @@ public class RE extends REToken {
}
+ private static class ParseCharClassResult {
+ RETokenOneOf token;
+ int index;
+ boolean returnAtAndOperator = false;
+ }
+
+ /**
+ * Parse [...] or [^...] and make an RETokenOneOf instance.
+ * @param subIndex subIndex to be given to the created RETokenOneOf instance.
+ * @param pattern Input array of characters to be parsed.
+ * @param index Index pointing to the character next to the beginning '['.
+ * @param pLength Limit of the input array.
+ * @param cflags Compilation flags used to parse the pattern.
+ * @param pflags Flags that affect the behavior of this method.
+ * @param syntax Syntax used to parse the pattern.
+ */
+ private static ParseCharClassResult parseCharClass(int subIndex,
+ char[] pattern, int index,
+ int pLength, int cflags, RESyntax syntax, int pflags)
+ throws REException {
+
+ boolean insens = ((cflags & REG_ICASE) > 0);
+ Vector options = new Vector();
+ Vector addition = new Vector();
+ boolean additionAndAppeared = false;
+ final int RETURN_AT_AND = 0x01;
+ boolean returnAtAndOperator = ((pflags & RETURN_AT_AND) != 0);
+ boolean negative = false;
+ char ch;
+
+ char lastChar = 0;
+ boolean lastCharIsSet = false;
+ if (index == pLength) throw new REException(getLocalizedMessage("unmatched.bracket"),REException.REG_EBRACK,index);
+
+ // Check for initial caret, negation
+ if ((ch = pattern[index]) == '^') {
+ negative = true;
+ if (++index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
+ ch = pattern[index];
+ }
+
+ // Check for leading right bracket literal
+ if (ch == ']') {
+ lastChar = ch; lastCharIsSet = true;
+ if (++index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
+ }
+
+ while ((ch = pattern[index++]) != ']') {
+ if ((ch == '-') && (lastCharIsSet)) {
+ if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
+ if ((ch = pattern[index]) == ']') {
+ options.addElement(new RETokenChar(subIndex,lastChar,insens));
+ lastChar = '-';
+ } else {
+ if ((ch == '\\') && syntax.get(RESyntax.RE_BACKSLASH_ESCAPE_IN_LISTS)) {
+ CharExpression ce = getCharExpression(pattern, index, pLength, syntax);
+ if (ce == null)
+ throw new REException("invalid escape sequence", REException.REG_ESCAPE, index);
+ ch = ce.ch;
+ index = index + ce.len - 1;
+ }
+ options.addElement(new RETokenRange(subIndex,lastChar,ch,insens));
+ lastChar = 0; lastCharIsSet = false;
+ index++;
+ }
+ } else if ((ch == '\\') && syntax.get(RESyntax.RE_BACKSLASH_ESCAPE_IN_LISTS)) {
+ if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
+ int posixID = -1;
+ boolean negate = false;
+ char asciiEsc = 0;
+ boolean asciiEscIsSet = false;
+ NamedProperty np = null;
+ if (("dswDSW".indexOf(pattern[index]) != -1) && syntax.get(RESyntax.RE_CHAR_CLASS_ESC_IN_LISTS)) {
+ switch (pattern[index]) {
+ case 'D':
+ negate = true;
+ case 'd':
+ posixID = RETokenPOSIX.DIGIT;
+ break;
+ case 'S':
+ negate = true;
+ case 's':
+ posixID = RETokenPOSIX.SPACE;
+ break;
+ case 'W':
+ negate = true;
+ case 'w':
+ posixID = RETokenPOSIX.ALNUM;
+ break;
+ }
+ }
+ if (("pP".indexOf(pattern[index]) != -1) && syntax.get(RESyntax.RE_NAMED_PROPERTY)) {
+ np = getNamedProperty(pattern, index - 1, pLength);
+ if (np == null)
+ throw new REException("invalid escape sequence", REException.REG_ESCAPE, index);
+ index = index - 1 + np.len - 1;
+ }
+ else {
+ CharExpression ce = getCharExpression(pattern, index - 1, pLength, syntax);
+ if (ce == null)
+ throw new REException("invalid escape sequence", REException.REG_ESCAPE, index);
+ asciiEsc = ce.ch; asciiEscIsSet = true;
+ index = index - 1 + ce.len - 1;
+ }
+ if (lastCharIsSet) options.addElement(new RETokenChar(subIndex,lastChar,insens));
+
+ if (posixID != -1) {
+ options.addElement(new RETokenPOSIX(subIndex,posixID,insens,negate));
+ } else if (np != null) {
+ options.addElement(getRETokenNamedProperty(subIndex,np,insens,index));
+ } else if (asciiEscIsSet) {
+ lastChar = asciiEsc; lastCharIsSet = true;
+ } else {
+ lastChar = pattern[index]; lastCharIsSet = true;
+ }
+ ++index;
+ } else if ((ch == '[') && (syntax.get(RESyntax.RE_CHAR_CLASSES)) && (index < pLength) && (pattern[index] == ':')) {
+ StringBuffer posixSet = new StringBuffer();
+ index = getPosixSet(pattern,index+1,posixSet);
+ int posixId = RETokenPOSIX.intValue(posixSet.toString());
+ if (posixId != -1)
+ options.addElement(new RETokenPOSIX(subIndex,posixId,insens,false));
+ } else if ((ch == '[') && (syntax.get(RESyntax.RE_NESTED_CHARCLASS))) {
+ ParseCharClassResult result = parseCharClass(
+ subIndex, pattern, index, pLength, cflags, syntax, 0);
+ addition.addElement(result.token);
+ addition.addElement("|");
+ index = result.index;
+ } else if ((ch == '&') &&
+ (syntax.get(RESyntax.RE_NESTED_CHARCLASS)) &&
+ (index < pLength) && (pattern[index] == '&')) {
+ if (returnAtAndOperator) {
+ ParseCharClassResult result = new ParseCharClassResult();
+ options.trimToSize();
+ if (additionAndAppeared) addition.addElement("&");
+ if (addition.size() == 0) addition = null;
+ result.token = new RETokenOneOf(subIndex,
+ options, addition, negative);
+ result.index = index - 1;
+ result.returnAtAndOperator = true;
+ return result;
+ }
+ // The precedence of the operator "&&" is the lowest.
+ // So we postpone adding "&" until other elements
+ // are added. And we insert Boolean.FALSE at the
+ // beginning of the list of tokens following "&&".
+ // So, "&&[a-b][k-m]" will be stored in the Vecter
+ // addition in this order:
+ // Boolean.FALSE, [a-b], "|", [k-m], "|", "&"
+ if (additionAndAppeared) addition.addElement("&");
+ addition.addElement(Boolean.FALSE);
+ additionAndAppeared = true;
+
+ // The part on which "&&" operates may be either
+ // (1) explicitly enclosed by []
+ // or
+ // (2) not enclosed by [] and terminated by the
+ // next "&&" or the end of the character list.
+ // Let the preceding else if block do the case (1).
+ // We must do something in case of (2).
+ if ((index + 1 < pLength) && (pattern[index + 1] != '[')) {
+ ParseCharClassResult result = parseCharClass(
+ subIndex, pattern, index+1, pLength, cflags, syntax,
+ RETURN_AT_AND);
+ addition.addElement(result.token);
+ addition.addElement("|");
+ // If the method returned at the next "&&", it is OK.
+ // Otherwise we have eaten the mark of the end of this
+ // character list "]". In this case we must give back
+ // the end mark.
+ index = (result.returnAtAndOperator ?
+ result.index: result.index - 1);
+ }
+ } else {
+ if (lastCharIsSet) options.addElement(new RETokenChar(subIndex,lastChar,insens));
+ lastChar = ch; lastCharIsSet = true;
+ }
+ if (index == pLength) throw new REException(getLocalizedMessage("class.no.end"),REException.REG_EBRACK,index);
+ } // while in list
+ // Out of list, index is one past ']'
+
+ if (lastCharIsSet) options.addElement(new RETokenChar(subIndex,lastChar,insens));
+
+ ParseCharClassResult result = new ParseCharClassResult();
+ // Create a new RETokenOneOf
+ options.trimToSize();
+ if (additionAndAppeared) addition.addElement("&");
+ if (addition.size() == 0) addition = null;
+ result.token = new RETokenOneOf(subIndex,options, addition, negative);
+ result.index = index;
+ return result;
+ }
+
private static int getCharUnit(char[] input, int index, CharUnit unit, boolean quot) throws REException {
unit.ch = input[index++];
unit.bk = (unit.ch == '\\'
@@ -878,6 +1188,176 @@ public class RE extends REToken {
return index;
}
+ private static int parseInt(char[] input, int pos, int len, int radix) {
+ int ret = 0;
+ for (int i = pos; i < pos + len; i++) {
+ ret = ret * radix + Character.digit(input[i], radix);
+ }
+ return ret;
+ }
+
+ /**
+ * This class represents various expressions for a character.
+ * "a" : 'a' itself.
+ * "\0123" : Octal char 0123
+ * "\x1b" : Hex char 0x1b
+ * "\u1234" : Unicode char \u1234
+ */
+ private static class CharExpression {
+ /** character represented by this expression */
+ char ch;
+ /** String expression */
+ String expr;
+ /** length of this expression */
+ int len;
+ public String toString() { return expr; }
+ }
+
+ private static CharExpression getCharExpression(char[] input, int pos, int lim,
+ RESyntax syntax) {
+ CharExpression ce = new CharExpression();
+ char c = input[pos];
+ if (c == '\\') {
+ if (pos + 1 >= lim) return null;
+ c = input[pos + 1];
+ switch(c) {
+ case 't':
+ ce.ch = '\t';
+ ce.len = 2;
+ break;
+ case 'n':
+ ce.ch = '\n';
+ ce.len = 2;
+ break;
+ case 'r':
+ ce.ch = '\r';
+ ce.len = 2;
+ break;
+ case 'x':
+ case 'u':
+ if ((c == 'x' && syntax.get(RESyntax.RE_HEX_CHAR)) ||
+ (c == 'u' && syntax.get(RESyntax.RE_UNICODE_CHAR))) {
+ int l = 0;
+ int expectedLength = (c == 'x' ? 2 : 4);
+ for (int i = pos + 2; i < pos + 2 + expectedLength; i++) {
+ if (i >= lim) break;
+ if (!((input[i] >= '0' && input[i] <= '9') ||
+ (input[i] >= 'A' && input[i] <= 'F') ||
+ (input[i] >= 'a' && input[i] <= 'f')))
+ break;
+ l++;
+ }
+ if (l != expectedLength) return null;
+ ce.ch = (char)(parseInt(input, pos + 2, l, 16));
+ ce.len = l + 2;
+ }
+ else {
+ ce.ch = c;
+ ce.len = 2;
+ }
+ break;
+ case '0':
+ if (syntax.get(RESyntax.RE_OCTAL_CHAR)) {
+ int l = 0;
+ for (int i = pos + 2; i < pos + 2 + 3; i++) {
+ if (i >= lim) break;
+ if (input[i] < '0' || input[i] > '7') break;
+ l++;
+ }
+ if (l == 3 && input[pos + 2] > '3') l--;
+ if (l <= 0) return null;
+ ce.ch = (char)(parseInt(input, pos + 2, l, 8));
+ ce.len = l + 2;
+ }
+ else {
+ ce.ch = c;
+ ce.len = 2;
+ }
+ break;
+ default:
+ ce.ch = c;
+ ce.len = 2;
+ break;
+ }
+ }
+ else {
+ ce.ch = input[pos];
+ ce.len = 1;
+ }
+ ce.expr = new String(input, pos, ce.len);
+ return ce;
+ }
+
+ /**
+ * This class represents a substring in a pattern string expressing
+ * a named property.
+ * "\pA" : Property named "A"
+ * "\p{prop}" : Property named "prop"
+ * "\PA" : Property named "A" (Negated)
+ * "\P{prop}" : Property named "prop" (Negated)
+ */
+ private static class NamedProperty {
+ /** Property name */
+ String name;
+ /** Negated or not */
+ boolean negate;
+ /** length of this expression */
+ int len;
+ }
+
+ private static NamedProperty getNamedProperty(char[] input, int pos, int lim) {
+ NamedProperty np = new NamedProperty();
+ char c = input[pos];
+ if (c == '\\') {
+ if (++pos >= lim) return null;
+ c = input[pos++];
+ switch(c) {
+ case 'p':
+ np.negate = false;
+ break;
+ case 'P':
+ np.negate = true;
+ break;
+ default:
+ return null;
+ }
+ c = input[pos++];
+ if (c == '{') {
+ int p = -1;
+ for (int i = pos; i < lim; i++) {
+ if (input[i] == '}') {
+ p = i;
+ break;
+ }
+ }
+ if (p < 0) return null;
+ int len = p - pos;
+ np.name = new String(input, pos, len);
+ np.len = len + 4;
+ }
+ else {
+ np.name = new String(input, pos - 1, 1);
+ np.len = 3;
+ }
+ return np;
+ }
+ else return null;
+ }
+
+ private static RETokenNamedProperty getRETokenNamedProperty(
+ int subIndex, NamedProperty np, boolean insens, int index)
+ throws REException {
+ try {
+ return new RETokenNamedProperty(subIndex, np.name, insens, np.negate);
+ }
+ catch (REException e) {
+ REException ree;
+ ree = new REException(e.getMessage(), REException.REG_ESCAPE, index);
+ ree.initCause(e);
+ throw ree;
+ }
+ }
+
/**
* Checks if the regular expression matches the input in its entirety.
*
@@ -958,6 +1438,10 @@ public class RE extends REToken {
return minimumLength;
}
+ public int getMaximumLength() {
+ return maximumLength;
+ }
+
/**
* Returns an array of all matches found in the input.
*
@@ -1025,7 +1509,9 @@ public class RE extends REToken {
/* Implements abstract method REToken.match() */
boolean match(CharIndexed input, REMatch mymatch) {
- if (firstToken == null) return next(input, mymatch);
+ if (firstToken == null) {
+ return next(input, mymatch);
+ }
// Note the start of this subexpression
mymatch.start[subIndex] = mymatch.index;
@@ -1089,23 +1575,34 @@ public class RE extends REToken {
}
REMatch getMatchImpl(CharIndexed input, int anchor, int eflags, StringBuffer buffer) {
+ boolean tryEntireMatch = ((eflags & REG_TRY_ENTIRE_MATCH) != 0);
+ RE re = (tryEntireMatch ? (RE) this.clone() : this);
+ if (tryEntireMatch) {
+ re.chain(new RETokenEnd(0, null));
+ }
// Create a new REMatch to hold results
REMatch mymatch = new REMatch(numSubs, anchor, eflags);
do {
// Optimization: check if anchor + minimumLength > length
if (minimumLength == 0 || input.charAt(minimumLength-1) != CharIndexed.OUT_OF_BOUNDS) {
- if (match(input, mymatch)) {
- // Find longest match of them all to observe leftmost longest
- REMatch longest = mymatch;
+ if (re.match(input, mymatch)) {
+ REMatch best = mymatch;
+ // We assume that the match that coms first is the best.
+ // And the following "The longer, the better" rule has
+ // been commented out. The longest is not neccesarily
+ // the best. For example, "a" out of "aaa" is the best
+ // match for /a+?/.
+ /*
+ // Find best match of them all to observe leftmost longest
while ((mymatch = mymatch.next) != null) {
- if (mymatch.index > longest.index) {
- longest = mymatch;
+ if (mymatch.index > best.index) {
+ best = mymatch;
}
}
-
- longest.end[0] = longest.index;
- longest.finish(input);
- return longest;
+ */
+ best.end[0] = best.index;
+ best.finish(input);
+ return best;
}
}
mymatch.clear(++anchor);
@@ -1216,8 +1713,7 @@ public class RE extends REToken {
StringBuffer buffer = new StringBuffer();
REMatch m = getMatchImpl(input,index,eflags,buffer);
if (m==null) return buffer.toString();
- buffer.append( ((eflags & REG_NO_INTERPOLATE) > 0) ?
- replace : m.substituteInto(replace) );
+ buffer.append(getReplacement(replace, m, eflags));
if (input.move(m.end[0])) {
do {
buffer.append(input.charAt(0));
@@ -1278,8 +1774,7 @@ public class RE extends REToken {
StringBuffer buffer = new StringBuffer();
REMatch m;
while ((m = getMatchImpl(input,index,eflags,buffer)) != null) {
- buffer.append( ((eflags & REG_NO_INTERPOLATE) > 0) ?
- replace : m.substituteInto(replace) );
+ buffer.append(getReplacement(replace, m, eflags));
index = m.getEndIndex();
if (m.end[0] == 0) {
char ch = input.charAt(0);
@@ -1294,11 +1789,50 @@ public class RE extends REToken {
}
return buffer.toString();
}
+
+ public static String getReplacement(String replace, REMatch m, int eflags) {
+ if ((eflags & REG_NO_INTERPOLATE) > 0)
+ return replace;
+ else {
+ if ((eflags & REG_REPLACE_USE_BACKSLASHESCAPE) > 0) {
+ StringBuffer sb = new StringBuffer();
+ int l = replace.length();
+ for (int i = 0; i < l; i++) {
+ char c = replace.charAt(i);
+ switch(c) {
+ case '\\':
+ i++;
+ // Let StringIndexOutOfBoundsException be thrown.
+ sb.append(replace.charAt(i));
+ break;
+ case '$':
+ int i1 = i + 1;
+ while (i1 < replace.length() &&
+ Character.isDigit(replace.charAt(i1))) i1++;
+ sb.append(m.substituteInto(replace.substring(i, i1)));
+ i = i1 - 1;
+ break;
+ default:
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+ else
+ return m.substituteInto(replace);
+ }
+ }
/* Helper function for constructor */
private void addToken(REToken next) {
if (next == null) return;
minimumLength += next.getMinimumLength();
+ int nmax = next.getMaximumLength();
+ if (nmax < Integer.MAX_VALUE && maximumLength < Integer.MAX_VALUE)
+ maximumLength += nmax;
+ else
+ maximumLength = Integer.MAX_VALUE;
+
if (firstToken == null) {
lastToken = firstToken = next;
} else {
diff --git a/libjava/classpath/gnu/regexp/REMatch.java b/libjava/classpath/gnu/regexp/REMatch.java
index cf25bb331c5..91a3c0249c0 100644
--- a/libjava/classpath/gnu/regexp/REMatch.java
+++ b/libjava/classpath/gnu/regexp/REMatch.java
@@ -1,5 +1,5 @@
/* gnu/regexp/REMatch.java
- Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -67,6 +67,10 @@ public final class REMatch implements Serializable, Cloneable {
int[] start; // start positions (relative to offset) for each (sub)exp.
int[] end; // end positions for the same
REMatch next; // other possibility (to avoid having to use arrays)
+ boolean empty; // empty string matched. This flag is used only within
+ // RETokenRepeated.
+ int matchFlags; // flags passed to match methods
+ static final int MF_FIND_ALL = 0x01;
public Object clone() {
try {
@@ -177,7 +181,9 @@ public final class REMatch implements Serializable, Cloneable {
* @param sub Index of the subexpression.
*/
public String toString(int sub) {
- if ((sub >= start.length) || (start[sub] == -1)) return "";
+ if ((sub >= start.length) || sub < 0)
+ throw new IndexOutOfBoundsException("No group " + sub);
+ if (start[sub] == -1) return null;
return (matchedText.substring(start[sub],end[sub]));
}
@@ -242,6 +248,8 @@ public final class REMatch implements Serializable, Cloneable {
* <code>$0</code> through <code>$9</code>. <code>$0</code> matches
* the full substring matched; <code>$<i>n</i></code> matches
* subexpression number <i>n</i>.
+ * <code>$10, $11, ...</code> may match the 10th, 11th, ... subexpressions
+ * if such subexpressions exist.
*
* @param input A string consisting of literals and <code>$<i>n</i></code> tokens.
*/
@@ -252,6 +260,16 @@ public final class REMatch implements Serializable, Cloneable {
for (pos = 0; pos < input.length()-1; pos++) {
if ((input.charAt(pos) == '$') && (Character.isDigit(input.charAt(pos+1)))) {
int val = Character.digit(input.charAt(++pos),10);
+ int pos1 = pos + 1;
+ while (pos1 < input.length() &&
+ Character.isDigit(input.charAt(pos1))) {
+ int val1 = val*10 + Character.digit(input.charAt(pos1),10);
+ if (val1 >= start.length) break;
+ pos1++;
+ val = val1;
+ }
+ pos = pos1 - 1;
+
if (val < start.length) {
output.append(toString(val));
}
@@ -260,4 +278,42 @@ public final class REMatch implements Serializable, Cloneable {
if (pos < input.length()) output.append(input.charAt(pos));
return output.toString();
}
+
+ static class REMatchList {
+ REMatch head;
+ REMatch tail;
+ REMatchList() {
+ head = tail = null;
+ }
+ /* Not used now. But we may need this some day?
+ void addHead(REMatch newone) {
+ if (head == null) {
+ head = newone;
+ tail = newone;
+ while (tail.next != null) {
+ tail = tail.next;
+ }
+ }
+ else {
+ REMatch tmp = newone;
+ while (tmp.next != null) tmp = tmp.next;
+ tmp.next = head;
+ head = newone;
+ }
+ }
+ */
+ void addTail(REMatch newone) {
+ if (head == null) {
+ head = newone;
+ tail = newone;
+ }
+ else {
+ tail.next = newone;
+ }
+ while (tail.next != null) {
+ tail = tail.next;
+ }
+ }
+ }
+
}
diff --git a/libjava/classpath/gnu/regexp/RESyntax.java b/libjava/classpath/gnu/regexp/RESyntax.java
index 7272b03481b..81fd999bfcf 100644
--- a/libjava/classpath/gnu/regexp/RESyntax.java
+++ b/libjava/classpath/gnu/regexp/RESyntax.java
@@ -1,5 +1,5 @@
/* gnu/regexp/RESyntax.java
- Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -202,7 +202,37 @@ public final class RESyntax implements Serializable {
*/
public static final int RE_POSSESSIVE_OPS = 25;
- private static final int BIT_TOTAL = 26;
+ /**
+ * Syntax bit. Allow embedded flags, (?is-x), as in Perl5.
+ */
+ public static final int RE_EMBEDDED_FLAGS = 26;
+
+ /**
+ * Syntax bit. Allow octal char (\0377), as in Perl5.
+ */
+ public static final int RE_OCTAL_CHAR = 27;
+
+ /**
+ * Syntax bit. Allow hex char (\x1b), as in Perl5.
+ */
+ public static final int RE_HEX_CHAR = 28;
+
+ /**
+ * Syntax bit. Allow Unicode char (\u1234), as in Java 1.4.
+ */
+ public static final int RE_UNICODE_CHAR = 29;
+
+ /**
+ * Syntax bit. Allow named property (\p{P}, \P{p}), as in Perl5.
+ */
+ public static final int RE_NAMED_PROPERTY = 30;
+
+ /**
+ * Syntax bit. Allow nested characterclass ([a-z&&[^p-r]]), as in Java 1.4.
+ */
+ public static final int RE_NESTED_CHARCLASS = 31;
+
+ private static final int BIT_TOTAL = 32;
/**
* Predefined syntax.
@@ -422,6 +452,10 @@ public final class RESyntax implements Serializable {
.set(RE_STRING_ANCHORS) // \A,\Z
.set(RE_CHAR_CLASS_ESC_IN_LISTS)// \d,\D,\w,\W,\s,\S within []
.set(RE_COMMENTS) // (?#)
+ .set(RE_EMBEDDED_FLAGS) // (?imsx-imsx)
+ .set(RE_OCTAL_CHAR) // \0377
+ .set(RE_HEX_CHAR) // \x1b
+ .set(RE_NAMED_PROPERTY) // \p{prop}, \P{prop}
.makeFinal();
RE_SYNTAX_PERL5_S = new RESyntax(RE_SYNTAX_PERL5)
@@ -431,6 +465,8 @@ public final class RESyntax implements Serializable {
RE_SYNTAX_JAVA_1_4 = new RESyntax(RE_SYNTAX_PERL5)
// XXX
.set(RE_POSSESSIVE_OPS) // *+,?+,++,{}+
+ .set(RE_UNICODE_CHAR) // \u1234
+ .set(RE_NESTED_CHARCLASS) // [a-z&&[^p-r]]
.makeFinal();
}
diff --git a/libjava/classpath/gnu/regexp/REToken.java b/libjava/classpath/gnu/regexp/REToken.java
index 4eae9ec473c..5f4659b21ac 100644
--- a/libjava/classpath/gnu/regexp/REToken.java
+++ b/libjava/classpath/gnu/regexp/REToken.java
@@ -38,12 +38,21 @@ exception statement from your version. */
package gnu.regexp;
import java.io.Serializable;
-abstract class REToken implements Serializable {
+abstract class REToken implements Serializable, Cloneable {
protected REToken next = null;
protected REToken uncle = null;
protected int subIndex;
+ public Object clone() {
+ try {
+ REToken copy = (REToken) super.clone();
+ return copy;
+ } catch (CloneNotSupportedException e) {
+ throw new Error(); // doesn't happen
+ }
+ }
+
protected REToken(int subIndex) {
this.subIndex = subIndex;
}
@@ -52,6 +61,10 @@ abstract class REToken implements Serializable {
return 0;
}
+ int getMaximumLength() {
+ return Integer.MAX_VALUE;
+ }
+
void setUncle(REToken anUncle) {
uncle = anUncle;
}
diff --git a/libjava/classpath/gnu/regexp/RETokenAny.java b/libjava/classpath/gnu/regexp/RETokenAny.java
index ac032dcb3bf..2b0967a79a1 100644
--- a/libjava/classpath/gnu/regexp/RETokenAny.java
+++ b/libjava/classpath/gnu/regexp/RETokenAny.java
@@ -55,6 +55,10 @@ final class RETokenAny extends REToken {
return 1;
}
+ int getMaximumLength() {
+ return 1;
+ }
+
boolean match(CharIndexed input, REMatch mymatch) {
char ch = input.charAt(mymatch.index);
if ((ch == CharIndexed.OUT_OF_BOUNDS)
diff --git a/libjava/classpath/gnu/regexp/RETokenBackRef.java b/libjava/classpath/gnu/regexp/RETokenBackRef.java
index 674822abd70..060a6cf7d20 100644
--- a/libjava/classpath/gnu/regexp/RETokenBackRef.java
+++ b/libjava/classpath/gnu/regexp/RETokenBackRef.java
@@ -51,13 +51,25 @@ final class RETokenBackRef extends REToken {
// should implement getMinimumLength() -- any ideas?
boolean match(CharIndexed input, REMatch mymatch) {
+ if (num >= mymatch.start.length) return false;
+ if (num >= mymatch.end.length) return false;
int b,e;
b = mymatch.start[num];
e = mymatch.end[num];
if ((b==-1)||(e==-1)) return false; // this shouldn't happen, but...
for (int i=b; i<e; i++) {
- if (input.charAt(mymatch.index+i-b) != input.charAt(i)) {
- return false;
+ char c1 = input.charAt(mymatch.index+i-b);
+ char c2 = input.charAt(i);
+ if (c1 != c2) {
+ if (insens) {
+ if (c1 != Character.toLowerCase(c2) &&
+ c1 != Character.toUpperCase(c2)) {
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
}
}
mymatch.index += e-b;
diff --git a/libjava/classpath/gnu/regexp/RETokenChar.java b/libjava/classpath/gnu/regexp/RETokenChar.java
index a15449b2d96..5c087c68778 100644
--- a/libjava/classpath/gnu/regexp/RETokenChar.java
+++ b/libjava/classpath/gnu/regexp/RETokenChar.java
@@ -52,6 +52,10 @@ final class RETokenChar extends REToken {
return ch.length;
}
+ int getMaximumLength() {
+ return ch.length;
+ }
+
boolean match(CharIndexed input, REMatch mymatch) {
int z = ch.length;
char c;
@@ -68,7 +72,7 @@ final class RETokenChar extends REToken {
// Overrides REToken.chain() to optimize for strings
boolean chain(REToken next) {
- if (next instanceof RETokenChar) {
+ if (next instanceof RETokenChar && ((RETokenChar)next).insens == insens) {
RETokenChar cnext = (RETokenChar) next;
// assume for now that next can only be one character
int newsize = ch.length + cnext.ch.length;
diff --git a/libjava/classpath/gnu/regexp/RETokenEnd.java b/libjava/classpath/gnu/regexp/RETokenEnd.java
index 70483b746a9..788a964da41 100644
--- a/libjava/classpath/gnu/regexp/RETokenEnd.java
+++ b/libjava/classpath/gnu/regexp/RETokenEnd.java
@@ -49,6 +49,10 @@ final class RETokenEnd extends REToken {
this.newline = newline;
}
+ int getMaximumLength() {
+ return 0;
+ }
+
boolean match(CharIndexed input, REMatch mymatch) {
char ch = input.charAt(mymatch.index);
if (ch == CharIndexed.OUT_OF_BOUNDS)
diff --git a/libjava/classpath/gnu/regexp/RETokenEndSub.java b/libjava/classpath/gnu/regexp/RETokenEndSub.java
index f3bb4f2e131..fe2969d0592 100644
--- a/libjava/classpath/gnu/regexp/RETokenEndSub.java
+++ b/libjava/classpath/gnu/regexp/RETokenEndSub.java
@@ -41,6 +41,10 @@ final class RETokenEndSub extends REToken {
RETokenEndSub(int subIndex) {
super(subIndex);
}
+
+ int getMaximumLength() {
+ return 0;
+ }
boolean match(CharIndexed input, REMatch mymatch) {
mymatch.end[subIndex] = mymatch.index;
diff --git a/libjava/classpath/gnu/regexp/RETokenIndependent.java b/libjava/classpath/gnu/regexp/RETokenIndependent.java
new file mode 100644
index 00000000000..2eb14722361
--- /dev/null
+++ b/libjava/classpath/gnu/regexp/RETokenIndependent.java
@@ -0,0 +1,76 @@
+/* gnu/regexp/RETokenIndependent.java
+ 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.regexp;
+
+/**
+ * @author Ito Kazumitsu
+ */
+final class RETokenIndependent extends REToken
+{
+ REToken re;
+
+ RETokenIndependent(REToken re) throws REException {
+ super(0);
+ this.re = re;
+ }
+
+ int getMinimumLength() {
+ return re.getMinimumLength();
+ }
+
+ int getMaximumLength() {
+ return re.getMaximumLength();
+ }
+
+ boolean match(CharIndexed input, REMatch mymatch)
+ {
+ if (re.match(input, mymatch)) {
+ // Once we have found a match, we do not see other possible matches.
+ mymatch.next = null;
+ return next(input, mymatch);
+ }
+ return false;
+ }
+
+ void dump(StringBuffer os) {
+ os.append("(?>");
+ re.dumpAll(os);
+ os.append(')');
+ }
+}
+
diff --git a/libjava/classpath/gnu/regexp/RETokenLookAhead.java b/libjava/classpath/gnu/regexp/RETokenLookAhead.java
index 33eaec9fac1..b44dfa50c4f 100644
--- a/libjava/classpath/gnu/regexp/RETokenLookAhead.java
+++ b/libjava/classpath/gnu/regexp/RETokenLookAhead.java
@@ -52,6 +52,10 @@ final class RETokenLookAhead extends REToken
this.negative = negative;
}
+ int getMaximumLength() {
+ return 0;
+ }
+
boolean match(CharIndexed input, REMatch mymatch)
{
REMatch trymatch = (REMatch)mymatch.clone();
diff --git a/libjava/classpath/gnu/regexp/RETokenLookBehind.java b/libjava/classpath/gnu/regexp/RETokenLookBehind.java
new file mode 100644
index 00000000000..a6c1b34cb0b
--- /dev/null
+++ b/libjava/classpath/gnu/regexp/RETokenLookBehind.java
@@ -0,0 +1,116 @@
+/* gnu/regexp/RETokenLookBehind.java
+ 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.regexp;
+
+/**
+ * @author Ito Kazumitsu
+ */
+final class RETokenLookBehind extends REToken
+{
+ REToken re;
+ boolean negative;
+
+ RETokenLookBehind(REToken re, boolean negative) throws REException {
+ super(0);
+ this.re = re;
+ this.negative = negative;
+ }
+
+ int getMaximumLength() {
+ return 0;
+ }
+
+ boolean match(CharIndexed input, REMatch mymatch)
+ {
+ int max = re.getMaximumLength();
+ CharIndexed behind = input.lookBehind(mymatch.index, max);
+ REMatch trymatch = (REMatch)mymatch.clone();
+ REMatch trymatch1 = (REMatch)mymatch.clone();
+ REMatch newMatch = null;
+ int curIndex = trymatch.index + behind.length() - input.length();
+ trymatch.index = 0;
+ RETokenMatchHereOnly stopper = new RETokenMatchHereOnly(curIndex);
+ REToken re1 = (REToken) re.clone();
+ re1.chain(stopper);
+ if (re1.match(behind, trymatch)) {
+ if (negative) return false;
+ if (next(input, trymatch1))
+ newMatch = trymatch1;
+ }
+
+ if (newMatch != null) {
+ if (negative) return false;
+ //else
+ mymatch.assignFrom(newMatch);
+ return true;
+ }
+ else { // no match
+ if (negative)
+ return next(input, mymatch);
+ //else
+ return false;
+ }
+ }
+
+ void dump(StringBuffer os) {
+ os.append("(?<");
+ os.append(negative ? '!' : '=');
+ re.dumpAll(os);
+ os.append(')');
+ }
+
+ private static class RETokenMatchHereOnly extends REToken {
+
+ int getMaximumLength() { return 0; }
+
+ private int index;
+
+ RETokenMatchHereOnly(int index) {
+ super(0);
+ this.index = index;
+ }
+
+ boolean match(CharIndexed input, REMatch mymatch) {
+ return index == mymatch.index;
+ }
+
+ void dump(StringBuffer os) {}
+
+ }
+}
+
diff --git a/libjava/classpath/gnu/regexp/RETokenNamedProperty.java b/libjava/classpath/gnu/regexp/RETokenNamedProperty.java
new file mode 100644
index 00000000000..13c1e418a09
--- /dev/null
+++ b/libjava/classpath/gnu/regexp/RETokenNamedProperty.java
@@ -0,0 +1,301 @@
+/* gnu/regexp/RETokenNamedProperty.java
+ 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.regexp;
+
+final class RETokenNamedProperty extends REToken {
+ String name;
+ boolean insens;
+ boolean negate;
+ Handler handler;
+
+ // Grouped properties
+ static final byte[] LETTER = new byte[]
+ { Character.LOWERCASE_LETTER,
+ Character.UPPERCASE_LETTER,
+ Character.TITLECASE_LETTER,
+ Character.MODIFIER_LETTER,
+ Character.OTHER_LETTER };
+
+ static final byte[] MARK = new byte[]
+ { Character.NON_SPACING_MARK,
+ Character.COMBINING_SPACING_MARK,
+ Character.ENCLOSING_MARK };
+
+ static final byte[] SEPARATOR = new byte[]
+ { Character.SPACE_SEPARATOR,
+ Character.LINE_SEPARATOR,
+ Character.PARAGRAPH_SEPARATOR };
+
+ static final byte[] SYMBOL = new byte[]
+ { Character.MATH_SYMBOL,
+ Character.CURRENCY_SYMBOL,
+ Character.MODIFIER_SYMBOL,
+ Character.OTHER_SYMBOL };
+
+ static final byte[] NUMBER = new byte[]
+ { Character.DECIMAL_DIGIT_NUMBER,
+ Character.LETTER_NUMBER,
+ Character.OTHER_NUMBER };
+
+ static final byte[] PUNCTUATION = new byte[]
+ { Character.DASH_PUNCTUATION,
+ Character.START_PUNCTUATION,
+ Character.END_PUNCTUATION,
+ Character.CONNECTOR_PUNCTUATION,
+ Character.OTHER_PUNCTUATION,
+ Character.INITIAL_QUOTE_PUNCTUATION,
+ Character.FINAL_QUOTE_PUNCTUATION};
+
+ static final byte[] OTHER = new byte[]
+ { Character.CONTROL,
+ Character.FORMAT,
+ Character.PRIVATE_USE,
+ Character.SURROGATE,
+ Character.UNASSIGNED };
+
+ RETokenNamedProperty(int subIndex, String name, boolean insens, boolean negate) throws REException {
+ super(subIndex);
+ this.name = name;
+ this.insens = insens;
+ this.negate = negate;
+ handler = getHandler(name);
+ }
+
+ int getMinimumLength() {
+ return 1;
+ }
+
+ int getMaximumLength() {
+ return 1;
+ }
+
+ boolean match(CharIndexed input, REMatch mymatch) {
+ char ch = input.charAt(mymatch.index);
+ if (ch == CharIndexed.OUT_OF_BOUNDS)
+ return false;
+
+ boolean retval = handler.includes(ch);
+ if (insens) {
+ retval = retval ||
+ handler.includes(Character.toUpperCase(ch)) ||
+ handler.includes(Character.toLowerCase(ch));
+ }
+
+ if (negate) retval = !retval;
+ if (retval) {
+ ++mymatch.index;
+ return next(input, mymatch);
+ }
+ else return false;
+ }
+
+ void dump(StringBuffer os) {
+ os.append("\\")
+ .append(negate ? "P" : "p")
+ .append("{" + name + "}");
+ }
+
+ private abstract static class Handler {
+ public abstract boolean includes(char c);
+ }
+
+ private Handler getHandler(String name) throws REException {
+ if (name.equals("Lower") ||
+ name.equals("Upper") ||
+ // name.equals("ASCII") ||
+ name.equals("Alpha") ||
+ name.equals("Digit") ||
+ name.equals("Alnum") ||
+ name.equals("Punct") ||
+ name.equals("Graph") ||
+ name.equals("Print") ||
+ name.equals("Blank") ||
+ name.equals("Cntrl") ||
+ name.equals("XDigit") ||
+ name.equals("Space") ) {
+ return new POSIXHandler(name);
+ }
+ if (name.startsWith("In")) {
+ try {
+ name = name.substring(2);
+ Character.UnicodeBlock block = Character.UnicodeBlock.forName(name);
+ return new UnicodeBlockHandler(block);
+ }
+ catch (IllegalArgumentException e) {
+ throw new REException("Invalid Unicode block name: " + name, REException.REG_ESCAPE, 0);
+ }
+ }
+ if (name.startsWith("Is")) {
+ name = name.substring(2);
+ }
+
+ // "grouped properties"
+ if (name.equals("L"))
+ return new UnicodeCategoriesHandler(LETTER);
+ if (name.equals("M"))
+ return new UnicodeCategoriesHandler(MARK);
+ if (name.equals("Z"))
+ return new UnicodeCategoriesHandler(SEPARATOR);
+ if (name.equals("S"))
+ return new UnicodeCategoriesHandler(SYMBOL);
+ if (name.equals("N"))
+ return new UnicodeCategoriesHandler(NUMBER);
+ if (name.equals("P"))
+ return new UnicodeCategoriesHandler(PUNCTUATION);
+ if (name.equals("C"))
+ return new UnicodeCategoriesHandler(OTHER);
+
+ if (name.equals("Mc"))
+ return new UnicodeCategoryHandler(Character.COMBINING_SPACING_MARK);
+ if (name.equals("Pc"))
+ return new UnicodeCategoryHandler(Character.CONNECTOR_PUNCTUATION);
+ if (name.equals("Cc"))
+ return new UnicodeCategoryHandler(Character.CONTROL);
+ if (name.equals("Sc"))
+ return new UnicodeCategoryHandler(Character.CURRENCY_SYMBOL);
+ if (name.equals("Pd"))
+ return new UnicodeCategoryHandler(Character.DASH_PUNCTUATION);
+ if (name.equals("Nd"))
+ return new UnicodeCategoryHandler(Character.DECIMAL_DIGIT_NUMBER);
+ if (name.equals("Me"))
+ return new UnicodeCategoryHandler(Character.ENCLOSING_MARK);
+ if (name.equals("Pe"))
+ return new UnicodeCategoryHandler(Character.END_PUNCTUATION);
+ if (name.equals("Pf"))
+ return new UnicodeCategoryHandler(Character.FINAL_QUOTE_PUNCTUATION);
+ if (name.equals("Cf"))
+ return new UnicodeCategoryHandler(Character.FORMAT);
+ if (name.equals("Pi"))
+ return new UnicodeCategoryHandler(Character.INITIAL_QUOTE_PUNCTUATION);
+ if (name.equals("Nl"))
+ return new UnicodeCategoryHandler(Character.LETTER_NUMBER);
+ if (name.equals("Zl"))
+ return new UnicodeCategoryHandler(Character.LINE_SEPARATOR);
+ if (name.equals("Ll"))
+ return new UnicodeCategoryHandler(Character.LOWERCASE_LETTER);
+ if (name.equals("Sm"))
+ return new UnicodeCategoryHandler(Character.MATH_SYMBOL);
+ if (name.equals("Lm"))
+ return new UnicodeCategoryHandler(Character.MODIFIER_LETTER);
+ if (name.equals("Sk"))
+ return new UnicodeCategoryHandler(Character.MODIFIER_SYMBOL);
+ if (name.equals("Mn"))
+ return new UnicodeCategoryHandler(Character.NON_SPACING_MARK);
+ if (name.equals("Lo"))
+ return new UnicodeCategoryHandler(Character.OTHER_LETTER);
+ if (name.equals("No"))
+ return new UnicodeCategoryHandler(Character.OTHER_NUMBER);
+ if (name.equals("Po"))
+ return new UnicodeCategoryHandler(Character.OTHER_PUNCTUATION);
+ if (name.equals("So"))
+ return new UnicodeCategoryHandler(Character.OTHER_SYMBOL);
+ if (name.equals("Zp"))
+ return new UnicodeCategoryHandler(Character.PARAGRAPH_SEPARATOR);
+ if (name.equals("Co"))
+ return new UnicodeCategoryHandler(Character.PRIVATE_USE);
+ if (name.equals("Zs"))
+ return new UnicodeCategoryHandler(Character.SPACE_SEPARATOR);
+ if (name.equals("Ps"))
+ return new UnicodeCategoryHandler(Character.START_PUNCTUATION);
+ if (name.equals("Cs"))
+ return new UnicodeCategoryHandler(Character.SURROGATE);
+ if (name.equals("Lt"))
+ return new UnicodeCategoryHandler(Character.TITLECASE_LETTER);
+ if (name.equals("Cn"))
+ return new UnicodeCategoryHandler(Character.UNASSIGNED);
+ if (name.equals("Lu"))
+ return new UnicodeCategoryHandler(Character.UPPERCASE_LETTER);
+ throw new REException("unsupported name " + name, REException.REG_ESCAPE, 0);
+ }
+
+ private static class POSIXHandler extends Handler {
+ private RETokenPOSIX retoken;
+ private REMatch mymatch = new REMatch(0,0,0);
+ private char[] chars = new char[1];
+ private CharIndexedCharArray ca = new CharIndexedCharArray(chars, 0);
+ public POSIXHandler(String name) {
+ int posixId = RETokenPOSIX.intValue(name.toLowerCase());
+ if (posixId != -1)
+ retoken = new RETokenPOSIX(0,posixId,false,false);
+ else
+ throw new RuntimeException("Unknown posix ID: " + name);
+ }
+ public boolean includes(char c) {
+ chars[0] = c;
+ mymatch.index = 0;
+ return retoken.match(ca, mymatch);
+ }
+ }
+
+ private static class UnicodeCategoryHandler extends Handler {
+ public UnicodeCategoryHandler(byte category) {
+ this.category = (int)category;
+ }
+ private int category;
+ public boolean includes(char c) {
+ return Character.getType(c) == category;
+ }
+ }
+
+ private static class UnicodeCategoriesHandler extends Handler {
+ public UnicodeCategoriesHandler(byte[] categories) {
+ this.categories = categories;
+ }
+ private byte[] categories;
+ public boolean includes(char c) {
+ int category = Character.getType(c);
+ for (int i = 0; i < categories.length; i++)
+ if (category == categories[i])
+ return true;
+ return false;
+ }
+ }
+
+ private static class UnicodeBlockHandler extends Handler {
+ public UnicodeBlockHandler(Character.UnicodeBlock block) {
+ this.block = block;
+ }
+ private Character.UnicodeBlock block;
+ public boolean includes(char c) {
+ Character.UnicodeBlock cblock = Character.UnicodeBlock.of(c);
+ return (cblock != null && cblock.equals(block));
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/regexp/RETokenOneOf.java b/libjava/classpath/gnu/regexp/RETokenOneOf.java
index 3f6e89e2103..260bc4b8f67 100644
--- a/libjava/classpath/gnu/regexp/RETokenOneOf.java
+++ b/libjava/classpath/gnu/regexp/RETokenOneOf.java
@@ -1,5 +1,5 @@
/* gnu/regexp/RETokenOneOf.java
- Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,11 +37,35 @@ exception statement from your version. */
package gnu.regexp;
import java.util.Vector;
+import java.util.Stack;
final class RETokenOneOf extends REToken {
private Vector options;
private boolean negative;
+ private Vector addition;
+ // This Vector addition is used to store nested character classes.
+ // For example, if the original expression is
+ // [2-7a-c[f-k][m-z]&&[^p-v][st]]
+ // the basic part /2-7a-c/ is stored in the Vector options, and
+ // the additional part /[f-k][m-z]&&[^p-v][st]/ is stored in the
+ // Vector addition in the following order (Reverse Polish Notation):
+ // -- The matching result of the basic part is assumed here.
+ // [f-k] -- REToken
+ // "|" -- or
+ // [m-z] -- REToken
+ // "|" -- or
+ // false
+ // [^p-v] -- REToken
+ // "|" -- or
+ // [st] -- REToken
+ // "|" -- or
+ // "&" -- and
+ //
+ // As it is clear from the explanation above, the Vector addition is
+ // effective only when this REToken originates from a character class
+ // expression.
+
// This constructor is used for convenience when we know the set beforehand,
// e.g. \d --> new RETokenOneOf("0123456789",false, ..)
// \D --> new RETokenOneOf("0123456789",true, ..)
@@ -60,7 +84,17 @@ final class RETokenOneOf extends REToken {
this.negative = negative;
}
+ RETokenOneOf(int subIndex, Vector options, Vector addition, boolean negative) {
+ super(subIndex);
+ this.options = options;
+ this.addition = addition;
+ this.negative = negative;
+ }
+
int getMinimumLength() {
+ // (negative || addition != null) occurs when this token originates from
+ // character class expression.
+ if (negative || addition != null) return 1;
int min = Integer.MAX_VALUE;
int x;
for (int i=0; i < options.size(); i++) {
@@ -70,54 +104,123 @@ final class RETokenOneOf extends REToken {
return min;
}
+ int getMaximumLength() {
+ // (negative || addition != null) occurs when this token originates from
+ // character class expression.
+ if (negative || addition != null) return 1;
+ int max = 0;
+ int x;
+ for (int i=0; i < options.size(); i++) {
+ if ((x = ((REToken) options.elementAt(i)).getMaximumLength()) > max)
+ max = x;
+ }
+ return max;
+ }
+
boolean match(CharIndexed input, REMatch mymatch) {
- if (negative && (input.charAt(mymatch.index) == CharIndexed.OUT_OF_BOUNDS))
+ REMatch tryMatch;
+ boolean tryOnly;
+ if (addition == null) {
+ tryMatch = mymatch;
+ tryOnly = false;
+ }
+ else {
+ tryMatch = (REMatch) mymatch.clone();
+ tryOnly = true;
+ }
+ boolean b = negative ?
+ matchN(input, tryMatch, tryOnly) :
+ matchP(input, tryMatch, tryOnly);
+ if (addition == null) return b;
+
+ Stack stack = new Stack();
+ stack.push(new Boolean(b));
+ for (int i=0; i < addition.size(); i++) {
+ Object obj = addition.elementAt(i);
+ if (obj instanceof REToken) {
+ b = ((REToken)obj).match(input, (REMatch)mymatch.clone());
+ stack.push(new Boolean(b));
+ }
+ else if (obj instanceof Boolean) {
+ stack.push(obj);
+ }
+ else if (obj.equals("|")) {
+ b = ((Boolean)stack.pop()).booleanValue();
+ b = ((Boolean)stack.pop()).booleanValue() || b;
+ stack.push(new Boolean(b));
+ }
+ else if (obj.equals("&")) {
+ b = ((Boolean)stack.pop()).booleanValue();
+ b = ((Boolean)stack.pop()).booleanValue() && b;
+ stack.push(new Boolean(b));
+ }
+ else {
+ throw new RuntimeException("Invalid object found");
+ }
+ }
+ b = ((Boolean)stack.pop()).booleanValue();
+ if (b) {
+ ++mymatch.index;
+ return next(input, mymatch);
+ }
return false;
+ }
- REMatch newMatch = null;
- REMatch last = null;
- REToken tk;
- boolean isMatch;
- for (int i=0; i < options.size(); i++) {
+ private boolean matchN(CharIndexed input, REMatch mymatch, boolean tryOnly) {
+ if (input.charAt(mymatch.index) == CharIndexed.OUT_OF_BOUNDS)
+ return false;
+
+ REMatch newMatch = null;
+ REMatch last = null;
+ REToken tk;
+ for (int i=0; i < options.size(); i++) {
tk = (REToken) options.elementAt(i);
REMatch tryMatch = (REMatch) mymatch.clone();
if (tk.match(input, tryMatch)) { // match was successful
- if (negative) return false;
-
- if (next(input, tryMatch)) {
- // Add tryMatch to list of possibilities.
- if (last == null) {
- newMatch = tryMatch;
- last = tryMatch;
- } else {
- last.next = tryMatch;
- last = tryMatch;
- }
- } // next succeeds
- } // is a match
- } // try next option
-
- if (newMatch != null) {
- if (negative) {
return false;
- } else {
- // set contents of mymatch equal to newMatch
+ } // is a match
+ } // try next option
- // try each one that matched
- mymatch.assignFrom(newMatch);
- return true;
- }
- } else {
- if (negative) {
- ++mymatch.index;
- return next(input, mymatch);
- } else {
- return false;
- }
+ if (tryOnly) return true;
+ ++mymatch.index;
+ return next(input, mymatch);
}
- // index+1 works for [^abc] lists, not for generic lookahead (--> index)
- }
+ private boolean matchP(CharIndexed input, REMatch mymatch, boolean tryOnly) {
+ boolean stopMatchingIfSatisfied =
+ (mymatch.matchFlags & REMatch.MF_FIND_ALL) == 0;
+ REMatch.REMatchList newMatch = new REMatch.REMatchList();
+ REToken tk;
+ for (int i=0; i < options.size(); i++) {
+ // In order that the backtracking can work,
+ // each option must be chained to the next token.
+ // But the chain method has some side effect, so
+ // we use clones.
+ tk = (REToken)((REToken) options.elementAt(i)).clone();
+ if (! tryOnly) {
+ tk.chain(this.next);
+ tk.setUncle(this.uncle);
+ tk.subIndex = this.subIndex;
+ }
+ REMatch tryMatch = (REMatch) mymatch.clone();
+ if (tk.match(input, tryMatch)) { // match was successful
+ if (tryOnly) return true;
+ newMatch.addTail(tryMatch);
+ if (stopMatchingIfSatisfied) break;
+ } // is a match
+ } // try next option
+ if (tryOnly) return false;
+
+ if (newMatch.head != null) {
+ // set contents of mymatch equal to newMatch
+
+ // try each one that matched
+ mymatch.assignFrom(newMatch.head);
+ return true;
+ } else {
+ return false;
+ }
+ }
void dump(StringBuffer os) {
os.append(negative ? "[^" : "(?:");
diff --git a/libjava/classpath/gnu/regexp/RETokenPOSIX.java b/libjava/classpath/gnu/regexp/RETokenPOSIX.java
index bbb8066bca8..4182c6fab98 100644
--- a/libjava/classpath/gnu/regexp/RETokenPOSIX.java
+++ b/libjava/classpath/gnu/regexp/RETokenPOSIX.java
@@ -81,6 +81,10 @@ final class RETokenPOSIX extends REToken {
return 1;
}
+ int getMaximumLength() {
+ return 1;
+ }
+
boolean match(CharIndexed input, REMatch mymatch) {
char ch = input.charAt(mymatch.index);
if (ch == CharIndexed.OUT_OF_BOUNDS)
diff --git a/libjava/classpath/gnu/regexp/RETokenRange.java b/libjava/classpath/gnu/regexp/RETokenRange.java
index dadaf2d8072..8a1ac86b212 100644
--- a/libjava/classpath/gnu/regexp/RETokenRange.java
+++ b/libjava/classpath/gnu/regexp/RETokenRange.java
@@ -43,19 +43,32 @@ final class RETokenRange extends REToken {
RETokenRange(int subIndex, char lo, char hi, boolean ins) {
super(subIndex);
- this.lo = (insens = ins) ? Character.toLowerCase(lo) : lo;
- this.hi = ins ? Character.toLowerCase(hi) : hi;
+ insens = ins;
+ this.lo = lo;
+ this.hi = hi;
}
int getMinimumLength() {
return 1;
}
+ int getMaximumLength() {
+ return 1;
+ }
+
boolean match(CharIndexed input, REMatch mymatch) {
char c = input.charAt(mymatch.index);
if (c == CharIndexed.OUT_OF_BOUNDS) return false;
- if (insens) c = Character.toLowerCase(c);
- if ((c >= lo) && (c <= hi)) {
+ boolean matches = (c >= lo) && (c <= hi);
+ if (! matches && insens) {
+ char c1 = Character.toLowerCase(c);
+ matches = (c1 >= lo) && (c1 <= hi);
+ if (!matches) {
+ c1 = Character.toUpperCase(c);
+ matches = (c1 >= lo) && (c1 <= hi);
+ }
+ }
+ if (matches) {
++mymatch.index;
return next(input, mymatch);
}
diff --git a/libjava/classpath/gnu/regexp/RETokenRepeated.java b/libjava/classpath/gnu/regexp/RETokenRepeated.java
index 6291a3c3960..2d019c53cbd 100644
--- a/libjava/classpath/gnu/regexp/RETokenRepeated.java
+++ b/libjava/classpath/gnu/regexp/RETokenRepeated.java
@@ -1,5 +1,5 @@
/* gnu/regexp/RETokenRepeated.java
- Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ exception statement from your version. */
package gnu.regexp;
import java.util.Vector;
+import java.util.Arrays;
final class RETokenRepeated extends REToken {
private REToken token;
@@ -82,6 +83,38 @@ final class RETokenRepeated extends REToken {
return (min * token.getMinimumLength());
}
+ int getMaximumLength() {
+ if (max == Integer.MAX_VALUE) return Integer.MAX_VALUE;
+ int tmax = token.getMaximumLength();
+ if (tmax == Integer.MAX_VALUE) return tmax;
+ return (max * tmax);
+ }
+
+ private static REMatch findDoables(REToken tk,
+ CharIndexed input, REMatch mymatch) {
+
+ REMatch.REMatchList doables = new REMatch.REMatchList();
+
+ // try next repeat at all possible positions
+ for (REMatch current = mymatch;
+ current != null; current = current.next) {
+ REMatch recurrent = (REMatch) current.clone();
+ int origin = recurrent.index;
+ tk = (REToken) tk.clone();
+ tk.next = tk.uncle = null;
+ recurrent.matchFlags |= REMatch.MF_FIND_ALL;
+ if (tk.match(input, recurrent)) {
+ for (REMatch m = recurrent; m != null; m = m.next) {
+ m.matchFlags &= ~REMatch.MF_FIND_ALL;
+ }
+ if (recurrent.index == origin) recurrent.empty = true;
+ // add all items in current to doables array
+ doables.addTail(recurrent);
+ }
+ }
+ return doables.head;
+ }
+
// We do need to save every possible point, but the number of clone()
// invocations here is really a killer for performance on non-stingy
// repeat operators. I'm open to suggestions...
@@ -91,59 +124,167 @@ final class RETokenRepeated extends REToken {
// the subexpression back-reference operator allow that?
boolean match(CharIndexed input, REMatch mymatch) {
- // number of times we've matched so far
- int numRepeats = 0;
-
- // Possible positions for the next repeat to match at
- REMatch newMatch = mymatch;
- REMatch last = null;
- REMatch current;
- // Add the '0-repeats' index
- // positions.elementAt(z) == position [] in input after <<z>> matches
- Vector positions = new Vector();
- positions.addElement(newMatch);
-
- // Declare variables used in loop
- REMatch doables;
- REMatch doablesLast;
- REMatch recurrent;
- int lastIndex = mymatch.index;
-
- do {
- // Check for stingy match for each possibility.
- if (stingy && (numRepeats >= min)) {
- REMatch result = matchRest(input, newMatch);
- if (result != null) {
- mymatch.assignFrom(result);
- return true;
- }
+ boolean stopMatchingIfSatisfied =
+ (mymatch.matchFlags & REMatch.MF_FIND_ALL) == 0;
+
+ REMatch newMatch = matchMinimum(input, mymatch);
+ if (newMatch == null) return false;
+
+ // Array of positions we have already visited
+ int[] visited = initVisited();
+ for (REMatch m = newMatch; m != null; m = m.next) {
+ visited = addVisited(m.index, visited);
+ }
+
+ int max1 = decreaseMax(max, min);
+
+ newMatch = _match(input, newMatch, max1,
+ stopMatchingIfSatisfied, visited);
+ if (newMatch != null) {
+ mymatch.assignFrom(newMatch);
+ return true;
+ }
+ return false;
+ }
+
+ private static int decreaseMax(int m, int n) {
+ if (m == Integer.MAX_VALUE) return m;
+ return m - n;
+ }
+
+ // Array visited is an array of character positions we have already
+ // visited. visited[0] is used to store the effective length of the
+ // array.
+ private static int[] initVisited() {
+ int[] visited = new int[32];
+ visited[0] = 0;
+ return visited;
+ }
+
+ private static boolean visitedContains(int n, int[] visited) {
+ // Experience tells that for a small array like this,
+ // simple linear search is faster than binary search.
+ for (int i = 1; i < visited[0]; i++) {
+ if (n == visited[i]) return true;
+ }
+ return false;
+ }
+
+ private static int[] addVisited(int n, int[] visited) {
+ if (visitedContains(n, visited)) return visited;
+ if (visited[0] >= visited.length - 1) {
+ int[] newvisited = new int[visited.length + 32];
+ System.arraycopy(visited, 0, newvisited, 0, visited.length);
+ visited = newvisited;
+ }
+ visited[0]++;
+ visited[visited[0]] = n;
+ return visited;
+ }
+
+ private REMatch _match(CharIndexed input, REMatch mymatch,
+ int max1, boolean stopMatchingIfSatisfied,
+ int[] visited) {
+
+ if (max1 == 0) {
+ return matchRest(input, mymatch);
+ }
+ max1 = decreaseMax(max1, 1);
+
+ REMatch.REMatchList allResults = new REMatch.REMatchList();
+
+ // Depth-first search
+
+ for (REMatch cur = mymatch; cur != null; cur = cur.next) {
+
+ REMatch cur1 = (REMatch) cur.clone();
+
+ if (stingy) {
+ REMatch results = matchRest(input, cur1);
+ if (results != null) {
+ if (stopMatchingIfSatisfied) {
+ return results;
+ }
+ allResults.addTail(results);
+ }
}
- doables = null;
- doablesLast = null;
+ DO_THIS:
+ do {
- // try next repeat at all possible positions
- for (current = newMatch; current != null; current = current.next) {
- recurrent = (REMatch) current.clone();
- if (token.match(input, recurrent)) {
- // add all items in current to doables array
- if (doables == null) {
- doables = recurrent;
- doablesLast = recurrent;
- } else {
- // Order these from longest to shortest
- // Start by assuming longest (more repeats)
- doablesLast.next = recurrent;
+ boolean emptyMatchFound = false;
+ REMatch doables = findDoables(token, input, cur1);
+ if (doables == null) break DO_THIS;
+ if (doables.empty) emptyMatchFound = true;
+
+ if (!emptyMatchFound) {
+ REMatch.REMatchList list = new REMatch.REMatchList();
+ for (REMatch m = doables; m != null; m = m.next) {
+ REMatch m1 = (REMatch) m.clone();
+ int n = m1.index;
+ if (! visitedContains(n, visited)) {
+ visited = addVisited(n, visited);
+ list.addTail(m1);
}
- // Find new doablesLast
- while (doablesLast.next != null) {
- doablesLast = doablesLast.next;
+ }
+ if (list.head == null) break DO_THIS;
+ doables = list.head;
+ }
+
+ for (REMatch m = doables; m != null; m = m.next) {
+ if (! emptyMatchFound) {
+ REMatch m1 = _match(input, m, max1,
+ stopMatchingIfSatisfied, visited);
+ if (possessive) return m1;
+ if (m1 != null) {
+ if (stopMatchingIfSatisfied) {
+ return m1;
+ }
+ allResults.addTail(m1);
+ }
+ }
+ else {
+ REMatch m1 = matchRest(input, m);
+ if (m1 != null) {
+ if (stopMatchingIfSatisfied) {
+ return m1;
+ }
+ allResults.addTail(m1);
}
}
}
- // if none of the possibilities worked out, break out of do/while
- if (doables == null) break;
+
+ } while (false); // DO_THIS only once;
+
+ // This point itself is a candidate.
+ if (!stingy) {
+ REMatch m2 = matchRest(input, cur1);
+ if (m2 != null) {
+ if (stopMatchingIfSatisfied) {
+ return m2;
+ }
+ allResults.addTail(m2);
+ }
+ }
+ }
+
+ return allResults.head;
+ }
+
+ private REMatch matchMinimum(CharIndexed input, final REMatch mymatch) {
+ // Possible positions for the next repeat to match at
+ REMatch newMatch = mymatch;
+
+ // number of times we've matched so far
+ int numRepeats = 0;
+
+ while (numRepeats < min) {
+ REMatch doables = findDoables(token, input, newMatch);
+
+ // if none of the possibilities worked out,
+ // it means that minimum number of repeats could not be found.
+ if (doables == null) return null;
// reassign where the next repeat can match
newMatch = doables;
@@ -151,91 +292,24 @@ final class RETokenRepeated extends REToken {
// increment how many repeats we've successfully found
++numRepeats;
- positions.addElement(newMatch);
-
- // doables.index == lastIndex means an empty string
- // was the longest that matched this token.
- // We break here, otherwise we will fall into an endless loop.
- if (doables.index == lastIndex) {
- if (numRepeats < min) numRepeats = min;
- break;
- }
- lastIndex = doables.index;
- } while (numRepeats < max);
-
- // If there aren't enough repeats, then fail
- if (numRepeats < min) return false;
-
- // We're greedy, but ease off until a true match is found
- int posIndex = positions.size();
-
- // At this point we've either got too many or just the right amount.
- // See if this numRepeats works with the rest of the regexp.
- REMatch allResults = null;
- REMatch allResultsLast = null;
-
- REMatch results = null;
- int indexCount = posIndex - min;
- if (indexCount <= 0) {
- // This case occurs when we exited the previous do loop before
- // numRepeats >= min because an empty string matched the token.
- // In this case, an empty string can match as many times as
- // desired.
- indexCount = 1;
- }
- while (indexCount-- > 0) {
- --posIndex;
- newMatch = (REMatch) positions.elementAt(posIndex);
- results = matchRest(input, newMatch);
- if (results != null) {
- if (allResults == null) {
- allResults = results;
- allResultsLast = results;
- } else {
- // Order these from longest to shortest
- // Start by assuming longest (more repeats)
- allResultsLast.next = results;
- }
- // Find new doablesLast
- while (allResultsLast.next != null) {
- allResultsLast = allResultsLast.next;
- }
- }
- // else did not match rest of the tokens, try again on smaller sample
- // or break out when performing possessive matching
- if (possessive) break;
+ if (newMatch.empty) break;
}
- if (allResults != null) {
- mymatch.assignFrom(allResults); // does this get all?
- return true;
- }
- // If we fall out, no matches.
- return false;
+ return newMatch;
}
private REMatch matchRest(CharIndexed input, final REMatch newMatch) {
REMatch current, single;
- REMatch doneIndex = null;
- REMatch doneIndexLast = null;
+ REMatch.REMatchList doneIndex = new REMatch.REMatchList();
// Test all possible matches for this number of repeats
for (current = newMatch; current != null; current = current.next) {
// clone() separates a single match from the chain
single = (REMatch) current.clone();
if (next(input, single)) {
// chain results to doneIndex
- if (doneIndex == null) {
- doneIndex = single;
- doneIndexLast = single;
- } else {
- doneIndexLast.next = single;
- }
- // Find new doneIndexLast
- while (doneIndexLast.next != null) {
- doneIndexLast = doneIndexLast.next;
- }
+ doneIndex.addTail(single);
}
}
- return doneIndex;
+ return doneIndex.head;
}
void dump(StringBuffer os) {
diff --git a/libjava/classpath/gnu/regexp/RETokenStart.java b/libjava/classpath/gnu/regexp/RETokenStart.java
index 8f7198237e1..42e3c0b2de0 100644
--- a/libjava/classpath/gnu/regexp/RETokenStart.java
+++ b/libjava/classpath/gnu/regexp/RETokenStart.java
@@ -44,6 +44,10 @@ class RETokenStart extends REToken {
super(subIndex);
this.newline = newline;
}
+
+ int getMaximumLength() {
+ return 0;
+ }
boolean match(CharIndexed input, REMatch mymatch) {
// charAt(index-n) may be unknown on a Reader/InputStream. FIXME
diff --git a/libjava/classpath/gnu/regexp/RETokenWordBoundary.java b/libjava/classpath/gnu/regexp/RETokenWordBoundary.java
index 6804151e261..f86214bbf68 100644
--- a/libjava/classpath/gnu/regexp/RETokenWordBoundary.java
+++ b/libjava/classpath/gnu/regexp/RETokenWordBoundary.java
@@ -52,6 +52,11 @@ final class RETokenWordBoundary extends REToken {
this.where = where;
this.negated = negated;
}
+
+ int getMaximumLength() {
+ return 0;
+ }
+
boolean match(CharIndexed input, REMatch mymatch) {
// Word boundary means input[index-1] was a word character
diff --git a/libjava/classpath/gnu/xml/aelfred2/XmlParser.java b/libjava/classpath/gnu/xml/aelfred2/XmlParser.java
index ab2ed16f946..37466ca1c05 100644
--- a/libjava/classpath/gnu/xml/aelfred2/XmlParser.java
+++ b/libjava/classpath/gnu/xml/aelfred2/XmlParser.java
@@ -2182,6 +2182,7 @@ loop:
{
nest++;
}
+ break;
case ']':
if (tryRead("]>"))
{
diff --git a/libjava/classpath/gnu/xml/dom/DomCharacterData.java b/libjava/classpath/gnu/xml/dom/DomCharacterData.java
index e94dcc4ecf9..1eec5bea734 100644
--- a/libjava/classpath/gnu/xml/dom/DomCharacterData.java
+++ b/libjava/classpath/gnu/xml/dom/DomCharacterData.java
@@ -1,5 +1,5 @@
/* DomCharacterData.java --
- Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
+ Copyright (C) 1999,2000,2001,2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,8 @@ package gnu.xml.dom;
import org.w3c.dom.CharacterData;
import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.w3c.dom.events.MutationEvent;
@@ -55,6 +57,30 @@ public abstract class DomCharacterData
implements CharacterData
{
+ /**
+ * Empty node list representing the children of character data nodes.
+ */
+ static class EmptyNodeList
+ implements NodeList
+ {
+
+ public int getLength()
+ {
+ return 0;
+ }
+
+ public Node item(int index)
+ {
+ return null;
+ }
+
+ }
+
+ /**
+ * Singleton empty node list for character data nodes.
+ */
+ static final NodeList CHILD_NODES = new EmptyNodeList();
+
private String text;
// package private
@@ -280,6 +306,15 @@ public abstract class DomCharacterData
}
/**
+ * Returns an empty node list.
+ * Character data nodes do not have children.
+ */
+ public NodeList getChildNodes()
+ {
+ return CHILD_NODES;
+ }
+
+ /**
* The base URI for character data is <code>null</code>.
* @since DOM Level 3 Core
*/
diff --git a/libjava/classpath/gnu/xml/dom/DomDocumentBuilder.java b/libjava/classpath/gnu/xml/dom/DomDocumentBuilder.java
index 42444e86515..343f48c13fd 100644
--- a/libjava/classpath/gnu/xml/dom/DomDocumentBuilder.java
+++ b/libjava/classpath/gnu/xml/dom/DomDocumentBuilder.java
@@ -1,5 +1,5 @@
/* DomDocumentBuilder.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,9 +37,11 @@ exception statement from your version. */
package gnu.xml.dom;
+import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.Reader;
+import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
@@ -157,8 +159,18 @@ class DomDocumentBuilder
}
else
{
- URL url = new URL(systemId);
- input.setByteStream(url.openStream());
+ try
+ {
+ URL url = new URL(systemId);
+ input.setByteStream(url.openStream());
+ }
+ catch (MalformedURLException e)
+ {
+ // Maybe this is a relative file URL
+ File cwd = new File(System.getProperty("user.dir"));
+ URL url = new URL(cwd.toURL(), systemId);
+ input.setByteStream(url.openStream());
+ }
}
}
input.setPublicId(is.getPublicId());
diff --git a/libjava/classpath/gnu/xml/dom/DomDocumentBuilderFactory.java b/libjava/classpath/gnu/xml/dom/DomDocumentBuilderFactory.java
index 814141c9441..02347858002 100644
--- a/libjava/classpath/gnu/xml/dom/DomDocumentBuilderFactory.java
+++ b/libjava/classpath/gnu/xml/dom/DomDocumentBuilderFactory.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package gnu.xml.dom;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
@@ -59,6 +60,7 @@ public class DomDocumentBuilderFactory
final DOMImplementation impl;
final DOMImplementationLS ls;
+ private boolean secureProcessing;
public DomDocumentBuilderFactory()
{
@@ -124,5 +126,26 @@ public class DomDocumentBuilderFactory
// TODO
}
+ public void setFeature(String name, boolean value)
+ throws ParserConfigurationException
+ {
+ if (name == null)
+ throw new NullPointerException();
+ if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
+ {
+ secureProcessing = true;
+ return;
+ }
+ throw new ParserConfigurationException(name);
+ }
+
+ public boolean getFeature(String name)
+ throws ParserConfigurationException
+ {
+ if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
+ return secureProcessing;
+ throw new ParserConfigurationException(name);
+ }
+
}
diff --git a/libjava/classpath/gnu/xml/dom/JAXPFactory.java b/libjava/classpath/gnu/xml/dom/JAXPFactory.java
index 8f481fad643..ca14a8e9daf 100644
--- a/libjava/classpath/gnu/xml/dom/JAXPFactory.java
+++ b/libjava/classpath/gnu/xml/dom/JAXPFactory.java
@@ -49,6 +49,7 @@ import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -70,6 +71,7 @@ public final class JAXPFactory
private static final String FEATURE = "http://xml.org/sax/features/";
private SAXParserFactory pf;
+ private boolean secureProcessing;
/**
* Default constructor.
@@ -138,6 +140,27 @@ public final class JAXPFactory
throw new IllegalArgumentException(name);
}
+ public void setFeature(String name, boolean value)
+ throws ParserConfigurationException
+ {
+ if (name == null)
+ throw new NullPointerException();
+ if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
+ {
+ secureProcessing = true;
+ return;
+ }
+ throw new ParserConfigurationException(name);
+ }
+
+ public boolean getFeature(String name)
+ throws ParserConfigurationException
+ {
+ if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
+ return secureProcessing;
+ throw new ParserConfigurationException(name);
+ }
+
static final class JAXPBuilder
extends DocumentBuilder
implements ErrorHandler
diff --git a/libjava/classpath/gnu/xml/libxmlj/dom/GnomeDocumentBuilderFactory.java b/libjava/classpath/gnu/xml/libxmlj/dom/GnomeDocumentBuilderFactory.java
index c4f0ce20158..c8918aa728b 100644
--- a/libjava/classpath/gnu/xml/libxmlj/dom/GnomeDocumentBuilderFactory.java
+++ b/libjava/classpath/gnu/xml/libxmlj/dom/GnomeDocumentBuilderFactory.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package gnu.xml.libxmlj.dom;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -47,9 +48,11 @@ import javax.xml.parsers.ParserConfigurationException;
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
public class GnomeDocumentBuilderFactory
-extends DocumentBuilderFactory
+ extends DocumentBuilderFactory
{
+ private boolean secureProcessing;
+
public GnomeDocumentBuilderFactory ()
{
setNamespaceAware (true);
@@ -91,4 +94,25 @@ extends DocumentBuilderFactory
// TODO
}
+ public void setFeature(String name, boolean value)
+ throws ParserConfigurationException
+ {
+ if (name == null)
+ throw new NullPointerException();
+ if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
+ {
+ secureProcessing = true;
+ return;
+ }
+ throw new ParserConfigurationException(name);
+ }
+
+ public boolean getFeature(String name)
+ throws ParserConfigurationException
+ {
+ if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
+ return secureProcessing;
+ throw new ParserConfigurationException(name);
+ }
+
}
diff --git a/libjava/classpath/gnu/xml/stream/CRLFReader.java b/libjava/classpath/gnu/xml/stream/CRLFReader.java
index 1d214ce52c1..dad02b94a1d 100644
--- a/libjava/classpath/gnu/xml/stream/CRLFReader.java
+++ b/libjava/classpath/gnu/xml/stream/CRLFReader.java
@@ -1,5 +1,5 @@
/* CRLFReader.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -153,13 +153,14 @@ class CRLFReader
throws IOException
{
doReset = false;
- int lm1 = len - 1;
- for (int i = off; i < len; i++)
+ int end = off + len;
+ int em1 = end - 1;
+ for (int i = off; i < end; i++)
{
if (b[i] == '\r') // CR
{
int d;
- if (i == lm1)
+ if (i == em1)
{
d = in.read();
doReset = true;
diff --git a/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java b/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java
index 4b40bfa526a..38e1f00b1af 100644
--- a/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java
+++ b/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java
@@ -1,5 +1,5 @@
/* EntityReferenceImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,7 +41,7 @@ import java.io.IOException;
import java.io.Writer;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
-//import javax.xml.stream.events.EntityDeclaration;
+import javax.xml.stream.events.EntityDeclaration;
import javax.xml.stream.events.EntityReference;
/**
@@ -54,26 +54,16 @@ public class EntityReferenceImpl
implements EntityReference
{
- //protected final EntityDeclaration decl;
+ protected final EntityDeclaration decl;
protected final String name;
- protected final String baseUri;
- protected final String publicId;
- protected final String systemId;
- protected final String replacementText;
protected EntityReferenceImpl(Location location,
- //EntityDeclaration decl,
- String name,
- String baseUri, String publicId,
- String systemId, String replacementText)
+ EntityDeclaration decl,
+ String name)
{
super(location);
- //this.decl = decl;
+ this.decl = decl;
this.name = name;
- this.baseUri = baseUri;
- this.publicId = publicId;
- this.systemId = systemId;
- this.replacementText = replacementText;
}
public int getEventType()
@@ -81,36 +71,16 @@ public class EntityReferenceImpl
return ENTITY_REFERENCE;
}
- /*public EntityDeclaration getDeclaration()
+ public EntityDeclaration getDeclaration()
{
return decl;
- }*/
+ }
public String getName()
{
return name;
}
- public String getBaseUri()
- {
- return baseUri;
- }
-
- public String getPublicId()
- {
- return publicId;
- }
-
- public String getSystemId()
- {
- return systemId;
- }
-
- public String getReplacementText()
- {
- return replacementText;
- }
-
public void writeAsEncodedUnicode(Writer writer)
throws XMLStreamException
{
diff --git a/libjava/classpath/gnu/xml/stream/FilteredEventReader.java b/libjava/classpath/gnu/xml/stream/FilteredEventReader.java
index 3bf0f2518b5..fd6fe8b0721 100644
--- a/libjava/classpath/gnu/xml/stream/FilteredEventReader.java
+++ b/libjava/classpath/gnu/xml/stream/FilteredEventReader.java
@@ -1,5 +1,5 @@
/* FilteredEventReader.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -56,24 +56,37 @@ class FilteredEventReader
}
public boolean hasNext()
- throws XMLStreamException
{
// XXX ???
return super.hasNext();
}
- public XMLEvent next()
+ public XMLEvent nextEvent()
throws XMLStreamException
{
XMLEvent ret;
do
{
- ret = super.next();
+ ret = super.nextEvent();
}
while (!filter.accept(ret));
return ret;
}
+ public Object next()
+ {
+ try
+ {
+ return nextEvent();
+ }
+ catch (XMLStreamException e)
+ {
+ RuntimeException e2 = new RuntimeException();
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
public XMLEvent peek()
throws XMLStreamException
{
diff --git a/libjava/classpath/gnu/xml/stream/SAXParser.java b/libjava/classpath/gnu/xml/stream/SAXParser.java
index 54c8b36244b..fd768a43da3 100644
--- a/libjava/classpath/gnu/xml/stream/SAXParser.java
+++ b/libjava/classpath/gnu/xml/stream/SAXParser.java
@@ -1,5 +1,5 @@
/* SAXParser.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -92,8 +92,7 @@ import org.xml.sax.ext.Locator2;
*/
public class SAXParser
extends javax.xml.parsers.SAXParser
- implements XMLReader, Attributes2, Locator2, XMLReporter,
- XMLParser.XMLResolver2
+ implements XMLReader, Attributes2, Locator2, XMLReporter, XMLResolver
{
ContentHandler contentHandler;
@@ -323,6 +322,7 @@ public class SAXParser
supportDTD,
baseAware,
stringInterning,
+ true,
this,
this);
else
@@ -338,6 +338,7 @@ public class SAXParser
supportDTD,
baseAware,
stringInterning,
+ true,
this,
this);
}
@@ -357,6 +358,7 @@ public class SAXParser
supportDTD,
baseAware,
stringInterning,
+ true,
this,
this);
}
@@ -486,14 +488,14 @@ public class SAXParser
contentHandler.processingInstruction(target, data);
}
break;
- case XMLStreamConstants.START_ENTITY:
+ case XMLParser.START_ENTITY:
if (lexicalHandler != null)
{
String name = reader.getText();
lexicalHandler.startEntity(name);
}
break;
- case XMLStreamConstants.END_ENTITY:
+ case XMLParser.END_ENTITY:
if (lexicalHandler != null)
{
String name = reader.getText();
@@ -649,24 +651,36 @@ public class SAXParser
lexicalHandler.endDTD();
}
}
+ reset();
+ if (opened)
+ in.close();
}
- catch (XMLStreamException e)
+ catch (Exception e)
{
- if (!startDocumentDone && contentHandler != null)
- contentHandler.startDocument();
SAXParseException e2 = new SAXParseException(e.getMessage(), this);
e2.initCause(e);
- if (errorHandler != null)
- errorHandler.fatalError(e2);
- if (contentHandler != null)
- contentHandler.endDocument();
- throw e2;
- }
- finally
- {
+ try
+ {
+ if (!startDocumentDone && contentHandler != null)
+ contentHandler.startDocument();
+ if (errorHandler != null)
+ errorHandler.fatalError(e2);
+ if (contentHandler != null)
+ contentHandler.endDocument();
+ }
+ catch (SAXException sex)
+ {
+ // Ignored, we will rethrow the original exception.
+ }
+ reset();
if (opened)
in.close();
- reset();
+ if (e instanceof SAXException)
+ throw (SAXException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ else
+ throw e2;
}
}
@@ -685,7 +699,7 @@ public class SAXParser
int ac = reader.getAttributeCount();
for (int i = 0; i < ac; i++)
{
- QName aname = reader.getAttributeQName(i);
+ QName aname = reader.getAttributeName(i);
if ("space".equals(aname.getLocalPart()) &&
XMLConstants.XML_NS_URI.equals(aname.getNamespaceURI()))
{
@@ -726,7 +740,7 @@ public class SAXParser
int len = reader.getAttributeCount();
for (int i = 0; i < len; i++)
{
- QName q = reader.getAttributeQName(i);
+ QName q = reader.getAttributeName(i);
String localName = q.getLocalPart();
String prefix = q.getPrefix();
String qn = ("".equals(prefix)) ? localName : prefix + ":" + localName;
@@ -741,7 +755,7 @@ public class SAXParser
int len = reader.getAttributeCount();
for (int i = 0; i < len; i++)
{
- QName q = reader.getAttributeQName(i);
+ QName q = reader.getAttributeName(i);
String ln = q.getLocalPart();
String u = q.getNamespaceURI();
if (u == null && uri != null)
@@ -761,12 +775,12 @@ public class SAXParser
public String getLocalName(int index)
{
- return reader.getAttributeName(index);
+ return reader.getAttributeLocalName(index);
}
public String getQName(int index)
{
- QName q = reader.getAttributeQName(index);
+ QName q = reader.getAttributeName(index);
String localName = q.getLocalPart();
String prefix = q.getPrefix();
return ("".equals(prefix)) ? localName : prefix + ":" + localName;
@@ -864,13 +878,14 @@ public class SAXParser
public String getPublicId()
{
- return null;
+ Location l = reader.getLocation();
+ return l.getPublicId();
}
public String getSystemId()
{
Location l = reader.getLocation();
- return l.getLocationURI();
+ return l.getSystemId();
}
public String getEncoding()
@@ -885,13 +900,8 @@ public class SAXParser
// -- XMLResolver --
- public InputStream resolve(String uri)
- throws XMLStreamException
- {
- return resolve(null, uri);
- }
-
- public InputStream resolve(String publicId, String systemId)
+ public Object resolveEntity(String publicId, String systemId,
+ String baseURI, String namespace)
throws XMLStreamException
{
if (entityResolver != null)
@@ -901,7 +911,16 @@ public class SAXParser
InputSource input =
entityResolver.resolveEntity(publicId, systemId);
if (input != null)
- return input.getByteStream();
+ {
+ InputStream in = input.getByteStream();
+ if (in == null)
+ {
+ String newSystemId = input.getSystemId();
+ if (newSystemId != null && !newSystemId.equals(systemId))
+ in = XMLParser.resolve(newSystemId);
+ }
+ return in;
+ }
}
catch (SAXException e)
{
diff --git a/libjava/classpath/gnu/xml/stream/UnicodeReader.java b/libjava/classpath/gnu/xml/stream/UnicodeReader.java
index c38516c30f8..9350cb2e0b6 100644
--- a/libjava/classpath/gnu/xml/stream/UnicodeReader.java
+++ b/libjava/classpath/gnu/xml/stream/UnicodeReader.java
@@ -45,7 +45,7 @@ import java.io.Reader;
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
-class UnicodeReader
+public class UnicodeReader
{
final Reader in;
@@ -152,6 +152,10 @@ class UnicodeReader
in.close();
}
+ /**
+ * Returns the specified UTF-16 char array as an array of Unicode code
+ * points.
+ */
public static int[] toCodePointArray(String text)
throws IOException
{
diff --git a/libjava/classpath/gnu/xml/stream/XIncludeFilter.java b/libjava/classpath/gnu/xml/stream/XIncludeFilter.java
index e151ac69d3c..7e707820d52 100644
--- a/libjava/classpath/gnu/xml/stream/XIncludeFilter.java
+++ b/libjava/classpath/gnu/xml/stream/XIncludeFilter.java
@@ -42,6 +42,7 @@ import java.io.InputStreamReader;
import java.io.IOException;
import java.io.Reader;
import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
@@ -121,7 +122,17 @@ class XIncludeFilter
boolean expandERefs)
{
super(reader);
- this.systemId = XMLParser.absolutize(null, systemId);
+ try
+ {
+ this.systemId = XMLParser.absolutize(null, systemId);
+ }
+ catch (MalformedURLException e)
+ {
+ RuntimeException e2 = new RuntimeException("unsupported URL: " +
+ systemId);
+ e2.initCause(e);
+ throw e2;
+ }
this.namespaceAware = namespaceAware;
this.validating = validating;
this.expandERefs = expandERefs;
@@ -137,7 +148,7 @@ class XIncludeFilter
return super.getAttributeCount();
}
- public String getAttributeName(int index)
+ public String getAttributeLocalName(int index)
{
if (current != null)
{
@@ -147,7 +158,7 @@ class XIncludeFilter
Node attr = attrs.item(index);
return attr.getLocalName();
}
- return super.getAttributeName(index);
+ return super.getAttributeLocalName(index);
}
public String getAttributeNamespace(int index)
@@ -176,7 +187,7 @@ class XIncludeFilter
return super.getAttributePrefix(index);
}
- public QName getAttributeQName(int index)
+ public QName getAttributeName(int index)
{
if (current != null)
{
@@ -189,7 +200,7 @@ class XIncludeFilter
String prefix = attr.getPrefix();
return new QName(uri, localName, prefix);
}
- return super.getAttributeQName(index);
+ return super.getAttributeName(index);
}
public String getAttributeType(int index)
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java
index 4b21b6c7110..666bffabe23 100644
--- a/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java
@@ -1,5 +1,5 @@
/* XMLEventAllocatorImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -116,10 +116,9 @@ public class XMLEventAllocatorImpl
namespaces);
case XMLStreamConstants.ENTITY_REFERENCE:
String name = reader.getLocalName();
- //EntityDeclaration decl =
- // (EntityDeclaration) entityDeclarations.get(name);
- //return new EntityReferenceImpl(location, decl, name);
- return new EntityReferenceImpl(location, name, null, null, null, null);
+ EntityDeclaration decl =
+ (EntityDeclaration) entityDeclarations.get(name);
+ return new EntityReferenceImpl(location, decl, name);
case XMLStreamConstants.PROCESSING_INSTRUCTION:
return new ProcessingInstructionImpl(location,
reader.getPITarget(),
@@ -132,7 +131,7 @@ public class XMLEventAllocatorImpl
return new CharactersImpl(location, text,
whitespace, false, ignorableWhitespace);
case XMLStreamConstants.START_DOCUMENT:
- String systemId = location.getLocationURI();
+ String systemId = location.getSystemId();
String encoding = reader.getCharacterEncodingScheme();
boolean encodingDeclared = encoding != null;
if (encoding == null)
@@ -164,7 +163,7 @@ public class XMLEventAllocatorImpl
List attributes = new LinkedList();
for (int i = 0; i < len; i++)
attributes.add(new AttributeImpl(location,
- reader.getAttributeQName(i),
+ reader.getAttributeName(i),
reader.getAttributeValue(i),
QName.valueOf(reader.getAttributeType(i)),
reader.isAttributeSpecified(i)));
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java
index a839b182c09..e1d7d6ab82f 100644
--- a/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java
@@ -1,5 +1,5 @@
/* XMLEventFactoryImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -233,12 +233,9 @@ public class XMLEventFactoryImpl
}
public EntityReference createEntityReference(String name,
- //EntityDeclaration declaration)
- String replacementText)
+ EntityDeclaration declaration)
{
- //return new EntityReferenceImpl(location, declaration, name);
- return new EntityReferenceImpl(location, name, null, null, null,
- replacementText);
+ return new EntityReferenceImpl(location, declaration, name);
}
public Comment createComment(String text)
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventImpl.java
index a8b522f88a7..9f57d89d828 100644
--- a/libjava/classpath/gnu/xml/stream/XMLEventImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLEventImpl.java
@@ -1,5 +1,5 @@
/* XMLEventImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -116,16 +116,6 @@ public abstract class XMLEventImpl
return getEventType() == END_DOCUMENT;
}
- public boolean isStartEntity()
- {
- return getEventType() == START_ENTITY;
- }
-
- public boolean isEndEntity()
- {
- return getEventType() == END_ENTITY;
- }
-
public StartElement asStartElement()
{
return (StartElement) this;
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java
index 70481d7c407..bb64b1e3f9d 100644
--- a/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java
@@ -67,7 +67,7 @@ public class XMLEventReaderImpl
this.systemId = systemId;
}
- public XMLEvent next()
+ public XMLEvent nextEvent()
throws XMLStreamException
{
XMLEvent ret = peek();
@@ -75,10 +75,32 @@ public class XMLEventReaderImpl
return ret;
}
+ public Object next()
+ {
+ try
+ {
+ return nextEvent();
+ }
+ catch (XMLStreamException e)
+ {
+ RuntimeException e2 = new RuntimeException();
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
public boolean hasNext()
- throws XMLStreamException
{
- return peekEvent != null || reader.hasNext();
+ if (peekEvent != null)
+ return true;
+ try
+ {
+ return reader.hasNext();
+ }
+ catch (XMLStreamException e)
+ {
+ return false;
+ }
}
public XMLEvent peek()
@@ -121,5 +143,16 @@ public class XMLEventReaderImpl
return reader.getProperty(name);
}
+ public void close()
+ throws XMLStreamException
+ {
+ reader.close();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
}
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java
index 45024158da6..72b7adce24c 100644
--- a/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java
@@ -155,7 +155,7 @@ public class XMLEventWriterImpl
throws XMLStreamException
{
while (reader.hasNext())
- add(reader.next());
+ add(reader.nextEvent());
}
public String getPrefix(String uri)
diff --git a/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java
index 164774d8236..5f72e361e52 100644
--- a/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java
@@ -1,5 +1,5 @@
/* XMLInputFactoryImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -89,14 +89,15 @@ public class XMLInputFactoryImpl
public XMLStreamReader createXMLStreamReader(Reader reader)
throws XMLStreamException
{
- /*
- return new XMLStreamReaderImpl(reader, null, null,
- resolver, reporter,
- validating, namespaceAware,
- coalescing, replacingEntityReferences,
- externalEntities, supportDTD);
- */
- XMLParser ret = new XMLParser(reader, null,
+ return createXMLStreamReader(null, reader);
+ }
+
+ public XMLStreamReader createXMLStreamReader(Source source)
+ throws XMLStreamException
+ {
+ String systemId = source.getSystemId();
+ InputStream in = getInputStream(source);
+ XMLParser ret = new XMLParser(in, systemId,
validating,
namespaceAware,
coalescing,
@@ -105,24 +106,30 @@ public class XMLInputFactoryImpl
supportDTD,
baseAware,
stringInterning,
+ false,
reporter,
resolver);
if (xIncludeAware)
- return new XIncludeFilter(ret, null, namespaceAware, validating,
+ return new XIncludeFilter(ret, systemId, namespaceAware, validating,
replacingEntityReferences);
return ret;
}
- public XMLStreamReader createXMLStreamReader(Source source)
+ public XMLStreamReader createXMLStreamReader(InputStream in)
+ throws XMLStreamException
+ {
+ return createXMLStreamReader(null, in);
+ }
+
+ public XMLStreamReader createXMLStreamReader(InputStream in, String encoding)
+ throws XMLStreamException
+ {
+ return createXMLStreamReader(in);
+ }
+
+ public XMLStreamReader createXMLStreamReader(String systemId, InputStream in)
throws XMLStreamException
{
- String systemId = source.getSystemId();
- InputStream in = getInputStream(source);
- /*return new XMLStreamReaderImpl(in, null, systemId,
- resolver, reporter,
- validating, namespaceAware,
- coalescing, replacingEntityReferences,
- externalEntities, supportDTD);*/
XMLParser ret = new XMLParser(in, systemId,
validating,
namespaceAware,
@@ -132,23 +139,19 @@ public class XMLInputFactoryImpl
supportDTD,
baseAware,
stringInterning,
+ false,
reporter,
resolver);
if (xIncludeAware)
- return new XIncludeFilter(ret, systemId, namespaceAware, validating,
+ return new XIncludeFilter(ret, null, namespaceAware, validating,
replacingEntityReferences);
return ret;
}
-
- public XMLStreamReader createXMLStreamReader(InputStream in)
+
+ public XMLStreamReader createXMLStreamReader(String systemId, Reader reader)
throws XMLStreamException
{
- /*return new XMLStreamReaderImpl(in, null, null,
- resolver, reporter,
- validating, namespaceAware,
- coalescing, replacingEntityReferences,
- externalEntities, supportDTD);*/
- XMLParser ret = new XMLParser(in, null,
+ XMLParser ret = new XMLParser(reader, systemId,
validating,
namespaceAware,
coalescing,
@@ -157,6 +160,7 @@ public class XMLInputFactoryImpl
supportDTD,
baseAware,
stringInterning,
+ false,
reporter,
resolver);
if (xIncludeAware)
@@ -164,12 +168,6 @@ public class XMLInputFactoryImpl
replacingEntityReferences);
return ret;
}
-
- public XMLStreamReader createXMLStreamReader(InputStream in, String encoding)
- throws XMLStreamException
- {
- return createXMLStreamReader(in);
- }
public XMLEventReader createXMLEventReader(Reader reader)
throws XMLStreamException
@@ -178,6 +176,13 @@ public class XMLInputFactoryImpl
return new XMLEventReaderImpl(sr, allocator, null);
}
+ public XMLEventReader createXMLEventReader(String systemId, Reader reader)
+ throws XMLStreamException
+ {
+ XMLStreamReader sr = createXMLStreamReader(systemId, reader);
+ return new XMLEventReaderImpl(sr, allocator, null);
+ }
+
public XMLEventReader createXMLEventReader(XMLStreamReader reader)
throws XMLStreamException
{
@@ -205,6 +210,13 @@ public class XMLInputFactoryImpl
return new XMLEventReaderImpl(sr, allocator, null);
}
+ public XMLEventReader createXMLEventReader(String systemId, InputStream in)
+ throws XMLStreamException
+ {
+ XMLStreamReader sr = createXMLStreamReader(systemId, in);
+ return new XMLEventReaderImpl(sr, allocator, null);
+ }
+
public XMLStreamReader createFilteredReader(XMLStreamReader reader,
StreamFilter filter)
throws XMLStreamException
diff --git a/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java
index 05b6d6c0f11..c8c651fb1af 100644
--- a/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java
@@ -42,6 +42,8 @@ import java.io.OutputStreamWriter;
import java.io.Writer;
import java.io.UnsupportedEncodingException;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamResult;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
@@ -94,6 +96,22 @@ public class XMLOutputFactoryImpl
}
}
+ public XMLStreamWriter createXMLStreamWriter(Result result)
+ throws XMLStreamException
+ {
+ if (result instanceof StreamResult)
+ {
+ StreamResult sr = (StreamResult) result;
+ OutputStream out = sr.getOutputStream();
+ if (out != null)
+ return createXMLStreamWriter(out);
+ Writer writer = sr.getWriter();
+ if (writer != null)
+ return createXMLStreamWriter(writer);
+ }
+ throw new UnsupportedOperationException();
+ }
+
public XMLEventWriter createXMLEventWriter(OutputStream stream)
throws XMLStreamException
{
@@ -116,10 +134,26 @@ public class XMLOutputFactoryImpl
return new XMLEventWriterImpl(writer);
}
+ public XMLEventWriter createXMLEventWriter(Result result)
+ throws XMLStreamException
+ {
+ if (result instanceof StreamResult)
+ {
+ StreamResult sr = (StreamResult) result;
+ OutputStream out = sr.getOutputStream();
+ if (out != null)
+ return createXMLEventWriter(out);
+ Writer writer = sr.getWriter();
+ if (writer != null)
+ return createXMLEventWriter(writer);
+ }
+ throw new UnsupportedOperationException();
+ }
+
public void setProperty(String name, Object value)
throws IllegalArgumentException
{
- if (IS_PREFIX_DEFAULTING.equals(name))
+ if (IS_REPAIRING_NAMESPACES.equals(name))
prefixDefaulting = ((Boolean) value).booleanValue();
else
throw new IllegalArgumentException(name);
@@ -128,14 +162,14 @@ public class XMLOutputFactoryImpl
public Object getProperty(String name)
throws IllegalArgumentException
{
- if (IS_PREFIX_DEFAULTING.equals(name))
+ if (IS_REPAIRING_NAMESPACES.equals(name))
return new Boolean(prefixDefaulting);
throw new IllegalArgumentException(name);
}
public boolean isPropertySupported(String name)
{
- if (IS_PREFIX_DEFAULTING.equals(name))
+ if (IS_REPAIRING_NAMESPACES.equals(name))
return true;
return false;
}
diff --git a/libjava/classpath/gnu/xml/stream/XMLParser.java b/libjava/classpath/gnu/xml/stream/XMLParser.java
index 6f10b9303dc..9bb4834267e 100644
--- a/libjava/classpath/gnu/xml/stream/XMLParser.java
+++ b/libjava/classpath/gnu/xml/stream/XMLParser.java
@@ -137,6 +137,10 @@ public class XMLParser
final static int ATTRIBUTE_DEFAULT_REQUIRED = 33;
final static int ATTRIBUTE_DEFAULT_FIXED = 34;
+ // -- additional event types --
+ final static int START_ENTITY = 50;
+ final static int END_ENTITY = 51;
+
/**
* The current input.
*/
@@ -318,6 +322,12 @@ public class XMLParser
private final boolean baseAware;
/**
+ * Whether to report extended event types (START_ENTITY and END_ENTITY)
+ * in addition to the standard event types. Used by the SAX parser.
+ */
+ private final boolean extendedEventTypes;
+
+ /**
* The reporter to receive parsing warnings.
*/
final XMLReporter reporter;
@@ -389,6 +399,7 @@ public class XMLParser
boolean supportDTD,
boolean baseAware,
boolean stringInterning,
+ boolean extendedEventTypes,
XMLReporter reporter,
XMLResolver resolver)
{
@@ -400,6 +411,7 @@ public class XMLParser
this.supportDTD = supportDTD;
this.baseAware = baseAware;
this.stringInterning = stringInterning;
+ this.extendedEventTypes = extendedEventTypes;
this.reporter = reporter;
this.resolver = resolver;
if (validating)
@@ -446,6 +458,7 @@ public class XMLParser
boolean supportDTD,
boolean baseAware,
boolean stringInterning,
+ boolean extendedEventTypes,
XMLReporter reporter,
XMLResolver resolver)
{
@@ -457,6 +470,7 @@ public class XMLParser
this.supportDTD = supportDTD;
this.baseAware = baseAware;
this.stringInterning = stringInterning;
+ this.extendedEventTypes = extendedEventTypes;
this.reporter = reporter;
this.resolver = resolver;
if (validating)
@@ -561,7 +575,7 @@ public class XMLParser
return attrs.size();
}
- public String getAttributeName(int index)
+ public String getAttributeLocalName(int index)
{
Attribute a = (Attribute) attrs.get(index);
return a.localName;
@@ -579,7 +593,7 @@ public class XMLParser
return a.prefix;
}
- public QName getAttributeQName(int index)
+ public QName getAttributeName(int index)
{
Attribute a = (Attribute) attrs.get(index);
String namespaceURI = getNamespaceURI(a.prefix);
@@ -710,7 +724,7 @@ public class XMLParser
public int getNamespaceCount()
{
- if (!namespaceAware)
+ if (!namespaceAware || namespaces.isEmpty())
return 0;
switch (event)
{
@@ -984,10 +998,10 @@ public class XMLParser
if (event == XMLStreamConstants.END_ELEMENT)
{
// Pop namespace context
- if (namespaceAware)
+ if (namespaceAware && !namespaces.isEmpty())
namespaces.removeFirst();
// Pop base context
- if (baseAware)
+ if (baseAware && !bases.isEmpty())
bases.removeFirst();
}
if (!startEntityStack.isEmpty())
@@ -995,16 +1009,16 @@ public class XMLParser
String entityName = (String) startEntityStack.removeFirst();
buf.setLength(0);
buf.append(entityName);
- event = XMLStreamConstants.START_ENTITY;
- return event;
+ event = START_ENTITY;
+ return extendedEventTypes ? event : next();
}
else if (!endEntityStack.isEmpty())
{
String entityName = (String) endEntityStack.removeFirst();
buf.setLength(0);
buf.append(entityName);
- event = XMLStreamConstants.END_ENTITY;
- return event;
+ event = END_ENTITY;
+ return extendedEventTypes ? event : next();
}
try
{
@@ -1484,7 +1498,6 @@ public class XMLParser
{
if (!externalEntities)
return;
- InputStream in = null;
String url = absolutize(input.systemId, ids.systemId);
// Check for recursion
for (Iterator i = inputStack.iterator(); i.hasNext(); )
@@ -1497,12 +1510,13 @@ public class XMLParser
}
if (name == null || "".equals(name))
report = false;
- if (in == null && url != null && resolver != null)
+ InputStream in = null;
+ if (resolver != null)
{
- if (resolver instanceof XMLResolver2)
- in = ((XMLResolver2) resolver).resolve(ids.publicId, url);
- else
- in = resolver.resolve(url);
+ Object obj = resolver.resolveEntity(ids.publicId, url, getXMLBase(),
+ null);
+ if (obj instanceof InputStream)
+ in = (InputStream) obj;
}
if (in == null)
in = resolve(url);
@@ -1535,12 +1549,13 @@ public class XMLParser
* @param base the current base URL
* @param href the (absolute or relative) URL to resolve
*/
- static String absolutize(String base, String href)
+ public static String absolutize(String base, String href)
+ throws MalformedURLException
{
if (href == null)
return null;
int ci = href.indexOf(':');
- if (ci > 1 && isLowercaseAscii(href.substring(0, ci)))
+ if (ci > 1 && isURLScheme(href.substring(0, ci)))
{
// href is absolute already
return href;
@@ -1565,40 +1580,23 @@ public class XMLParser
if (!base.endsWith("/"))
base += "/";
}
- if (href.startsWith("/"))
- {
- if (base.startsWith("file:"))
- return "file://" + href;
- int i = base.indexOf("://");
- if (i != -1)
- {
- i = base.indexOf('/', i + 3);
- if (i != -1)
- base = base.substring(0, i);
- }
- }
- else
- {
- while (href.startsWith(".."))
- {
- int i = base.lastIndexOf('/', base.length() - 2);
- if (i != -1)
- base = base.substring(0, i + 1);
- href = href.substring(2);
- if (href.startsWith("/"))
- href = href.substring(1);
- }
- }
- return base + href;
+ return new URL(new URL(base), href).toString();
}
- private static boolean isLowercaseAscii(String text)
+ /**
+ * Indicates whether the specified characters match the scheme portion of
+ * a URL.
+ * @see RFC 1738 section 2.1
+ */
+ private static boolean isURLScheme(String text)
{
int len = text.length();
for (int i = 0; i < len; i++)
{
char c = text.charAt(i);
- if (c < 97 || c > 122)
+ if (c == '+' || c == '.' || c == '-')
+ continue;
+ if (c < 65 || (c > 90 && c < 97) || c > 122)
return false;
}
return true;
@@ -1607,7 +1605,7 @@ public class XMLParser
/**
* Returns an input stream for the given URL.
*/
- private InputStream resolve(String url)
+ static InputStream resolve(String url)
throws IOException
{
try
@@ -1618,6 +1616,12 @@ public class XMLParser
{
return null;
}
+ catch (IOException e)
+ {
+ IOException e2 = new IOException("error resolving " + url);
+ e2.initCause(e);
+ throw e2;
+ }
}
/**
@@ -1891,7 +1895,10 @@ public class XMLParser
throws IOException, XMLStreamException
{
requireWhitespace();
+ boolean saved = expandPE;
+ expandPE = (inputStack.size() > 1);
String name = readNmtoken(true);
+ expandPE = saved;
requireWhitespace();
readContentspec(name);
skipWhitespace();
@@ -2106,7 +2113,10 @@ public class XMLParser
throws IOException, XMLStreamException
{
requireWhitespace();
+ boolean saved = expandPE;
+ expandPE = (inputStack.size() > 1);
String elementName = readNmtoken(true);
+ expandPE = saved;
boolean white = tryWhitespace();
while (!tryRead('>'))
{
@@ -2419,11 +2429,11 @@ public class XMLParser
}
else
{
- if (!isNameStartCharacter(cp[0]))
+ if (!isNameStartCharacter(cp[0], input.xml11))
error("malformed reference in entity value", value);
for (int i = 1; i < cp.length; i++)
{
- if (!isNameCharacter(cp[i]))
+ if (!isNameCharacter(cp[i], input.xml11))
error("malformed reference in entity value", value);
}
}
@@ -2838,8 +2848,6 @@ public class XMLParser
error("Duplicate default namespace declaration");
if (XMLConstants.XML_NS_URI.equals(attr.value))
error("can't bind XML namespace");
- if ("".equals(attr.value) && !input.xml11)
- error("illegal use of 1.1-style prefix unbinding in 1.0 document");
ctx.put(XMLConstants.DEFAULT_NS_PREFIX, attr.value);
return true;
}
@@ -3087,7 +3095,15 @@ public class XMLParser
break;
case 0x3c: // '<'
reset();
- read(tmpBuf, 0, i);
+ // read i characters
+ int count = 0, remaining = i;
+ do
+ {
+ int r = read(tmpBuf, 0, remaining);
+ count += r;
+ remaining -= r;
+ }
+ while (count < i);
i = len;
if (coalescing && tryRead(TEST_CDATA))
readUntil(TEST_END_CDATA); // read CDATA section into buf
@@ -3258,15 +3274,7 @@ public class XMLParser
reset();
char[] ref = readCharacterRef(hex ? 16 : 10);
for (int i = 0; i < ref.length; i++)
- {
- char x = ref[i];
- if ((flags & (LIT_ATTRIBUTE | LIT_PUBID)) != 0 &&
- (x == 0x0a || x == 0x0d))
- x = 0x20; // normalize
- else if ((flags & LIT_ATTRIBUTE) != 0 && x == 0x09)
- x = 0x20; // normalize
- literalBuf.append(x);
- }
+ literalBuf.append(ref[i]);
entities = true;
continue;
}
@@ -3469,13 +3477,13 @@ public class XMLParser
int c = readCh();
if (isName)
{
- if (!isNameStartCharacter(c))
+ if (!isNameStartCharacter(c, input.xml11))
error("not a name start character",
"U+" + Integer.toHexString(c));
}
else
{
- if (!isNameCharacter(c))
+ if (!isNameCharacter(c, input.xml11))
error("not a name character",
"U+" + Integer.toHexString(c));
}
@@ -3510,7 +3518,7 @@ public class XMLParser
reset();
return intern(buf.toString());
default:
- if (!isNameCharacter(c))
+ if (!isNameCharacter(c, input.xml11))
error("not a name character",
"U+" + Integer.toHexString(c));
else
@@ -3523,7 +3531,7 @@ public class XMLParser
/**
* Indicates whether the specified Unicode character is an XML 1.1 Char.
*/
- private boolean isXML11Char(int c)
+ public static boolean isXML11Char(int c)
{
return ((c >= 0x0001 && c <= 0xD7FF) ||
(c >= 0xE000 && c < 0xFFFD) || // NB exclude 0xfffd
@@ -3534,7 +3542,7 @@ public class XMLParser
* Indicates whether the specified Unicode character is an XML 1.1
* RestrictedChar.
*/
- private boolean isXML11RestrictedChar(int c)
+ public static boolean isXML11RestrictedChar(int c)
{
return ((c >= 0x0001 && c <= 0x0008) ||
(c >= 0x000B && c <= 0x000C) ||
@@ -3556,17 +3564,17 @@ public class XMLParser
return false;
if (isName)
{
- if (!isNameStartCharacter(cp[0]))
+ if (!isNameStartCharacter(cp[0], input.xml11))
return false;
}
else
{
- if (!isNameCharacter(cp[0]))
+ if (!isNameCharacter(cp[0], input.xml11))
return false;
}
for (int i = 1; i < cp.length; i++)
{
- if (!isNameCharacter(cp[i]))
+ if (!isNameCharacter(cp[i], input.xml11))
return false;
}
return true;
@@ -3581,9 +3589,9 @@ public class XMLParser
* Indicates whether the specified Unicode character is a Name start
* character.
*/
- private boolean isNameStartCharacter(int c)
+ public static boolean isNameStartCharacter(int c, boolean xml11)
{
- if (input.xml11)
+ if (xml11)
return ((c >= 0x0041 && c <= 0x005a) ||
(c >= 0x0061 && c <= 0x007a) ||
c == 0x3a |
@@ -3608,9 +3616,9 @@ public class XMLParser
* Indicates whether the specified Unicode character is a Name non-initial
* character.
*/
- private boolean isNameCharacter(int c)
+ public static boolean isNameCharacter(int c, boolean xml11)
{
- if (input.xml11)
+ if (xml11)
return ((c >= 0x0041 && c <= 0x005a) ||
(c >= 0x0061 && c <= 0x007a) ||
(c >= 0x0030 && c <= 0x0039) ||
@@ -4255,6 +4263,7 @@ public class XMLParser
true, // supportDTD
true, // baseAware
true, // stringInterning
+ true, // extendedEventTypes
null,
null);
XMLStreamReader reader = p;
@@ -4286,7 +4295,7 @@ public class XMLParser
"='"+reader.getNamespaceURI(i)+"'");
l = reader.getAttributeCount();
for (int i = 0; i < l; i++)
- System.out.println("\tattribute "+reader.getAttributeQName(i)+
+ System.out.println("\tattribute "+reader.getAttributeName(i)+
"='"+reader.getAttributeValue(i)+"'");
break;
case XMLStreamConstants.END_ELEMENT:
@@ -4314,10 +4323,10 @@ public class XMLParser
System.out.println("PROCESSING_INSTRUCTION "+reader.getPITarget()+
" "+reader.getPIData());
break;
- case XMLStreamConstants.START_ENTITY:
+ case START_ENTITY:
System.out.println("START_ENTITY "+reader.getText());
break;
- case XMLStreamConstants.END_ENTITY:
+ case END_ENTITY:
System.out.println("END_ENTITY "+reader.getText());
break;
default:
@@ -4330,7 +4339,7 @@ public class XMLParser
Location l = reader.getLocation();
System.out.println("At line "+l.getLineNumber()+
", column "+l.getColumnNumber()+
- " of "+l.getLocationURI());
+ " of "+l.getSystemId());
throw e;
}
}
@@ -4939,19 +4948,6 @@ public class XMLParser
}
/**
- * Compatibility interface that can be used to resolve based on a public
- * ID, not just an URL.
- */
- interface XMLResolver2
- extends XMLResolver
- {
-
- InputStream resolve(String publicId, String systemId)
- throws XMLStreamException;
-
- }
-
- /**
* An XML input source.
*/
static class Input
@@ -5019,7 +5015,12 @@ public class XMLParser
return line;
}
- public String getLocationURI()
+ public String getPublicId()
+ {
+ return publicId;
+ }
+
+ public String getSystemId()
{
return systemId;
}
diff --git a/libjava/classpath/gnu/xml/stream/XMLStreamReaderImpl.java b/libjava/classpath/gnu/xml/stream/XMLStreamReaderImpl.java
deleted file mode 100644
index 568d800ae0d..00000000000
--- a/libjava/classpath/gnu/xml/stream/XMLStreamReaderImpl.java
+++ /dev/null
@@ -1,1037 +0,0 @@
-/* XMLStreamReaderImpl.java --
- Copyright (C) 2005 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.xml.stream;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Map;
-import javax.xml.namespace.NamespaceContext;
-import javax.xml.namespace.QName;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.stream.Location;
-import javax.xml.stream.XMLResolver;
-import javax.xml.stream.XMLReporter;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.Characters;
-import javax.xml.stream.events.Comment;
-import javax.xml.stream.events.DTD;
-import javax.xml.stream.events.EndDocument;
-import javax.xml.stream.events.EndElement;
-import javax.xml.stream.events.EndEntity;
-import javax.xml.stream.events.EntityDeclaration;
-import javax.xml.stream.events.EntityReference;
-import javax.xml.stream.events.Namespace;
-import javax.xml.stream.events.NotationDeclaration;
-import javax.xml.stream.events.ProcessingInstruction;
-import javax.xml.stream.events.StartDocument;
-import javax.xml.stream.events.StartElement;
-import javax.xml.stream.events.StartEntity;
-import javax.xml.stream.events.XMLEvent;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.DTDHandler;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.ext.Attributes2;
-import org.xml.sax.ext.DeclHandler;
-import org.xml.sax.ext.LexicalHandler;
-import org.xml.sax.ext.Locator2;
-import org.xml.sax.helpers.NamespaceSupport;
-
-/**
- * An XML parser.
- *
- * This implementation uses SAX to create a series of events in memory,
- * and then iterates over this series. This has the advantage of being simple
- * and unifying the existing XML parsing code. However, it is quite
- * memory-inefficient and obviously won't cope with streams of arbitrary
- * length.
- *
- * A future task could be to write a real, progressive/incremental
- * implementation of this class. In that case we should consider making that
- * the default XML parser implementation and using a SAX wrapper to it to
- * provide the GNU SAX implementation.
- *
- * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
- */
-public class XMLStreamReaderImpl
- implements XMLStreamReader, NamespaceContext
-{
-
- private LinkedList events;
- private XMLEvent currentEvent;
- private int eventType;
- private NamespaceSupport namespaces;
-
- protected String publicId;
- protected String systemId;
-
- protected XMLResolver resolver;
- protected XMLReporter reporter;
- protected boolean validating;
- protected boolean namespaceAware;
- protected boolean coalescing;
- protected boolean replacingEntityReferences;
- protected boolean externalEntities;
- protected boolean supportDTD;
-
- protected XMLStreamReaderImpl(InputStream in,
- String publicId,
- String systemId,
- XMLResolver resolver,
- XMLReporter reporter,
- boolean validating,
- boolean namespaceAware,
- boolean coalescing,
- boolean replacingEntityReferences,
- boolean externalEntities,
- boolean supportDTD)
- throws XMLStreamException
- {
- //this.in = in;
- this.publicId = publicId;
- this.systemId = systemId;
- this.resolver = resolver;
- this.reporter = reporter;
- this.validating = validating;
- this.namespaceAware = namespaceAware;
- this.coalescing = coalescing;
- this.replacingEntityReferences = replacingEntityReferences;
- this.externalEntities = externalEntities;
- this.supportDTD = supportDTD;
- namespaces = new NamespaceSupport();
- events = new LinkedList();
-
- // Configure the SAX parser and perform the parse
- try
- {
- SAXParserFactory f = SAXParserFactory.newInstance();
- f.setNamespaceAware(namespaceAware);
- f.setValidating(validating);
- SAXParser p = f.newSAXParser();
- XMLReader r = p.getXMLReader();
- CallbackHandler ch = this.new CallbackHandler(r);
- r.setFeature("http://xml.org/sax/features/external-general-entities",
- externalEntities);
- r.setFeature("http://xml.org/sax/features/namespaces",
- namespaceAware);
- r.setContentHandler(ch);
- r.setDTDHandler(ch);
- r.setEntityResolver(ch);
- r.setErrorHandler(ch);
- r.setProperty("http://xml.org/sax/properties/lexical-handler",
- ch);
- InputSource source = new InputSource(in);
- source.setSystemId(systemId);
- r.parse(source);
- }
- catch (SAXException e)
- {
- events.add(e);
- }
- catch (IOException e)
- {
- events.add(e);
- }
- catch (ParserConfigurationException e)
- {
- XMLStreamException e2 = new XMLStreamException(e);
- e2.initCause(e);
- throw e2;
- }
- }
-
- protected XMLStreamReaderImpl(Reader reader,
- String publicId,
- String systemId,
- XMLResolver resolver,
- XMLReporter reporter,
- boolean validating,
- boolean namespaceAware,
- boolean coalescing,
- boolean replacingEntityReferences,
- boolean externalEntities,
- boolean supportDTD)
- throws XMLStreamException
- {
- //this.reader = reader;
- this.publicId = publicId;
- this.systemId = systemId;
- this.resolver = resolver;
- this.reporter = reporter;
- this.validating = validating;
- this.namespaceAware = namespaceAware;
- this.coalescing = coalescing;
- this.replacingEntityReferences = replacingEntityReferences;
- this.externalEntities = externalEntities;
- this.supportDTD = supportDTD;
- namespaces = new NamespaceSupport();
- events = new LinkedList();
-
- // Configure the SAX parser and perform the parse
- try
- {
- SAXParserFactory f = SAXParserFactory.newInstance();
- f.setNamespaceAware(namespaceAware);
- f.setValidating(validating);
- SAXParser p = f.newSAXParser();
- XMLReader r = p.getXMLReader();
- CallbackHandler ch = this.new CallbackHandler(r);
- r.setFeature("http://xml.org/sax/features/external-general-entities",
- externalEntities);
- r.setFeature("http://xml.org/sax/features/namespaces",
- namespaceAware);
- r.setContentHandler(ch);
- r.setDTDHandler(ch);
- r.setEntityResolver(ch);
- r.setErrorHandler(ch);
- r.setProperty("http://xml.org/sax/properties/lexical-handler",
- ch);
- InputSource source = new InputSource(reader);
- source.setSystemId(systemId);
- r.parse(source);
- }
- catch (SAXException e)
- {
- events.add(e);
- }
- catch (IOException e)
- {
- events.add(e);
- }
- catch (ParserConfigurationException e)
- {
- XMLStreamException e2 = new XMLStreamException(e);
- e2.initCause(e);
- throw e2;
- }
- }
-
- public Object getProperty(String name)
- throws IllegalArgumentException
- {
- throw new IllegalArgumentException(name);
- }
-
- public int next()
- throws XMLStreamException
- {
- if (events.isEmpty())
- throw new XMLStreamException("EOF");
- Object event = events.removeFirst();
- if (event instanceof Exception)
- {
- Exception e = (Exception) event;
- XMLStreamException e2 = new XMLStreamException(e);
- e2.initCause(e);
- throw e2;
- }
- currentEvent = (XMLEvent) event;
- eventType = currentEvent.getEventType();
- return eventType;
- }
-
- public void require(int type, String namespaceURI, String localName)
- throws XMLStreamException
- {
- // TODO
- throw new UnsupportedOperationException();
- }
-
- public String getElementText()
- throws XMLStreamException
- {
- // TODO
- throw new UnsupportedOperationException();
- }
-
- public int nextTag()
- throws XMLStreamException
- {
- int ret;
- do
- {
- ret = next();
- }
- while (ret != XMLStreamConstants.START_ELEMENT &&
- ret != XMLStreamConstants.END_ELEMENT);
- return ret;
- }
-
- public boolean hasNext()
- throws XMLStreamException
- {
- return !events.isEmpty();
- }
-
- public void close()
- throws XMLStreamException
- {
- }
-
- public String getNamespaceURI(String prefix)
- {
- return namespaces.getURI(prefix);
- }
-
- public String getPrefix(String namespaceURI)
- {
- return namespaces.getPrefix(namespaceURI);
- }
-
- public Iterator getPrefixes(String namespaceURI)
- {
- LinkedList acc = new LinkedList();
- for (Enumeration e = namespaces.getPrefixes(namespaceURI);
- e.hasMoreElements(); )
- acc.add(e.nextElement());
- return acc.iterator();
- }
-
- public boolean isStartElement()
- {
- return eventType == START_ELEMENT;
- }
-
- public boolean isEndElement()
- {
- return eventType == END_ELEMENT;
- }
-
- public boolean isCharacters()
- {
- return eventType == CHARACTERS || eventType == CDATA;
- }
-
- public boolean isWhiteSpace()
- {
- return eventType == SPACE;
- }
-
- public String getAttributeValue(String namespaceURI, String localName)
- {
- StartElement se = (StartElement) currentEvent;
- for (Iterator i = se.getAttributes(); i.hasNext(); )
- {
- Attribute attr = (Attribute) i.next();
- QName name = attr.getName();
- if (namespaceURI != null &&
- !namespaceURI.equals(name.getNamespaceURI()))
- continue;
- if (!localName.equals(name.getLocalPart()))
- continue;
- return attr.getValue();
- }
- return null;
- }
-
- public int getAttributeCount()
- {
- StartElement se = (StartElement) currentEvent;
- int count = 0;
- for (Iterator i = se.getAttributes(); i.hasNext(); )
- {
- i.next();
- count++;
- }
- return count;
- }
-
- public QName getAttributeQName(int index)
- {
- StartElement se = (StartElement) currentEvent;
- int count = 0;
- for (Iterator i = se.getAttributes(); i.hasNext(); )
- {
- Attribute attr = (Attribute) i.next();
- if (index == count)
- return attr.getName();
- count++;
- }
- return null;
- }
-
- public String getAttributeNamespace(int index)
- {
- QName name = getAttributeQName(index);
- return (name == null) ? null : name.getNamespaceURI();
- }
-
- public String getAttributeName(int index)
- {
- QName name = getAttributeQName(index);
- return (name == null) ? null : name.getLocalPart();
- }
-
- public String getAttributePrefix(int index)
- {
- QName name = getAttributeQName(index);
- return (name == null) ? null : name.getPrefix();
- }
-
- public String getAttributeType(int index)
- {
- StartElement se = (StartElement) currentEvent;
- int count = 0;
- for (Iterator i = se.getAttributes(); i.hasNext(); )
- {
- Attribute attr = (Attribute) i.next();
- if (index == count)
- {
- QName type = attr.getDTDType();
- return (type == null) ? "CDATA" : type.toString();
- }
- count++;
- }
- return null;
- }
-
- public String getAttributeValue(int index)
- {
- StartElement se = (StartElement) currentEvent;
- int count = 0;
- for (Iterator i = se.getAttributes(); i.hasNext(); )
- {
- Attribute attr = (Attribute) i.next();
- if (index == count)
- return attr.getValue();
- count++;
- }
- return null;
- }
-
- public boolean isAttributeSpecified(int index)
- {
- StartElement se = (StartElement) currentEvent;
- int count = 0;
- for (Iterator i = se.getAttributes(); i.hasNext(); )
- {
- Attribute attr = (Attribute) i.next();
- if (index == count)
- return attr.isSpecified();
- count++;
- }
- return false;
- }
-
- public int getNamespaceCount()
- {
- Iterator i = null;
- switch (eventType)
- {
- case XMLStreamConstants.START_ELEMENT:
- i = ((StartElement) currentEvent).getNamespaces();
- break;
- case XMLStreamConstants.END_ELEMENT:
- i = ((EndElement) currentEvent).getNamespaces();
- break;
- default:
- throw new IllegalStateException();
- }
- int count = 0;
- while (i.hasNext())
- {
- i.next();
- count++;
- }
- return count;
- }
-
- public String getNamespacePrefix(int index)
- {
- Iterator i = null;
- switch (eventType)
- {
- case XMLStreamConstants.START_ELEMENT:
- i = ((StartElement) currentEvent).getNamespaces();
- break;
- case XMLStreamConstants.END_ELEMENT:
- i = ((EndElement) currentEvent).getNamespaces();
- break;
- default:
- throw new IllegalStateException();
- }
- int count = 0;
- while (i.hasNext())
- {
- Namespace ns = (Namespace) i.next();
- if (index == count)
- return ns.getPrefix();
- count++;
- }
- return null;
- }
-
- public String getNamespaceURI(int index)
- {
- Iterator i = null;
- switch (eventType)
- {
- case XMLStreamConstants.START_ELEMENT:
- i = ((StartElement) currentEvent).getNamespaces();
- break;
- case XMLStreamConstants.END_ELEMENT:
- i = ((EndElement) currentEvent).getNamespaces();
- break;
- default:
- throw new IllegalStateException();
- }
- int count = 0;
- while (i.hasNext())
- {
- Namespace ns = (Namespace) i.next();
- if (index == count)
- return ns.getNamespaceURI();
- count++;
- }
- return null;
- }
-
- public NamespaceContext getNamespaceContext()
- {
- return this;
- }
-
- public int getEventType()
- {
- return eventType;
- }
-
- public String getText()
- {
- switch (eventType)
- {
- case XMLStreamConstants.CHARACTERS:
- case XMLStreamConstants.CDATA:
- case XMLStreamConstants.SPACE:
- return ((Characters) currentEvent).getData();
- case XMLStreamConstants.COMMENT:
- return ((Comment) currentEvent).getText();
- case XMLStreamConstants.ENTITY_REFERENCE:
- return ((EntityReference) currentEvent).getReplacementText();
- case XMLStreamConstants.DTD:
- return ((DTD) currentEvent).getDocumentTypeDeclaration();
- }
- return null;
- }
-
- public char[] getTextCharacters()
- {
- String text = getText();
- return (text == null) ? null : text.toCharArray();
- }
-
- public int getTextCharacters(int sourceStart, char[] target,
- int targetStart, int length)
- throws XMLStreamException
- {
- char[] source = getTextCharacters();
- int len = Math.min(source.length, length);
- System.arraycopy(source, sourceStart, target, targetStart, len);
- return len;
- }
-
- public int getTextStart()
- {
- return 0;
- }
-
- public int getTextLength()
- {
- String text = getText();
- return (text == null) ? 0 : text.length();
- }
-
- public String getEncoding()
- {
- // XXX SAX doesn't provide this
- return null;
- }
-
- public boolean hasText()
- {
- return eventType == CHARACTERS || eventType == DTD ||
- eventType == SPACE || eventType == ENTITY_REFERENCE ||
- eventType == COMMENT || eventType == DTD;
- }
-
- public Location getLocation()
- {
- return currentEvent.getLocation();
- }
-
- public QName getName()
- {
- switch (eventType)
- {
- case XMLStreamConstants.START_ELEMENT:
- return ((StartElement) currentEvent).getName();
- case XMLStreamConstants.END_ELEMENT:
- return ((EndElement) currentEvent).getName();
- case XMLStreamConstants.ATTRIBUTE:
- return ((Attribute) currentEvent).getName();
- }
- return null;
- }
-
- public String getLocalName()
- {
- QName name = getName();
- return (name == null) ? null : name.getLocalPart();
- }
-
- public boolean hasName()
- {
- return getName() != null;
- }
-
- public String getNamespaceURI()
- {
- QName name = getName();
- return (name == null) ? null : name.getNamespaceURI();
- }
-
- public String getPrefix()
- {
- QName name = getName();
- return (name == null) ? null : name.getPrefix();
- }
-
- public String getVersion()
- {
- StartDocument sd = (StartDocument) currentEvent;
- return sd.getVersion();
- }
-
- public boolean isStandalone()
- {
- StartDocument sd = (StartDocument) currentEvent;
- return sd.isStandalone();
- }
-
- public boolean standaloneSet()
- {
- StartDocument sd = (StartDocument) currentEvent;
- return sd.standaloneSet();
- }
-
- public String getCharacterEncodingScheme()
- {
- StartDocument sd = (StartDocument) currentEvent;
- return sd.getCharacterEncodingScheme();
- }
-
- public String getPITarget()
- {
- ProcessingInstruction pi = (ProcessingInstruction) currentEvent;
- return pi.getTarget();
- }
-
- public String getPIData()
- {
- ProcessingInstruction pi = (ProcessingInstruction) currentEvent;
- return pi.getData();
- }
-
- /**
- * This class is used to construct the event series from SAX callbacks.
- */
- class CallbackHandler
- implements ContentHandler, DTDHandler, LexicalHandler,
- DeclHandler, EntityResolver, ErrorHandler
- {
-
- XMLReader reader;
- Locator locator;
- Location location;
- private boolean inCDATA;
- private LinkedList namespaces = new LinkedList();
- private LinkedList notations;
- private LinkedList entities;
-
- CallbackHandler(XMLReader reader)
- {
- this.reader = reader;
- }
-
- public void setDocumentLocator(Locator locator)
- {
- this.locator = locator;
- location = new LocationImpl(-1,
- locator.getColumnNumber(),
- locator.getLineNumber(),
- locator.getSystemId());
- }
-
- public void startDocument()
- throws SAXException
- {
- String version = (locator instanceof Locator2) ?
- ((Locator2) locator).getXMLVersion() : null;
- String encoding = (locator instanceof Locator2) ?
- ((Locator2) locator).getEncoding() : null;
- boolean standalone =
- reader.getFeature("http://xml.org/sax/features/is-standalone");
- boolean standaloneDeclared = standalone;
- boolean encodingDeclared = (encoding != null);
- events.add(new StartDocumentImpl(location,
- location.getLocationURI(),
- encoding,
- version,
- standalone,
- standaloneDeclared,
- encodingDeclared));
- }
-
- public void endDocument()
- throws SAXException
- {
- events.add(new EndDocumentImpl(location));
- }
-
- public void startPrefixMapping(String prefix, String uri)
- throws SAXException
- {
- namespaces.add(new NamespaceImpl(location, prefix, uri));
- }
-
- public void endPrefixMapping(String prefix)
- throws SAXException
- {
- }
-
- public void startElement(String namespaceURI, String localName,
- String qName, Attributes atts)
- throws SAXException
- {
- LinkedList ns = namespaces;
- namespaces = new LinkedList();
- int ci = qName.indexOf(':');
- String prefix = null;
- localName = qName;
- if (ci != -1)
- {
- prefix = qName.substring(0, ci);
- localName = qName.substring(ci + 1);
- }
- QName name = new QName(namespaceURI, localName, prefix);
- LinkedList attrs = new LinkedList();
- StartElementImpl se = new StartElementImpl(location, name,
- attrs, ns, null);
- events.add(se);
- // Add namespaces
- //for (Iterator i = ns.iterator(); i.hasNext(); )
- // events.add(i.next());
- // Add attributes
- int len = atts.getLength();
- for (int i = 0; i < len; i++)
- {
- String attURI = atts.getURI(i);
- String attQName = atts.getQName(i);
- String value = atts.getValue(i);
- QName type = QName.valueOf(atts.getType(i));
- boolean specified = (atts instanceof Attributes2) &&
- ((Attributes2) atts).isSpecified(i);
- ci = attQName.indexOf(':');
- String attPrefix = null;
- String attLocalName = attQName;
- if (ci != -1)
- {
- attPrefix = attQName.substring(0, ci);
- attLocalName = attQName.substring(ci + 1);
- }
- if ("xmlns".equals(attPrefix) || "xmlns".equals(attQName))
- continue;
- QName attrName = new QName(attURI, attLocalName, attPrefix);
- AttributeImpl attr = new AttributeImpl(location, attrName,
- value, type, specified);
- attrs.add(attr);
- //events.add(attr);
- }
- }
-
- public void endElement(String namespaceURI, String localName,
- String qName)
- throws SAXException
- {
- int ci = qName.indexOf(':');
- String prefix = null;
- localName = qName;
- if (ci != -1)
- {
- prefix = qName.substring(0, ci);
- localName = qName.substring(ci + 1);
- }
- QName name = new QName(namespaceURI, localName, prefix);
- events.add(new EndElementImpl(location, name, new LinkedList()));
- // TODO namespaces out of scope
- }
-
- public void characters(char[] ch, int start, int length)
- throws SAXException
- {
- boolean whitespace = isWhitespace(ch, start, length);
- events.add(new CharactersImpl(location, new String(ch, start, length),
- whitespace, inCDATA, false));
- }
-
- public void ignorableWhitespace(char[] ch, int start, int length)
- throws SAXException
- {
- boolean whitespace = isWhitespace(ch, start, length);
- events.add(new CharactersImpl(location, new String(ch, start, length),
- whitespace, inCDATA, true));
- }
-
- boolean isWhitespace(char[] ch, int start, int len)
- {
- int end = start + len;
- for (int i = start; i < end; i++)
- {
- char c = ch[i];
- if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
- return false;
- }
- return true;
- }
-
- public void processingInstruction(String target, String data)
- throws SAXException
- {
- events.add(new ProcessingInstructionImpl(location, target, data));
- }
-
- public void skippedEntity(String name)
- throws SAXException
- {
- }
-
- public void startDTD(String name, String publicId, String systemId)
- throws SAXException
- {
- notations = new LinkedList();
- entities = new LinkedList();
- events.add(new DTDImpl(location, null, null, notations, entities));
- }
-
- public void endDTD()
- throws SAXException
- {
- }
-
- public void startEntity(String name)
- throws SAXException
- {
- events.add(new StartEntityImpl(location, name));
- }
-
- public void endEntity(String name)
- throws SAXException
- {
- events.add(new EndEntityImpl(location, name));
- }
-
- public void startCDATA()
- throws SAXException
- {
- inCDATA = true;
- }
-
- public void endCDATA()
- throws SAXException
- {
- inCDATA = false;
- }
-
- public void comment(char[] ch, int start, int length)
- throws SAXException
- {
- events.add(new CommentImpl(location, new String(ch, start, length)));
- }
-
- public void notationDecl(String name, String publicId, String systemId)
- throws SAXException
- {
- Object n = new NotationDeclarationImpl(location, name, publicId,
- systemId);
- notations.add(n);
- //events.add(n);
- }
-
- public void unparsedEntityDecl(String name, String publicId,
- String systemId, String notationName)
- throws SAXException
- {
- Object e = new EntityDeclarationImpl(location, publicId, systemId,
- name, notationName,
- null, null);
- entities.add(e);
- //events.add(e);
- }
-
- public void elementDecl(String name, String model)
- throws SAXException
- {
- }
-
- public void attributeDecl(String eName, String aName, String type,
- String valueDefault, String value)
- throws SAXException
- {
- }
-
- public void internalEntityDecl(String name, String value)
- throws SAXException
- {
- Object e = new EntityDeclarationImpl(location, null, null,
- name, null, value, null);
- entities.add(e);
- //events.add(e);
- }
-
- public void externalEntityDecl(String name, String publicId,
- String systemId)
- throws SAXException
- {
- Object e = new EntityDeclarationImpl(location, publicId, systemId,
- name, null, null, null);
- entities.add(e);
- //events.add(e);
- }
-
- public void warning(SAXParseException e)
- throws SAXException
- {
- if (reporter != null)
- {
- try
- {
- reporter.report(e.getMessage(), "warning", e, location);
- }
- catch (XMLStreamException e2)
- {
- SAXException e3 = new SAXException(e2.getMessage());
- e3.initCause(e2);
- throw e3;
- }
- }
- }
-
- public void error(SAXParseException e)
- throws SAXException
- {
- if (reporter != null)
- {
- try
- {
- reporter.report(e.getMessage(), "error", e, location);
- }
- catch (XMLStreamException e2)
- {
- SAXException e3 = new SAXException(e2.getMessage());
- e3.initCause(e2);
- throw e3;
- }
- }
- }
-
- public void fatalError(SAXParseException e)
- throws SAXException
- {
- if (reporter != null)
- {
- try
- {
- reporter.report(e.getMessage(), "fatal-error", e, location);
- }
- catch (XMLStreamException e2)
- {
- SAXException e3 = new SAXException(e2.getMessage());
- e3.initCause(e2);
- throw e3;
- }
- }
- }
-
- public InputSource resolveEntity(String publicId, String systemId)
- throws SAXException, IOException
- {
- if (resolver != null)
- {
- try
- {
- InputStream in = resolver.resolve(systemId);
- if (in != null)
- {
- InputSource ret = new InputSource(in);
- ret.setPublicId(publicId);
- ret.setSystemId(systemId);
- return ret;
- }
- }
- catch (XMLStreamException e)
- {
- SAXException e2 = new SAXException(e.getMessage());
- e2.initCause(e);
- throw e2;
- }
- }
- return null;
- }
-
- }
-
-}
-
diff --git a/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java b/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java
index 6157296c6b8..291016e6716 100644
--- a/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java
@@ -104,6 +104,9 @@ public class XMLStreamWriterImpl
private NamespaceSupport namespaces;
private int count = 0;
+ private boolean xml11;
+ private boolean hasXML11RestrictedChars;
+
/**
* Constructor.
* @see #writer
@@ -145,6 +148,9 @@ public class XMLStreamWriterImpl
{
try
{
+ if (!isName(localName))
+ throw new IllegalArgumentException("illegal Name: " + localName);
+
endStartElement();
namespaces.pushContext();
@@ -167,6 +173,11 @@ public class XMLStreamWriterImpl
{
try
{
+ if (namespaceURI != null && !isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (!isName(localName))
+ throw new IllegalArgumentException("illegal Name: " + localName);
+
endStartElement();
namespaces.pushContext();
@@ -190,7 +201,7 @@ public class XMLStreamWriterImpl
inStartElement = true;
if (!isDeclared)
{
- writeNamespace(prefix, namespaceURI);
+ writeNamespaceImpl(prefix, namespaceURI);
}
elements.addLast(new String[] { prefix, localName });
@@ -229,6 +240,13 @@ public class XMLStreamWriterImpl
{
try
{
+ if (namespaceURI != null && !isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (prefix != null && !isNCName(prefix))
+ throw new IllegalArgumentException("illegal NCName: " + prefix);
+ if (!isNCName(localName))
+ throw new IllegalArgumentException("illegal NCName: " + localName);
+
endStartElement();
namespaces.pushContext();
@@ -243,7 +261,7 @@ public class XMLStreamWriterImpl
writer.write(localName);
if (prefixDefaulting && !isCurrent)
{
- writeNamespace(prefix, namespaceURI);
+ writeNamespaceImpl(prefix, namespaceURI);
}
elements.addLast(new String[] { prefix, localName });
@@ -343,11 +361,19 @@ public class XMLStreamWriterImpl
throw new IllegalStateException();
try
{
+ if (!isName(localName))
+ throw new IllegalArgumentException("illegal Name: " + localName);
+ if (!isChars(value))
+ throw new IllegalArgumentException("illegal character: " + value);
+
writer.write(' ');
writer.write(localName);
writer.write('=');
writer.write('"');
- writeEncoded(value, true);
+ if (hasXML11RestrictedChars)
+ writeEncodedWithRestrictedChars(value, true);
+ else
+ writeEncoded(value, true);
writer.write('"');
}
catch (IOException e)
@@ -366,11 +392,20 @@ public class XMLStreamWriterImpl
throw new IllegalStateException();
try
{
+ if (namespaceURI != null && !isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (prefix != null && !isNCName(prefix))
+ throw new IllegalArgumentException("illegal NCName: " + prefix);
+ if (!isNCName(localName))
+ throw new IllegalArgumentException("illegal NCName: " + localName);
+ if (!isChars(value))
+ throw new IllegalArgumentException("illegal character: " + value);
+
String currentPrefix = getPrefix(namespaceURI);
if (currentPrefix == null)
{
if (prefixDefaulting)
- writeNamespace(prefix, namespaceURI);
+ writeNamespaceImpl(prefix, namespaceURI);
else
throw new XMLStreamException("namespace " + namespaceURI +
" is not bound");
@@ -388,7 +423,10 @@ public class XMLStreamWriterImpl
writer.write(localName);
writer.write('=');
writer.write('"');
- writeEncoded(value, true);
+ if (hasXML11RestrictedChars)
+ writeEncodedWithRestrictedChars(value, true);
+ else
+ writeEncoded(value, true);
writer.write('"');
}
catch (IOException e)
@@ -407,13 +445,20 @@ public class XMLStreamWriterImpl
throw new IllegalStateException();
try
{
+ if (namespaceURI != null && !isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (!isName(localName))
+ throw new IllegalArgumentException("illegal Name: " + localName);
+ if (!isChars(value))
+ throw new IllegalArgumentException("illegal character: " + value);
+
String prefix = getPrefix(namespaceURI);
if (prefix == null)
{
if (prefixDefaulting)
{
prefix = XMLConstants.DEFAULT_NS_PREFIX;
- writeNamespace(prefix, namespaceURI);
+ writeNamespaceImpl(prefix, namespaceURI);
}
else
throw new XMLStreamException("namespace " + namespaceURI +
@@ -428,7 +473,10 @@ public class XMLStreamWriterImpl
writer.write(localName);
writer.write('=');
writer.write('"');
- writeEncoded(value, true);
+ if (hasXML11RestrictedChars)
+ writeEncodedWithRestrictedChars(value, true);
+ else
+ writeEncoded(value, true);
writer.write('"');
}
catch (IOException e)
@@ -446,6 +494,25 @@ public class XMLStreamWriterImpl
throw new IllegalStateException();
try
{
+ if (!isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (!isNCName(prefix))
+ throw new IllegalArgumentException("illegal NCName: " + prefix);
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ writeNamespaceImpl(prefix, namespaceURI);
+ }
+
+ private void writeNamespaceImpl(String prefix, String namespaceURI)
+ throws XMLStreamException
+ {
+ try
+ {
if (prefix == null)
prefix = XMLConstants.DEFAULT_NS_PREFIX;
@@ -474,21 +541,41 @@ public class XMLStreamWriterImpl
public void writeDefaultNamespace(String namespaceURI)
throws XMLStreamException
{
- writeNamespace(XMLConstants.DEFAULT_NS_PREFIX, namespaceURI);
+ if (!inStartElement)
+ throw new IllegalStateException();
+ if (!isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ writeNamespaceImpl(XMLConstants.DEFAULT_NS_PREFIX, namespaceURI);
}
public void writeComment(String data)
throws XMLStreamException
{
+ if (data == null)
+ return;
try
{
+ if (!isChars(data))
+ throw new IllegalArgumentException("illegal XML character: " + data);
+ if (data.indexOf("--") != -1)
+ throw new IllegalArgumentException("illegal comment: " + data);
+
endStartElement();
- if (data != null && data.indexOf("--") != -1)
- throw new IllegalArgumentException(data);
-
writer.write("<!--");
- if (data != null)
+ if (hasXML11RestrictedChars)
+ {
+ int[] seq = UnicodeReader.toCodePointArray(data);
+ for (int i = 0; i < seq.length; i++)
+ {
+ int c = seq[i];
+ if (XMLParser.isXML11RestrictedChar(c))
+ writer.write("&#x" + Integer.toHexString(c) + ";");
+ else
+ writer.write(Character.toChars(i));
+ }
+ }
+ else
writer.write(data);
writer.write("-->");
}
@@ -511,6 +598,11 @@ public class XMLStreamWriterImpl
{
try
{
+ if (!isName(target) || "xml".equalsIgnoreCase(target))
+ throw new IllegalArgumentException("illegal PITarget: " + target);
+ if (data != null && !isChars(data))
+ throw new IllegalArgumentException("illegal XML character: " + data);
+
endStartElement();
writer.write('<');
@@ -519,7 +611,20 @@ public class XMLStreamWriterImpl
if (data != null)
{
writer.write(' ');
- writer.write(data);
+ if (hasXML11RestrictedChars)
+ {
+ int[] seq = UnicodeReader.toCodePointArray(data);
+ for (int i = 0; i < seq.length; i++)
+ {
+ int c = seq[i];
+ if (XMLParser.isXML11RestrictedChar(c))
+ writer.write("&#x" + Integer.toHexString(c) + ";");
+ else
+ writer.write(Character.toChars(i));
+ }
+ }
+ else
+ writer.write(data);
}
writer.write('?');
writer.write('>');
@@ -537,10 +642,12 @@ public class XMLStreamWriterImpl
{
try
{
- endStartElement();
-
+ if (!isChars(data) || hasXML11RestrictedChars)
+ throw new IllegalArgumentException("illegal XML character: " + data);
if (data.indexOf("]]") != -1)
- throw new IllegalArgumentException(data);
+ throw new IllegalArgumentException("illegal CDATA section: " + data);
+
+ endStartElement();
writer.write("<![CDATA[");
writer.write(data);
@@ -557,8 +664,12 @@ public class XMLStreamWriterImpl
public void writeDTD(String dtd)
throws XMLStreamException
{
+ // Really thoroughly pointless method...
try
{
+ if (!isName(dtd))
+ throw new IllegalArgumentException("illegal Name: " + dtd);
+
writer.write("<!DOCTYPE ");
writer.write(dtd);
writer.write('>');
@@ -576,6 +687,9 @@ public class XMLStreamWriterImpl
{
try
{
+ if (!isName(name))
+ throw new IllegalArgumentException("illegal Name: " + name);
+
endStartElement();
writer.write('&');
@@ -607,6 +721,8 @@ public class XMLStreamWriterImpl
{
if (version == null)
version = "1.0";
+ else if ("1.1".equals(version))
+ xml11 = true;
encoding = this.encoding; // YES: the parameter must be ignored
if (encoding == null)
encoding = "UTF-8";
@@ -632,11 +748,18 @@ public class XMLStreamWriterImpl
public void writeCharacters(String text)
throws XMLStreamException
{
+ if (text == null)
+ return;
try
{
+ if (!isChars(text))
+ throw new IllegalArgumentException("illegal XML character: " + text);
+
endStartElement();
- if (text != null)
+ if (hasXML11RestrictedChars)
+ writeEncodedWithRestrictedChars(text, false);
+ else
writeEncoded(text, false);
}
catch (IOException e)
@@ -650,39 +773,7 @@ public class XMLStreamWriterImpl
public void writeCharacters(char[] text, int start, int len)
throws XMLStreamException
{
- try
- {
- endStartElement();
-
- int end = start + len;
- len = 0;
- for (int i = start; i < end; i++)
- {
- char c = text[i];
- if (c == '<' || c == '>' || c == '&')
- {
- writer.write(text, start, len);
- if (c == '<')
- writer.write("&lt;");
- else if (c == '>')
- writer.write("&gt;");
- else
- writer.write("&amp;");
- start = i + 1;
- len = 0;
- }
- else
- len++;
- }
- if (len > 0)
- writer.write(text, start, len);
- }
- catch (IOException e)
- {
- XMLStreamException e2 = new XMLStreamException(e);
- e2.initCause(e);
- throw e2;
- }
+ writeCharacters(new String(text, start, len));
}
public String getPrefix(String uri)
@@ -697,6 +788,19 @@ public class XMLStreamWriterImpl
public void setPrefix(String prefix, String uri)
throws XMLStreamException
{
+ try
+ {
+ if (!isURI(uri))
+ throw new IllegalArgumentException("illegal URI: " + uri);
+ if (!isNCName(prefix))
+ throw new IllegalArgumentException("illegal NCName: " + prefix);
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
if (!namespaces.declarePrefix(prefix, uri))
throw new XMLStreamException("illegal prefix " + prefix);
}
@@ -704,6 +808,8 @@ public class XMLStreamWriterImpl
public void setDefaultNamespace(String uri)
throws XMLStreamException
{
+ if (!isURI(uri))
+ throw new IllegalArgumentException("illegal URI: " + uri);
if (!namespaces.declarePrefix(XMLConstants.DEFAULT_NS_PREFIX, uri))
throw new XMLStreamException("illegal default namespace prefix");
}
@@ -769,6 +875,131 @@ public class XMLStreamWriterImpl
if (len > 0)
writer.write(chars, start, len);
}
+
+ /**
+ * Writes the specified text, in the knowledge that some of the
+ * characters are XML 1.1 restricted characters.
+ */
+ private void writeEncodedWithRestrictedChars(String text, boolean inAttr)
+ throws IOException
+ {
+ int[] seq = UnicodeReader.toCodePointArray(text);
+ for (int i = 0; i < seq.length; i++)
+ {
+ int c = seq[i];
+ switch (c)
+ {
+ case 0x3c: // '<'
+ writer.write("&lt;");
+ break;
+ case 0x3e: // '>'
+ writer.write("&gt;");
+ break;
+ case 0x26: // '&'
+ writer.write("&amp;");
+ break;
+ case 0x22: // '"'
+ if (inAttr)
+ writer.write("&quot;");
+ else
+ writer.write(c);
+ break;
+ case 0x27: // '\''
+ if (inAttr)
+ writer.write("&apos;");
+ else
+ writer.write(c);
+ break;
+ default:
+ if (XMLParser.isXML11RestrictedChar(c))
+ writer.write("&#x" + Integer.toHexString(c) + ";");
+ else
+ {
+ char[] chars = Character.toChars(c);
+ writer.write(chars, 0, chars.length);
+ }
+ }
+ }
+ }
+
+ private boolean isName(String text)
+ throws IOException
+ {
+ if (text == null)
+ return false;
+ int[] seq = UnicodeReader.toCodePointArray(text);
+ if (seq.length < 1)
+ return false;
+ if (!XMLParser.isNameStartCharacter(seq[0], xml11))
+ return false;
+ for (int i = 1; i < seq.length; i++)
+ {
+ if (!XMLParser.isNameCharacter(seq[i], xml11))
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isNCName(String text)
+ throws IOException
+ {
+ if (text == null)
+ return false;
+ int[] seq = UnicodeReader.toCodePointArray(text);
+ if (seq.length < 1)
+ return false;
+ if (!XMLParser.isNameStartCharacter(seq[0], xml11) || seq[0] == 0x3a)
+ return false;
+ for (int i = 1; i < seq.length; i++)
+ {
+ if (!XMLParser.isNameCharacter(seq[i], xml11) || seq[i] == 0x3a)
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isChars(String text)
+ throws IOException
+ {
+ if (text == null)
+ return false;
+ int[] seq = UnicodeReader.toCodePointArray(text);
+ hasXML11RestrictedChars = false;
+ if (xml11)
+ {
+ for (int i = 0; i < seq.length; i++)
+ {
+ if (!XMLParser.isXML11Char(seq[i]))
+ return false;
+ if (XMLParser.isXML11RestrictedChar(seq[i]))
+ hasXML11RestrictedChars = true;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < seq.length; i++)
+ {
+ if (!XMLParser.isChar(seq[i]))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isURI(String text)
+ {
+ if (text == null)
+ return false;
+ char[] chars = text.toCharArray();
+ if (chars.length < 1)
+ return false;
+ for (int i = 0; i < chars.length; i++)
+ {
+ if (chars[i] < 0x20 || chars[i] >= 0x7f)
+ return false;
+ }
+ return true;
+ }
}
diff --git a/libjava/classpath/gnu/xml/transform/AbstractNumberNode.java b/libjava/classpath/gnu/xml/transform/AbstractNumberNode.java
index 91029d6d070..6d1202e69b4 100644
--- a/libjava/classpath/gnu/xml/transform/AbstractNumberNode.java
+++ b/libjava/classpath/gnu/xml/transform/AbstractNumberNode.java
@@ -317,7 +317,7 @@ abstract class AbstractNumberNode
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("number");
buf.append('[');
buf.append("format=");
buf.append(format);
diff --git a/libjava/classpath/gnu/xml/transform/ApplyImportsNode.java b/libjava/classpath/gnu/xml/transform/ApplyImportsNode.java
index 60dec85d378..4b06eea1041 100644
--- a/libjava/classpath/gnu/xml/transform/ApplyImportsNode.java
+++ b/libjava/classpath/gnu/xml/transform/ApplyImportsNode.java
@@ -1,5 +1,5 @@
/* ApplyImportsNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -54,13 +54,9 @@ final class ApplyImportsNode
{
TemplateNode ret = new ApplyImportsNode();
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -71,15 +67,16 @@ final class ApplyImportsNode
{
TemplateNode t = stylesheet.getTemplate(mode, context, true);
if (t != null)
- {
- t.apply(stylesheet, mode, context, pos, len,
- parent, nextSibling);
- }
+ t.apply(stylesheet, mode, context, pos, len,
+ parent, nextSibling);
if (next != null)
- {
- next.apply(stylesheet, mode, context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode, context, pos, len,
+ parent, nextSibling);
+ }
+
+ public String toString()
+ {
+ return "apply-imports";
}
}
diff --git a/libjava/classpath/gnu/xml/transform/ApplyTemplatesNode.java b/libjava/classpath/gnu/xml/transform/ApplyTemplatesNode.java
index ab26058bcb4..38b605a07ed 100644
--- a/libjava/classpath/gnu/xml/transform/ApplyTemplatesNode.java
+++ b/libjava/classpath/gnu/xml/transform/ApplyTemplatesNode.java
@@ -1,5 +1,5 @@
/* ApplyTemplatesNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -76,29 +76,21 @@ final class ApplyTemplatesNode
TemplateNode clone(Stylesheet stylesheet)
{
- int len = sortKeys.size();
+ int len = sortKeys != null ? sortKeys.size() : 0;
List sortKeys2 = new ArrayList(len);
for (int i = 0; i < len; i++)
- {
- sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
- }
+ sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
len = withParams.size();
List withParams2 = new ArrayList(len);
for (int i = 0; i < len; i++)
- {
- withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
- }
+ withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
TemplateNode ret = new ApplyTemplatesNode(select.clone(stylesheet),
mode, sortKeys2, withParams2,
isDefault);
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -147,9 +139,7 @@ final class ApplyTemplatesNode
Collections.sort(nodes, new XSLComparator(sortKeys));
}
else
- {
- Collections.sort(nodes, documentOrderComparator);
- }
+ Collections.sort(nodes, documentOrderComparator);
int l = nodes.size();
QName effectiveMode = isDefault ? mode : this.mode;
for (int i = 0; i < l; i++)
@@ -172,27 +162,21 @@ final class ApplyTemplatesNode
}
// apply-templates doesn't have processable children
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public boolean references(QName var)
{
if (select != null && select.references(var))
- {
- return true;
- }
+ return true;
if (withParams != null)
{
for (Iterator i = withParams.iterator(); i.hasNext(); )
{
if (((WithParam) i.next()).references(var))
- {
- return true;
- }
+ return true;
}
}
if (sortKeys != null)
@@ -200,9 +184,7 @@ final class ApplyTemplatesNode
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
{
if (((SortKey) i.next()).references(var))
- {
- return true;
- }
+ return true;
}
}
return super.references(var);
@@ -210,7 +192,7 @@ final class ApplyTemplatesNode
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("apply-templates");
buf.append('[');
boolean o = false;
if (select != null)
diff --git a/libjava/classpath/gnu/xml/transform/AttributeNode.java b/libjava/classpath/gnu/xml/transform/AttributeNode.java
index bc5bc30c9c1..71e2ed0f7af 100644
--- a/libjava/classpath/gnu/xml/transform/AttributeNode.java
+++ b/libjava/classpath/gnu/xml/transform/AttributeNode.java
@@ -231,7 +231,7 @@ final class AttributeNode
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("attribute");
buf.append('[');
buf.append("name=");
buf.append(name);
diff --git a/libjava/classpath/gnu/xml/transform/CallTemplateNode.java b/libjava/classpath/gnu/xml/transform/CallTemplateNode.java
index b678219d780..31b26cbcdb0 100644
--- a/libjava/classpath/gnu/xml/transform/CallTemplateNode.java
+++ b/libjava/classpath/gnu/xml/transform/CallTemplateNode.java
@@ -1,5 +1,5 @@
/* CallTemplateNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -69,18 +69,12 @@ final class CallTemplateNode
int len = withParams.size();
List withParams2 = new ArrayList(len);
for (int i = 0; i < len; i++)
- {
- withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
- }
+ withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
TemplateNode ret = new CallTemplateNode(name, withParams2);
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -89,52 +83,52 @@ final class CallTemplateNode
Node parent, Node nextSibling)
throws TransformerException
{
- if (withParams != null)
+ TemplateNode t = stylesheet.getTemplate(mode, name);
+ if (t != null)
{
- // compute the parameter values
- LinkedList values = new LinkedList();
- for (Iterator i = withParams.iterator(); i.hasNext(); )
+ if (withParams != null)
{
- WithParam p = (WithParam) i.next();
- Object value = p.getValue(stylesheet, mode, context, pos, len);
- Object[] pair = new Object[2];
- pair[0] = p.name;
- pair[1] = value;
- values.add(pair);
- }
- // push the parameter context
- stylesheet.bindings.push(Bindings.WITH_PARAM);
- // set the parameters
- for (Iterator i = values.iterator(); i.hasNext(); )
- {
- Object[] pair = (Object[]) i.next();
- QName name = (QName) pair[0];
- Object value = pair[1];
- stylesheet.bindings.set(name, value, Bindings.WITH_PARAM);
- if (stylesheet.debug)
+ // compute the parameter values
+ LinkedList values = new LinkedList();
+ for (Iterator i = withParams.iterator(); i.hasNext(); )
+ {
+ WithParam p = (WithParam) i.next();
+ if (t.hasParam(p.name)) // ignore parameters not specified
+ {
+ Object value = p.getValue(stylesheet, mode, context,
+ pos, len);
+ Object[] pair = new Object[2];
+ pair[0] = p.name;
+ pair[1] = value;
+ values.add(pair);
+ }
+ }
+ // push the parameter context
+ stylesheet.bindings.push(Bindings.WITH_PARAM);
+ // set the parameters
+ for (Iterator i = values.iterator(); i.hasNext(); )
{
- System.err.println("with-param: " + name + " = " + value);
+ Object[] pair = (Object[]) i.next();
+ QName name = (QName) pair[0];
+ Object value = pair[1];
+ stylesheet.bindings.set(name, value, Bindings.WITH_PARAM);
+ if (stylesheet.debug)
+ System.err.println("with-param: " + name + " = " + value);
}
}
- }
- TemplateNode t = stylesheet.getTemplate(mode, name);
- if (t != null)
- {
t.apply(stylesheet, mode, context, pos, len,
parent, nextSibling);
- }
- if (withParams != null)
- {
- // pop the variable context
- stylesheet.bindings.pop(Bindings.WITH_PARAM);
+ if (withParams != null)
+ {
+ // pop the variable context
+ stylesheet.bindings.pop(Bindings.WITH_PARAM);
+ }
}
// call-template doesn't have processable children
if (next != null)
- {
next.apply(stylesheet, mode,
context, pos, len,
parent, nextSibling);
- }
}
public boolean references(QName var)
@@ -144,9 +138,7 @@ final class CallTemplateNode
for (Iterator i = withParams.iterator(); i.hasNext(); )
{
if (((WithParam) i.next()).references(var))
- {
- return true;
- }
+ return true;
}
}
return super.references(var);
@@ -154,7 +146,7 @@ final class CallTemplateNode
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("call-template");
buf.append('[');
buf.append("name=");
buf.append(name);
diff --git a/libjava/classpath/gnu/xml/transform/ChooseNode.java b/libjava/classpath/gnu/xml/transform/ChooseNode.java
index fb1f2c45e75..cf07fa54b07 100644
--- a/libjava/classpath/gnu/xml/transform/ChooseNode.java
+++ b/libjava/classpath/gnu/xml/transform/ChooseNode.java
@@ -1,5 +1,5 @@
/* ChooseNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -54,13 +54,9 @@ final class ChooseNode
{
TemplateNode ret = new ChooseNode();
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -70,22 +66,18 @@ final class ChooseNode
throws TransformerException
{
if (children != null)
- {
- children.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ children.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("choose");
buf.append('[');
buf.append(']');
return buf.toString();
diff --git a/libjava/classpath/gnu/xml/transform/CommentNode.java b/libjava/classpath/gnu/xml/transform/CommentNode.java
index 1428a46fca1..8131fb28650 100644
--- a/libjava/classpath/gnu/xml/transform/CommentNode.java
+++ b/libjava/classpath/gnu/xml/transform/CommentNode.java
@@ -1,5 +1,5 @@
/* CommentNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -58,13 +58,9 @@ final class CommentNode
{
TemplateNode ret = new CommentNode();
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -90,27 +86,18 @@ final class CommentNode
Comment comment = doc.createComment(value);
// Insert into result tree
if (nextSibling != null)
- {
- parent.insertBefore(comment, nextSibling);
- }
+ parent.insertBefore(comment, nextSibling);
else
- {
- parent.appendChild(comment);
- }
+ parent.appendChild(comment);
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
- buf.append('[');
- buf.append(']');
- return buf.toString();
+ return "comment";
}
}
diff --git a/libjava/classpath/gnu/xml/transform/CopyNode.java b/libjava/classpath/gnu/xml/transform/CopyNode.java
index 3e019445aaa..64cfa519158 100644
--- a/libjava/classpath/gnu/xml/transform/CopyNode.java
+++ b/libjava/classpath/gnu/xml/transform/CopyNode.java
@@ -1,5 +1,5 @@
/* CopyNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -65,13 +65,9 @@ final class CopyNode
{
TemplateNode ret = new CopyNode(uas);
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -102,44 +98,32 @@ final class CopyNode
{
NamedNodeMap attrs = parent.getAttributes();
if (attrs != null)
- {
- attrs.setNamedItemNS(copy);
- }
+ attrs.setNamedItemNS(copy);
}
}
else
{
if (nextSibling != null)
- {
- parent.insertBefore(copy, nextSibling);
- }
+ parent.insertBefore(copy, nextSibling);
else
- {
- parent.appendChild(copy);
- }
+ parent.appendChild(copy);
}
}
if (uas != null)
{
StringTokenizer st = new StringTokenizer(uas, " ");
while (st.hasMoreTokens())
- {
- addAttributeSet(stylesheet, mode, context, pos, len,
- copy, null, st.nextToken());
- }
+ addAttributeSet(stylesheet, mode, context, pos, len,
+ copy, null, st.nextToken());
}
if (children != null)
- {
- children.apply(stylesheet, mode,
- context, pos, len,
- copy, null);
- }
+ children.apply(stylesheet, mode,
+ context, pos, len,
+ copy, null);
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
void addAttributeSet(Stylesheet stylesheet, QName mode,
@@ -151,32 +135,31 @@ final class CopyNode
{
AttributeSet as = (AttributeSet) i.next();
if (!as.name.equals(attributeSet))
- {
- continue;
- }
+ continue;
if (as.uas != null)
{
StringTokenizer st = new StringTokenizer(as.uas, " ");
while (st.hasMoreTokens())
- {
- addAttributeSet(stylesheet, mode, context, pos, len,
- parent, nextSibling, st.nextToken());
- }
+ addAttributeSet(stylesheet, mode, context, pos, len,
+ parent, nextSibling, st.nextToken());
}
if (as.children != null)
- {
- as.children.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ as.children.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
- buf.append('[');
- buf.append(']');
+ StringBuffer buf = new StringBuffer("copy");
+ if (uas != null)
+ {
+ buf.append('[');
+ buf.append("uas=");
+ buf.append(uas);
+ buf.append(']');
+ }
return buf.toString();
}
diff --git a/libjava/classpath/gnu/xml/transform/CopyOfNode.java b/libjava/classpath/gnu/xml/transform/CopyOfNode.java
index a43e3ba841e..ed4358c90b6 100644
--- a/libjava/classpath/gnu/xml/transform/CopyOfNode.java
+++ b/libjava/classpath/gnu/xml/transform/CopyOfNode.java
@@ -1,5 +1,5 @@
/* CopyOfNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -70,13 +70,9 @@ final class CopyOfNode
{
TemplateNode ret = new CopyOfNode(select.clone(stylesheet));
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -102,9 +98,7 @@ final class CopyOfNode
// Use document element
src = ((Document) src).getDocumentElement();
if (src == null)
- {
- continue;
- }
+ continue;
nodeType = Node.ELEMENT_NODE;
}
else if (nodeType == Node.ATTRIBUTE_NODE)
@@ -128,20 +122,14 @@ final class CopyOfNode
{
NamedNodeMap attrs = parent.getAttributes();
if (attrs != null)
- {
- attrs.setNamedItemNS(node);
- }
+ attrs.setNamedItemNS(node);
}
else
{
if (nextSibling != null)
- {
- parent.insertBefore(node, nextSibling);
- }
+ parent.insertBefore(node, nextSibling);
else
- {
- parent.appendChild(node);
- }
+ parent.appendChild(node);
}
}
}
@@ -152,36 +140,28 @@ final class CopyOfNode
{
Text textNode = doc.createTextNode(value);
if (nextSibling != null)
- {
- parent.insertBefore(textNode, nextSibling);
- }
+ parent.insertBefore(textNode, nextSibling);
else
- {
- parent.appendChild(textNode);
- }
+ parent.appendChild(textNode);
}
}
// copy-of doesn't process children
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public boolean references(QName var)
{
if (select != null && select.references(var))
- {
- return true;
- }
+ return true;
return super.references(var);
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("copy-of");
buf.append('[');
buf.append("select=");
buf.append(select);
diff --git a/libjava/classpath/gnu/xml/transform/DocumentFunction.java b/libjava/classpath/gnu/xml/transform/DocumentFunction.java
index d8f6090be66..29f3d4a4598 100644
--- a/libjava/classpath/gnu/xml/transform/DocumentFunction.java
+++ b/libjava/classpath/gnu/xml/transform/DocumentFunction.java
@@ -126,9 +126,7 @@ final class DocumentFunction
Object arg1 = values.get(0);
Object arg2 = values.get(1);
if (!(arg2 instanceof Collection))
- {
- throw new RuntimeException("second argument is not a node-set");
- }
+ throw new RuntimeException("second argument is not a node-set");
Collection arg2ns = (Collection) arg2;
String base2 = arg2ns.isEmpty() ? null :
((Node) arg2ns.iterator().next()).getBaseURI();
@@ -166,9 +164,7 @@ final class DocumentFunction
Collection document(String uri, String base)
{
if ("".equals(uri) || uri == null)
- {
- uri = this.base.getBaseURI();
- }
+ uri = this.base.getBaseURI();
// Get fragment
Expr fragment = null;
@@ -197,10 +193,10 @@ final class DocumentFunction
source = resolver.resolveDOM(null, base, uri);
}
Node node = source.getNode();
+ // Strip whitespace
+ TransformerImpl.strip(stylesheet, node);
if (fragment == null)
- {
- return Collections.singleton(node);
- }
+ return Collections.singleton(node);
else
{
Object ret = fragment.evaluate(node, 1, 1);
@@ -216,9 +212,7 @@ final class DocumentFunction
{
String msg = "can't open " + uri;
if (base != null)
- {
- msg += " with base " + base;
- }
+ msg += " with base " + base;
throw new RuntimeException(msg);
}
}
@@ -227,16 +221,12 @@ final class DocumentFunction
{
Stylesheet s = stylesheet;
if (context instanceof Stylesheet)
- {
- s = (Stylesheet) context;
- }
+ s = (Stylesheet) context;
DocumentFunction f = new DocumentFunction(s, base);
int len = args.size();
List args2 = new ArrayList(len);
for (int i = 0; i < len; i++)
- {
- args2.add(((Expr) args.get(i)).clone(context));
- }
+ args2.add(((Expr) args.get(i)).clone(context));
f.setArguments(args2);
return f;
}
@@ -246,9 +236,7 @@ final class DocumentFunction
for (Iterator i = args.iterator(); i.hasNext(); )
{
if (((Expr) i.next()).references(var))
- {
- return true;
- }
+ return true;
}
return false;
}
diff --git a/libjava/classpath/gnu/xml/transform/ElementNode.java b/libjava/classpath/gnu/xml/transform/ElementNode.java
index 092c56a4b64..b6a5c365b12 100644
--- a/libjava/classpath/gnu/xml/transform/ElementNode.java
+++ b/libjava/classpath/gnu/xml/transform/ElementNode.java
@@ -1,5 +1,5 @@
/* ElementNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -238,7 +238,7 @@ final class ElementNode
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("element");
buf.append('[');
buf.append("name=");
if (namespace != null)
diff --git a/libjava/classpath/gnu/xml/transform/ForEachNode.java b/libjava/classpath/gnu/xml/transform/ForEachNode.java
index 8f9220f679b..c8f51a6febb 100644
--- a/libjava/classpath/gnu/xml/transform/ForEachNode.java
+++ b/libjava/classpath/gnu/xml/transform/ForEachNode.java
@@ -1,5 +1,5 @@
/* ForEachNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -70,19 +70,13 @@ final class ForEachNode
int len = sortKeys.size();
List sortKeys2 = new ArrayList(len);
for (int i = 0; i < len; i++)
- {
- sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
- }
+ sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
TemplateNode ret = new ForEachNode(select.clone(stylesheet),
sortKeys2);
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -113,9 +107,7 @@ final class ForEachNode
Collections.sort(list, new XSLComparator(sortKeys));
}
else
- {
- Collections.sort(list, documentOrderComparator);
- }
+ Collections.sort(list, documentOrderComparator);
// Perform children for each node
int l = list.size();
int p = 1;
@@ -132,27 +124,21 @@ final class ForEachNode
stylesheet.currentTemplate = saved;
}
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public boolean references(QName var)
{
if (select != null && select.references(var))
- {
- return true;
- }
+ return true;
if (sortKeys != null)
{
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
{
if (((SortKey) i.next()).references(var))
- {
- return true;
- }
+ return true;
}
}
return super.references(var);
@@ -160,7 +146,7 @@ final class ForEachNode
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("for-each");
buf.append('[');
buf.append("select=");
buf.append(select);
diff --git a/libjava/classpath/gnu/xml/transform/IfNode.java b/libjava/classpath/gnu/xml/transform/IfNode.java
index 17e2486fe83..2a00d64ca82 100644
--- a/libjava/classpath/gnu/xml/transform/IfNode.java
+++ b/libjava/classpath/gnu/xml/transform/IfNode.java
@@ -1,5 +1,5 @@
/* IfNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -62,19 +62,15 @@ final class IfNode
{
TemplateNode ret = new IfNode(test.clone(stylesheet));
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
void doApply(Stylesheet stylesheet, QName mode,
- Node context, int pos, int len,
- Node parent, Node nextSibling)
+ Node context, int pos, int len,
+ Node parent, Node nextSibling)
throws TransformerException
{
Object ret = test.evaluate(context, pos, len);
@@ -84,32 +80,26 @@ final class IfNode
if (success)
{
if (children != null)
- {
- children.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ children.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public boolean references(QName var)
{
if (test != null && test.references(var))
- {
- return true;
- }
+ return true;
return super.references(var);
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("if");
buf.append('[');
buf.append("test=");
buf.append(test);
diff --git a/libjava/classpath/gnu/xml/transform/LiteralNode.java b/libjava/classpath/gnu/xml/transform/LiteralNode.java
index 453c22c5e0d..d4e283a6580 100644
--- a/libjava/classpath/gnu/xml/transform/LiteralNode.java
+++ b/libjava/classpath/gnu/xml/transform/LiteralNode.java
@@ -196,12 +196,7 @@ final class LiteralNode
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
- buf.append('[');
- buf.append("source=");
- buf.append(source);
- buf.append(']');
- return buf.toString();
+ return source.toString();
}
}
diff --git a/libjava/classpath/gnu/xml/transform/MessageNode.java b/libjava/classpath/gnu/xml/transform/MessageNode.java
index e8e07c6da29..890d76f6b1c 100644
--- a/libjava/classpath/gnu/xml/transform/MessageNode.java
+++ b/libjava/classpath/gnu/xml/transform/MessageNode.java
@@ -92,5 +92,17 @@ final class MessageNode
if (next != null && !terminate)
next.apply(stylesheet, mode, context, pos, len, parent, nextSibling);
}
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer("message");
+ if (terminate)
+ {
+ buf.append('[');
+ buf.append("terminate");
+ buf.append(']');
+ }
+ return buf.toString();
+ }
}
diff --git a/libjava/classpath/gnu/xml/transform/OtherwiseNode.java b/libjava/classpath/gnu/xml/transform/OtherwiseNode.java
index 570310f6bd5..9d8168ce4f9 100644
--- a/libjava/classpath/gnu/xml/transform/OtherwiseNode.java
+++ b/libjava/classpath/gnu/xml/transform/OtherwiseNode.java
@@ -1,5 +1,5 @@
/* OtherwiseNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -54,13 +54,9 @@ final class OtherwiseNode
{
TemplateNode ret = new OtherwiseNode();
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -70,25 +66,18 @@ final class OtherwiseNode
throws TransformerException
{
if (children != null)
- {
- children.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ children.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
- buf.append('[');
- buf.append(']');
- return buf.toString();
+ return "otherwise";
}
}
diff --git a/libjava/classpath/gnu/xml/transform/ParameterNode.java b/libjava/classpath/gnu/xml/transform/ParameterNode.java
index ef09ea5f9b2..8cd2677cf08 100644
--- a/libjava/classpath/gnu/xml/transform/ParameterNode.java
+++ b/libjava/classpath/gnu/xml/transform/ParameterNode.java
@@ -1,5 +1,5 @@
/* ParameterNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -73,13 +73,9 @@ final class ParameterNode
select.clone(stylesheet),
type);
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
@@ -96,18 +92,14 @@ final class ParameterNode
{
stylesheet.bindings.set(name, value, type);
if (stylesheet.debug)
- {
- System.err.println(this + ": set to " + value);
- }
+ System.err.println(this + ": set to " + value);
}
// variable and param don't process children as such
// all subsequent instructions are processed with that variable context
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
// pop the variable context
stylesheet.bindings.pop(type);
}
@@ -117,9 +109,7 @@ final class ParameterNode
throws TransformerException
{
if (select != null)
- {
- return select.evaluate(context, pos, len);
- }
+ return select.evaluate(context, pos, len);
else if (children != null)
{
Document doc = (context instanceof Document) ? (Document) context :
@@ -129,17 +119,13 @@ final class ParameterNode
return Collections.singleton(fragment);
}
else
- {
- return null;
- }
+ return null;
}
public boolean references(QName var)
{
if (select != null && select.references(var))
- {
- return true;
- }
+ return true;
return super.references(var);
}
@@ -151,33 +137,18 @@ final class ParameterNode
boolean r1 = references(pn.name);
boolean r2 = pn.references(name);
if (r1 && r2)
- {
- throw new IllegalArgumentException("circular definitions");
- }
+ throw new IllegalArgumentException("circular definitions");
if (r1)
- {
- return 1;
- }
+ return 1;
if (r2)
- {
- return -1;
- }
+ return -1;
}
return 0;
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
- buf.append('[');
- buf.append("name=");
- buf.append(name);
- if (select != null)
- {
- buf.append(",select=");
- buf.append(select);
- }
- buf.append(",type=");
+ StringBuffer buf = new StringBuffer();
switch (type)
{
case Bindings.VARIABLE:
@@ -190,6 +161,14 @@ final class ParameterNode
buf.append("with-param");
break;
}
+ buf.append('[');
+ buf.append("name=");
+ buf.append(name);
+ if (select != null)
+ {
+ buf.append(",select=");
+ buf.append(select);
+ }
buf.append(']');
return buf.toString();
}
diff --git a/libjava/classpath/gnu/xml/transform/ProcessingInstructionNode.java b/libjava/classpath/gnu/xml/transform/ProcessingInstructionNode.java
index d75f693663e..bf61fc03880 100644
--- a/libjava/classpath/gnu/xml/transform/ProcessingInstructionNode.java
+++ b/libjava/classpath/gnu/xml/transform/ProcessingInstructionNode.java
@@ -1,5 +1,5 @@
/* ProcessingInstructionNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -66,19 +66,15 @@ final class ProcessingInstructionNode
{
TemplateNode ret = new ProcessingInstructionNode(name);
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
void doApply(Stylesheet stylesheet, QName mode,
- Node context, int pos, int len,
- Node parent, Node nextSibling)
+ Node context, int pos, int len,
+ Node parent, Node nextSibling)
throws TransformerException
{
String data = null;
@@ -98,24 +94,18 @@ final class ProcessingInstructionNode
ProcessingInstruction pi = doc.createProcessingInstruction(name, data);
// Insert into result tree
if (nextSibling != null)
- {
- parent.insertBefore(pi, nextSibling);
- }
+ parent.insertBefore(pi, nextSibling);
else
- {
- parent.appendChild(pi);
- }
+ parent.appendChild(pi);
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("processing-instruction");
buf.append('[');
buf.append("name=");
buf.append(name);
diff --git a/libjava/classpath/gnu/xml/transform/Stylesheet.java b/libjava/classpath/gnu/xml/transform/Stylesheet.java
index 51accaa3b9a..73b22969114 100644
--- a/libjava/classpath/gnu/xml/transform/Stylesheet.java
+++ b/libjava/classpath/gnu/xml/transform/Stylesheet.java
@@ -408,7 +408,7 @@ class Stylesheet
{
if (debug)
System.err.println("getTemplate: mode="+mode+" context="+context);
- Set candidates = new TreeSet();
+ Template selected = null;
for (Iterator j = templates.iterator(); j.hasNext(); )
{
Template t = (Template) j.next();
@@ -426,10 +426,21 @@ class Stylesheet
}
//System.err.println("\t"+context+" "+t+"="+isMatch);
if (isMatch)
- candidates.add(t);
+ {
+ // Conflict resolution
+ // @see http://www.w3.org/TR/xslt#conflict
+ if (selected == null)
+ selected = t;
+ else
+ {
+ if (t.precedence < selected.precedence ||
+ t.priority < selected.priority)
+ continue;
+ selected = t;
+ }
+ }
}
- //System.err.println("\tcandidates="+candidates);
- if (candidates.isEmpty())
+ if (selected == null)
{
// Apply built-in template
// Current template is unchanged
@@ -451,32 +462,39 @@ class Stylesheet
return null;
}
}
- else
- {
- Template t = (Template) candidates.iterator().next();
- // Set current template
- currentTemplate = t;
- if (debug)
- System.err.println("\ttemplate="+t+" context="+context);
- return t.node;
- }
+ // Set current template
+ currentTemplate = selected;
+ if (debug)
+ System.err.println("\ttemplate="+currentTemplate+" context="+context);
+ return currentTemplate.node;
}
TemplateNode getTemplate(QName mode, QName name)
throws TransformerException
{
- Set candidates = new TreeSet();
+ Template selected = null;
for (Iterator j = templates.iterator(); j.hasNext(); )
{
Template t = (Template) j.next();
boolean isMatch = t.matches(name);
if (isMatch)
- candidates.add(t);
+ {
+ // Conflict resolution
+ // @see http://www.w3.org/TR/xslt#conflict
+ if (selected == null)
+ selected = t;
+ else
+ {
+ if (t.precedence < selected.precedence ||
+ t.priority < selected.priority)
+ continue;
+ selected = t;
+ }
+ }
}
- if (candidates.isEmpty())
+ if (selected == null)
return null;
- Template t = (Template) candidates.iterator().next();
- return t.node;
+ return selected.node;
}
/**
@@ -504,11 +522,9 @@ class Stylesheet
String p = getAttribute(attrs, "priority");
String mm = getAttribute(attrs, "mode");
QName mode = (mm == null) ? null : getQName(mm);
- double priority = (p == null) ? Template.DEFAULT_PRIORITY :
- Double.parseDouble(p);
Node children = node.getFirstChild();
return new Template(this, name, match, parse(children),
- precedence, priority, mode);
+ precedence, p, mode);
}
/**
@@ -799,7 +815,7 @@ class Stylesheet
templates.add(new Template(this, null, new Root(),
parse(rootClone),
precedence,
- Template.DEFAULT_PRIORITY,
+ null,
null));
}
else
diff --git a/libjava/classpath/gnu/xml/transform/Template.java b/libjava/classpath/gnu/xml/transform/Template.java
index e3c172fb559..1414dac9eb3 100644
--- a/libjava/classpath/gnu/xml/transform/Template.java
+++ b/libjava/classpath/gnu/xml/transform/Template.java
@@ -1,5 +1,5 @@
/* Template.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -66,51 +66,77 @@ class Template
final double priority;
final int precedence;
final QName mode;
+ final boolean isAnyNode; // is the match simply "node()"?
Template(Stylesheet stylesheet,
QName name, Pattern match, TemplateNode node,
- int precedence, double priority, QName mode)
+ int precedence, String priorityAttr, QName mode)
{
this.stylesheet = stylesheet;
this.name = name;
this.match = match;
this.node = node;
- // adjust priority if necessary
- // see XSLT section 5.5
- Test test = getNodeTest(match);
- if (test != null)
+ this.precedence = precedence;
+ this.mode = mode;
+
+ double p = DEFAULT_PRIORITY;
+ boolean a = false;
+ if (priorityAttr != null)
+ p = Double.parseDouble(priorityAttr);
+ else
{
- if (test instanceof NameTest)
+ // adjust priority if necessary
+ // see XSLT section 5.5
+ if (match instanceof Selector)
{
- NameTest nameTest = (NameTest) test;
- if (nameTest.matchesAny() ||
- nameTest.matchesAnyLocalName())
- {
- priority = -0.25d;
- }
- else
+ Selector selector = (Selector) match;
+ Test[] tests = selector.getTests();
+ if (tests.length > 0)
{
- priority = 0.0d;
- }
- }
- else
- {
- NodeTypeTest nodeTypeTest = (NodeTypeTest) test;
- if (nodeTypeTest.getNodeType() ==
- Node.PROCESSING_INSTRUCTION_NODE &&
- nodeTypeTest.getData() != null)
- {
- priority = 0.0d;
- }
- else
- {
- priority = -0.5d;
+ Test test = tests[0];
+ if (test instanceof NameTest)
+ {
+ NameTest nameTest = (NameTest) test;
+ if (nameTest.matchesAny())
+ p = -0.25d;
+ else if (nameTest.matchesAnyLocalName())
+ p = -0.20d;
+ else
+ p = 0.0d;
+ }
+ else
+ {
+ NodeTypeTest nodeTypeTest = (NodeTypeTest) test;
+ if (nodeTypeTest.getNodeType() ==
+ Node.PROCESSING_INSTRUCTION_NODE &&
+ nodeTypeTest.getData() != null)
+ p = 0.0d;
+ else
+ p = -0.5d;
+ a = (nodeTypeTest.getNodeType() == 0);
+ }
+ // Add a small difference for predicates
+ if (tests.length > 1)
+ p += ((double) tests.length - 1) * 0.001;
}
}
}
+ this.priority = p;
+ this.isAnyNode = a;
+ }
+
+ private Template(Stylesheet stylesheet,
+ QName name, Pattern match, TemplateNode node,
+ int precedence, double priority, QName mode, boolean isAnyNode)
+ {
+ this.stylesheet = stylesheet;
+ this.name = name;
+ this.match = match;
+ this.node = node;
this.precedence = precedence;
this.priority = priority;
this.mode = mode;
+ this.isAnyNode = isAnyNode;
}
Template clone(Stylesheet stylesheet)
@@ -124,7 +150,8 @@ class Template
(node == null) ? null : node.clone(stylesheet),
precedence,
priority,
- mode);
+ mode,
+ isAnyNode);
}
public int compareTo(Object other)
@@ -134,29 +161,16 @@ class Template
Template t = (Template) other;
int d = t.precedence - precedence;
if (d != 0)
- {
- return d;
- }
+ return d;
double d2 = t.priority - priority;
if (d2 != 0.0d)
- {
- return (int) Math.round(d2 * 1000.0d);
- }
+ return (int) Math.round(d2 * 1000.0d);
}
return 0;
}
Test getNodeTest(Expr expr)
{
- if (expr instanceof Selector)
- {
- Selector selector = (Selector) expr;
- Test[] tests = selector.getTests();
- if (tests.length > 0)
- {
- return tests[0];
- }
- }
return null;
}
@@ -164,13 +178,11 @@ class Template
{
if ((mode == null && this.mode != null) ||
(mode != null && !mode.equals(this.mode)))
- {
- return false;
- }
+ return false;
if (match == null)
- {
- return false;
- }
+ return false;
+ if (isAnyNode && node.getNodeType() == Node.DOCUMENT_NODE)
+ return false; // don't match document node
return match.matches(node);
}
@@ -186,9 +198,7 @@ class Template
ctx = ctx.parent)
{
if (ctx == stylesheet)
- {
- return true;
- }
+ return true;
}
return false;
}
@@ -206,13 +216,12 @@ class Template
Node parent, Node nextSibling)
throws TransformerException
{
- System.err.println("...applying " + toString() + " to " + context);
+ if (stylesheet.debug)
+ System.err.println("...applying " + toString() + " to " + context);
if (node != null)
- {
- node.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ node.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public String toString()
@@ -244,9 +253,7 @@ class Template
{
out.println(toString());
if (node != null)
- {
- node.list(1, out, true);
- }
+ node.list(1, out, true);
}
}
diff --git a/libjava/classpath/gnu/xml/transform/TemplateNode.java b/libjava/classpath/gnu/xml/transform/TemplateNode.java
index 36b25cf5222..6ff727c073c 100644
--- a/libjava/classpath/gnu/xml/transform/TemplateNode.java
+++ b/libjava/classpath/gnu/xml/transform/TemplateNode.java
@@ -64,9 +64,7 @@ abstract class TemplateNode
throws TransformerException
{
if (stylesheet.terminated)
- {
- return;
- }
+ return;
if (Thread.currentThread().isInterrupted())
{
// Try to head off any infinite loops at the pass
@@ -91,13 +89,9 @@ abstract class TemplateNode
public boolean references(QName var)
{
if (children != null && children.references(var))
- {
- return true;
- }
+ return true;
if (next != null && next.references(var))
- {
- return true;
- }
+ return true;
return false;
}
@@ -107,18 +101,30 @@ abstract class TemplateNode
void list(int depth, PrintStream out, boolean listNext)
{
for (int i = 0; i < depth; i++)
- {
- out.print(" ");
- }
+ out.print(" ");
out.println(toString());
if (children != null)
- {
- children.list(depth + 1, out, true);
- }
+ children.list(depth + 1, out, true);
if (listNext && next != null)
+ next.list(depth, out, listNext);
+ }
+
+ /**
+ * Indicates whether the template for which this template node is the
+ * first node specifies the given parameter.
+ */
+ boolean hasParam(QName name)
+ {
+ for (TemplateNode ctx = this; ctx != null; ctx = ctx.next)
{
- next.list(depth, out, listNext);
+ if (ctx instanceof ParameterNode)
+ {
+ ParameterNode param = (ParameterNode) ctx;
+ if (param.type == Bindings.PARAM && param.name.equals(name))
+ return true;
+ }
}
+ return false;
}
}
diff --git a/libjava/classpath/gnu/xml/transform/TextNode.java b/libjava/classpath/gnu/xml/transform/TextNode.java
index 1b581e5acbc..39423b270eb 100644
--- a/libjava/classpath/gnu/xml/transform/TextNode.java
+++ b/libjava/classpath/gnu/xml/transform/TextNode.java
@@ -1,5 +1,5 @@
/* TextNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -65,19 +65,15 @@ final class TextNode
{
TemplateNode ret = new TextNode(disableOutputEscaping);
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
void doApply(Stylesheet stylesheet, QName mode,
- Node context, int pos, int len,
- Node parent, Node nextSibling)
+ Node context, int pos, int len,
+ Node parent, Node nextSibling)
throws TransformerException
{
String value = "";
@@ -96,24 +92,28 @@ final class TextNode
}
Text text = doc.createTextNode(value);
if (disableOutputEscaping)
- {
- text.setUserData("disable-output-escaping", "yes", stylesheet);
- }
+ text.setUserData("disable-output-escaping", "yes", stylesheet);
// Insert into result tree
if (nextSibling != null)
- {
- parent.insertBefore(text, nextSibling);
- }
+ parent.insertBefore(text, nextSibling);
else
- {
- parent.appendChild(text);
- }
+ parent.appendChild(text);
if (next != null)
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer("text");
+ if (disableOutputEscaping)
{
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
+ buf.append('[');
+ buf.append("disable-output-escaping");
+ buf.append(']');
}
+ return buf.toString();
}
}
diff --git a/libjava/classpath/gnu/xml/transform/TransformerImpl.java b/libjava/classpath/gnu/xml/transform/TransformerImpl.java
index b7ff668843b..2c57e970be2 100644
--- a/libjava/classpath/gnu/xml/transform/TransformerImpl.java
+++ b/libjava/classpath/gnu/xml/transform/TransformerImpl.java
@@ -162,7 +162,7 @@ class TransformerImpl
}
// Make a copy of the source node, and strip it
context = context.cloneNode(true);
- strip(context);
+ strip(stylesheet, context);
// XSLT transformation
try
{
@@ -321,7 +321,7 @@ class TransformerImpl
if (indent)
{
parent.normalize();
- strip(parent);
+ strip(stylesheet, parent);
Document resultDoc = (parent instanceof Document) ?
(Document) parent :
parent.getOwnerDocument();
@@ -393,7 +393,7 @@ class TransformerImpl
/**
* Strip whitespace from the source tree.
*/
- boolean strip(Node node)
+ static boolean strip(Stylesheet stylesheet, Node node)
throws TransformerConfigurationException
{
short nt = node.getNodeType();
@@ -444,7 +444,7 @@ class TransformerImpl
Node child = node.getFirstChild();
while (child != null)
{
- boolean remove = strip(child);
+ boolean remove = strip(stylesheet, child);
Node next = child.getNextSibling();
if (remove)
node.removeChild(child);
@@ -691,7 +691,7 @@ class TransformerImpl
for (Iterator i = children.iterator(); i.hasNext(); )
{
ctx = (Node) i.next();
- reindent(doc, ctx, offset + 1);
+ reindent(doc, ctx, offset);
}
}
else
@@ -709,9 +709,9 @@ class TransformerImpl
}
buf = new StringBuffer();
buf.append('\n');
- ws = buf.toString();
for (int i = 0; i < offset; i++)
buf.append(INDENT_WHITESPACE);
+ ws = buf.toString();
node.appendChild(doc.createTextNode(ws));
}
}
diff --git a/libjava/classpath/gnu/xml/transform/ValueOfNode.java b/libjava/classpath/gnu/xml/transform/ValueOfNode.java
index 24c229ea3b3..68f31e05ae3 100644
--- a/libjava/classpath/gnu/xml/transform/ValueOfNode.java
+++ b/libjava/classpath/gnu/xml/transform/ValueOfNode.java
@@ -126,7 +126,7 @@ final class ValueOfNode
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("value-of");
buf.append('[');
buf.append("select=");
buf.append(select);
diff --git a/libjava/classpath/gnu/xml/transform/WhenNode.java b/libjava/classpath/gnu/xml/transform/WhenNode.java
index 231f2693b5b..fe3f403ab0c 100644
--- a/libjava/classpath/gnu/xml/transform/WhenNode.java
+++ b/libjava/classpath/gnu/xml/transform/WhenNode.java
@@ -1,5 +1,5 @@
/* WhenNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -62,19 +62,15 @@ final class WhenNode
{
TemplateNode ret = new WhenNode(test.clone(stylesheet));
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
void doApply(Stylesheet stylesheet, QName mode,
- Node context, int pos, int len,
- Node parent, Node nextSibling)
+ Node context, int pos, int len,
+ Node parent, Node nextSibling)
throws TransformerException
{
Object ret = test.evaluate(context, pos, len);
@@ -84,35 +80,29 @@ final class WhenNode
if (success)
{
if (children != null)
- {
- children.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ children.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
else
{
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
}
public boolean references(QName var)
{
if (test != null && test.references(var))
- {
- return true;
- }
+ return true;
return super.references(var);
}
public String toString()
{
- StringBuffer buf = new StringBuffer(getClass().getName());
+ StringBuffer buf = new StringBuffer("when");
buf.append('[');
buf.append("test=");
buf.append(test);
diff --git a/libjava/classpath/gnu/xml/util/XHTMLWriter.java b/libjava/classpath/gnu/xml/util/XHTMLWriter.java
index 272c66cd34c..02a0afca841 100644
--- a/libjava/classpath/gnu/xml/util/XHTMLWriter.java
+++ b/libjava/classpath/gnu/xml/util/XHTMLWriter.java
@@ -55,6 +55,8 @@ import java.io.Writer;
* data loss.
*
* @author David Brownell
+ *
+ * @deprecated Please use the javax.xml.stream APIs instead
*/
public class XHTMLWriter extends XMLWriter
{
diff --git a/libjava/classpath/gnu/xml/util/XMLWriter.java b/libjava/classpath/gnu/xml/util/XMLWriter.java
index fd36b715325..24b38923fa2 100644
--- a/libjava/classpath/gnu/xml/util/XMLWriter.java
+++ b/libjava/classpath/gnu/xml/util/XMLWriter.java
@@ -102,6 +102,8 @@ import org.xml.sax.helpers.*;
* @see gnu.xml.pipeline.TextConsumer
*
* @author David Brownell
+ *
+ * @deprecated Please use the javax.xml.stream APIs instead
*/
public class XMLWriter
implements ContentHandler, LexicalHandler, DTDHandler, DeclHandler
diff --git a/libjava/classpath/gnu/java/security/provider/MD5withRSA.java b/libjava/classpath/gnu/xml/validation/datatype/Annotation.java
index 721d897ed24..cba6954b624 100644
--- a/libjava/classpath/gnu/java/security/provider/MD5withRSA.java
+++ b/libjava/classpath/gnu/xml/validation/datatype/Annotation.java
@@ -1,5 +1,5 @@
-/* MD5withRSA.java -- MD5 with RSA encryption signatures.
- Copyright (C) 2004 Free Software Foundation, Inc.
+/* Annotation.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,20 +35,27 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
+package gnu.xml.validation.datatype;
-package gnu.java.security.provider;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-public class MD5withRSA extends RSA
+/**
+ * A schema component annotation.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class Annotation
{
- // Constructor.
- // -------------------------------------------------------------------------
+ public final String documentation;
+
+ public Annotation(String documentation)
+ {
+ this.documentation = documentation;
+ }
- public MD5withRSA() throws NoSuchAlgorithmException
+ public String toString()
{
- super(MessageDigest.getInstance("MD5"), DIGEST_ALGORITHM.getChild(5));
+ return documentation;
}
+
}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/AnySimpleType.java b/libjava/classpath/gnu/xml/validation/datatype/AnySimpleType.java
new file mode 100644
index 00000000000..63441c70a1d
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/AnySimpleType.java
@@ -0,0 +1,59 @@
+/* AnySimpleType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Set;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+
+final class AnySimpleType
+ extends SimpleType
+{
+
+ AnySimpleType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "anySimpleType"),
+ ANY, /* variety */
+ (Set) null, /* facets */
+ 0, /* fundametalFacets */
+ (SimpleType) Type.ANY_TYPE, /* baseType */
+ null);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/AnyType.java b/libjava/classpath/gnu/xml/validation/datatype/AnyType.java
new file mode 100644
index 00000000000..f26a0756d8b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/AnyType.java
@@ -0,0 +1,58 @@
+/* AnyType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+
+final class AnyType
+ extends SimpleType
+{
+
+ AnyType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "anyType"),
+ ANY, /* variety */
+ null, /* facets */
+ 0, /* fundamentalFacets */
+ null, /* baseType */
+ null);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/AnyURIType.java b/libjava/classpath/gnu/xml/validation/datatype/AnyURIType.java
new file mode 100644
index 00000000000..56c0a0658ea
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/AnyURIType.java
@@ -0,0 +1,94 @@
+/* AnyURIType.java --
+ 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.xml.validation.datatype;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema anyURI type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class AnyURIType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ AnyURIType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "anyURI"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ try
+ {
+ new URI(value);
+ }
+ catch (URISyntaxException e)
+ {
+ DatatypeException e2 = new DatatypeException(e.getIndex(),
+ e.getReason());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/AtomicSimpleType.java b/libjava/classpath/gnu/xml/validation/datatype/AtomicSimpleType.java
new file mode 100644
index 00000000000..d685e5cf00e
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/AtomicSimpleType.java
@@ -0,0 +1,78 @@
+/* AtomicSimpleType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Set;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * An XML Schema atomic simple type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class AtomicSimpleType
+ extends SimpleType
+{
+
+ public AtomicSimpleType(QName name,
+ Set facets,
+ int fundamentalFacets,
+ SimpleType baseType,
+ Annotation annotation)
+ {
+ super(name, ATOMIC, facets, fundamentalFacets, baseType, annotation);
+ }
+
+ // Only for use by built-in types
+ AtomicSimpleType(QName name, SimpleType baseType)
+ {
+ super(name, ATOMIC, null, 0, baseType, null);
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ if (baseType != null)
+ baseType.checkValid(value, context);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/Base64BinaryType.java b/libjava/classpath/gnu/xml/validation/datatype/Base64BinaryType.java
new file mode 100644
index 00000000000..5a72a280d7b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/Base64BinaryType.java
@@ -0,0 +1,131 @@
+/* Base64BinaryType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Collections;
+import java.util.Set;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema base64Binary type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class Base64BinaryType
+ extends AtomicSimpleType
+{
+
+ static final String B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+ "abcdefghijklmnopqrstuvwxyz0123456789+/";
+ static final String B16 = "AEIMQUYcgkosw048";
+ static final String B04 = "AQgw";
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ Base64BinaryType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "base64Binary"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ // TODO value = collapseWhitespace(value);
+ int len = value.length();
+ try
+ {
+ for (int i = len - 1; i >= 0; )
+ {
+ char c4 = value.charAt(i--);
+ if (c4 == ' ')
+ c4 = value.charAt(i--);
+ char c3 = value.charAt(i--);
+ if (c3 == ' ')
+ c3 = value.charAt(i--);
+ char c2 = value.charAt(i--);
+ if (c2 == ' ')
+ c2 = value.charAt(i--);
+ char c1 = value.charAt(i--);
+ if (c1 == ' ')
+ c1 = value.charAt(i--);
+
+ if (c4 == '=')
+ {
+ if (c3 == '=')
+ {
+ if (B04.indexOf(c2) != -1 &&
+ B64.indexOf(c1) != -1)
+ continue;
+ }
+ else if (B16.indexOf(c3) != -1)
+ {
+ if (B64.indexOf(c2) != -1 &&
+ B64.indexOf(c1) != -1)
+ continue;
+ }
+ }
+ else if (B64.indexOf(c4) != -1)
+ continue;
+ throw new DatatypeException(i, "illegal BASE64");
+ }
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ throw new DatatypeException("illegal BASE64");
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/BooleanType.java b/libjava/classpath/gnu/xml/validation/datatype/BooleanType.java
new file mode 100644
index 00000000000..5a2d9ecfa2d
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/BooleanType.java
@@ -0,0 +1,91 @@
+/* BooleanType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema boolean type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class BooleanType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.WHITESPACE
+ };
+
+ static final Set VALUE_SPACE =
+ new TreeSet(Arrays.asList(new String[] {"true", "false", "1", "0"}));
+
+ BooleanType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "boolean"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ if (!VALUE_SPACE.contains(value))
+ throw new DatatypeException("invalid boolean value");
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ return ("1".equals(literal) || "true".equals(literal)) ? Boolean.TRUE :
+ Boolean.FALSE;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/ByteType.java b/libjava/classpath/gnu/xml/validation/datatype/ByteType.java
new file mode 100644
index 00000000000..539dba29a99
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/ByteType.java
@@ -0,0 +1,133 @@
+/* ByteType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema byte type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class ByteType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final String MAX_VALUE = "127";
+ static final String MIN_VALUE = "128";
+ static final int LENGTH = MAX_VALUE.length();
+
+ ByteType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "byte"),
+ TypeLibrary.SHORT);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValue(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid byte value");
+ int i = 0, off = 0;
+ boolean compare = false;
+ String compareTo = MAX_VALUE;
+ char c = value.charAt(0);
+ if (c == '+')
+ i++;
+ else if (c == '-')
+ {
+ compareTo = MIN_VALUE;
+ i++;
+ }
+ if (len - i > LENGTH)
+ throw new DatatypeException(0, "invalid byte value");
+ else if (len - i == LENGTH)
+ compare = true;
+ for (; i < len; i++)
+ {
+ c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ {
+ if (compare)
+ {
+ char d = compareTo.charAt(off);
+ if (Character.digit(c, 10) > Character.digit(d, 10))
+ throw new DatatypeException(i, "invalid byte value");
+ }
+ off++;
+ continue;
+ }
+ throw new DatatypeException(i, "invalid byte value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Byte(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/DateTimeType.java b/libjava/classpath/gnu/xml/validation/datatype/DateTimeType.java
new file mode 100644
index 00000000000..749ba8106c1
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/DateTimeType.java
@@ -0,0 +1,335 @@
+/* DateTimeType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema dateTime type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class DateTimeType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ DateTimeType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "dateTime"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValue(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && i == 0)
+ {
+ start++;
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 0: // year
+ if (c == '-')
+ {
+ String year = value.substring(start, i);
+ if ("0000".equals(year) || year.length() < 4)
+ throw new DatatypeException(i, "invalid dateTime value");
+ state = 1;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 1: // month
+ if (c == '-')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid dateTime value");
+ state = 2;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 2: // day
+ if (c == 'T')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid dateTime value");
+ state = 3;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 3: // hour
+ if (c == ':')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid dateTime value");
+ state = 4;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 4: // minute
+ if (c == ':')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid dateTime value");
+ state = 5;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 5: // second
+ if (c == '.')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid dateTime value");
+ state = 6;
+ start = i + 1;
+ continue;
+ }
+ else if (c == ' ')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid dateTime value");
+ state = 7;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 6: // second fraction
+ if (c == ' ')
+ {
+ state = 7;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 7: // timezone 1
+ if (start == i)
+ {
+ if (c == '+' || c == '-')
+ continue;
+ else if (c == 'Z')
+ {
+ state = 9;
+ start = i + 1;
+ continue;
+ }
+ }
+ if (c == ':')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid dateTime value");
+ state = 8;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ throw new DatatypeException(i, "invalid dateTime value");
+ }
+ switch (state)
+ {
+ case 5: // second
+ if (len - start != 2)
+ throw new DatatypeException(len, "invalid dateTime value");
+ break;
+ case 6: // second fraction
+ break;
+ case 8: // timezone 2
+ if (len - start != 2)
+ throw new DatatypeException(len, "invalid dateTime value");
+ break;
+ case 9: // post Z
+ break;
+ default:
+ throw new DatatypeException(len, "invalid dateTime value");
+ }
+ }
+
+ public Object createValue(String value, ValidationContext context) {
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ Calendar cal = new GregorianCalendar();
+ try
+ {
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && i == 0)
+ {
+ start++;
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 0: // year
+ if (c == '-')
+ {
+ cal.set(Calendar.YEAR,
+ Integer.parseInt(value.substring(0, i)));
+ state = 1;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 1: // month
+ if (c == '-')
+ {
+ cal.set(Calendar.MONTH,
+ Integer.parseInt(value.substring(start, i)));
+ state = 2;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 2: // day
+ if (c == 'T')
+ {
+ cal.set(Calendar.DATE,
+ Integer.parseInt(value.substring(start, i)));
+ state = 3;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 3: // hour
+ if (c == ':')
+ {
+ cal.set(Calendar.HOUR,
+ Integer.parseInt(value.substring(start, i)));
+ state = 4;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 4: // minute
+ if (c == ':')
+ {
+ cal.set(Calendar.MINUTE,
+ Integer.parseInt(value.substring(start, i)));
+ state = 5;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 5: // second
+ if (c == ' ')
+ {
+ float second = Float.parseFloat(value.substring(start, i));
+ // TODO adjust non-integer values
+ cal.set(Calendar.SECOND, (int) second);
+ state = 7;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ }
+ // end of input
+ if (len - start > 0 && state == 7)
+ {
+ // Timezone
+ String timezone = value.substring(len - start);
+ int i = timezone.indexOf(':');
+ if (i == -1)
+ {
+ if ("Z".equals(timezone))
+ timezone = "UTC";
+ TimeZone tz = TimeZone.getTimeZone(timezone);
+ if (tz == null)
+ return null;
+ cal.set(Calendar.ZONE_OFFSET, tz.getRawOffset());
+ }
+ else
+ {
+ String tzh = timezone.substring(0, i);
+ String tzm = timezone.substring(i + 1);
+ int offset = Integer.parseInt(tzh) * 360000;
+ if (offset < 0)
+ offset -= Integer.parseInt(tzm) * 60000;
+ else
+ offset += Integer.parseInt(tzm) * 60000;
+ cal.set(Calendar.ZONE_OFFSET, offset);
+ }
+ }
+ return cal.getTime();
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/DateType.java b/libjava/classpath/gnu/xml/validation/datatype/DateType.java
new file mode 100644
index 00000000000..6a4e1d771a7
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/DateType.java
@@ -0,0 +1,222 @@
+/* DateType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema date type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class DateType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ DateType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "date"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && i == 0)
+ {
+ start++;
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 0: // year
+ if (c == '-')
+ {
+ String year = value.substring(start, i);
+ if ("0000".equals(year) || year.length() < 4)
+ throw new DatatypeException(i, "invalid date value");
+ state = 1;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 1: // month
+ if (c == '-')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid date value");
+ state = 2;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ throw new DatatypeException(i, "invalid date value");
+ }
+ switch (state)
+ {
+ case 2: // day
+ if (len - start != 2)
+ throw new DatatypeException("invalid date value");
+ break;
+ default:
+ throw new DatatypeException("invalid date value");
+ }
+ }
+
+ public Object createValue(String value, ValidationContext context) {
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ Calendar cal = new GregorianCalendar();
+ cal.set(Calendar.HOUR, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ try
+ {
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && i == 0)
+ {
+ start++;
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 0: // year
+ if (c == '-')
+ {
+ cal.set(Calendar.YEAR,
+ Integer.parseInt(value.substring(0, i)));
+ state = 1;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 1: // month
+ if (c == '-')
+ {
+ cal.set(Calendar.MONTH,
+ Integer.parseInt(value.substring(start, i)));
+ state = 2;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 2: // day
+ if (c == 'T')
+ {
+ cal.set(Calendar.DATE,
+ Integer.parseInt(value.substring(start, i)));
+ state = 7;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ }
+ // end of input
+ if (len - start > 0 && state == 7)
+ {
+ // Timezone
+ String timezone = value.substring(len - start);
+ int i = timezone.indexOf(':');
+ if (i == -1)
+ {
+ if ("Z".equals(timezone))
+ timezone = "UTC";
+ TimeZone tz = TimeZone.getTimeZone(timezone);
+ if (tz == null)
+ return null;
+ cal.set(Calendar.ZONE_OFFSET, tz.getRawOffset());
+ }
+ else
+ {
+ String tzh = timezone.substring(0, i);
+ String tzm = timezone.substring(i + 1);
+ int offset = Integer.parseInt(tzh) * 360000;
+ if (offset < 0)
+ offset -= Integer.parseInt(tzm) * 60000;
+ else
+ offset += Integer.parseInt(tzm) * 60000;
+ cal.set(Calendar.ZONE_OFFSET, offset);
+ }
+ }
+ return cal.getTime();
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/DecimalType.java b/libjava/classpath/gnu/xml/validation/datatype/DecimalType.java
new file mode 100644
index 00000000000..08fe3304c5f
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/DecimalType.java
@@ -0,0 +1,121 @@
+/* DecimalType.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.Set;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema decimal type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class DecimalType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ DecimalType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "decimal"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException("invalid decimal value");
+ boolean seenDot = false;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ else if (c == '.')
+ {
+ if (seenDot)
+ throw new DatatypeException(i, "invalid decimal value");
+ seenDot = true;
+ continue;
+ }
+ else if (c == '+' && i == 0)
+ continue;
+ else if (c == '-' && i == 0)
+ continue;
+ else
+ throw new DatatypeException(i, "invalid decimal value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new BigDecimal(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/DoubleType.java b/libjava/classpath/gnu/xml/validation/datatype/DoubleType.java
new file mode 100644
index 00000000000..e25d060fa5f
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/DoubleType.java
@@ -0,0 +1,112 @@
+/* DoubleType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema double type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class DoubleType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final Set SPECIAL =
+ new TreeSet(Arrays.asList(new String[] {"INF", "-INF", "NaN"}));
+
+ DoubleType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "double"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ if (SPECIAL.contains(value))
+ return;
+ try
+ {
+ Double.parseDouble(value);
+ }
+ catch (NumberFormatException e)
+ {
+ DatatypeException e2 = new DatatypeException("invalid double value");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Double(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/DurationType.java b/libjava/classpath/gnu/xml/validation/datatype/DurationType.java
new file mode 100644
index 00000000000..2cb92baae61
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/DurationType.java
@@ -0,0 +1,239 @@
+/* DurationType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema duration type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class DurationType
+ extends AtomicSimpleType
+{
+
+ static class Duration
+ implements Comparable
+ {
+ int years;
+ int months;
+ int days;
+ int minutes;
+ float seconds;
+
+ public int hashCode()
+ {
+ int hc = years;
+ hc = hc * 31 + months;
+ hc = hc * 31 + days;
+ hc = hc * 31 + minutes;
+ hc = hc * 31 + new Float(seconds).hashCode();
+ return hc;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other instanceof Duration)
+ {
+ Duration duration = (Duration) other;
+ return duration.years ==years &&
+ duration.months == months &&
+ duration.days == days &&
+ duration.minutes == minutes &&
+ duration.seconds == seconds;
+ }
+ return false;
+ }
+
+ public int compareTo(Object other)
+ {
+ if (other instanceof Duration)
+ {
+ Duration duration = (Duration) other;
+ if (duration.years != years)
+ return years - duration.years;
+ if (duration.months != months)
+ return months - duration.months;
+ if (duration.days != days)
+ return days - duration.days;
+ if (duration.minutes != minutes)
+ return minutes = duration.minutes;
+ if (duration.seconds == seconds)
+ return 0;
+ return (seconds < duration.seconds) ? -1 : 1;
+ }
+ return 0;
+ }
+
+ }
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ DurationType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "duration"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ char expect = 'P';
+ boolean seenT = false;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && expect == 'P')
+ continue;
+ if (c == expect)
+ {
+ if (c == 'P')
+ expect = 'Y';
+ else if (c == 'Y')
+ expect = 'M';
+ else if (c == 'M' && !seenT)
+ expect = 'D';
+ else if (c == 'D')
+ expect = 'T';
+ else if (c == 'T')
+ {
+ expect = 'H';
+ seenT = true;
+ }
+ else if (c == 'H')
+ expect = 'M';
+ else if (c == 'M' && seenT)
+ expect = 'S';
+ else if (c == 'S')
+ {
+ if (i + 1 != len)
+ throw new DatatypeException(i, "illegal duration value");
+ }
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39 && expect != 'P' && expect != 'T')
+ continue;
+ throw new DatatypeException(i, "illegal duration value");
+ }
+ }
+
+ public Object createValue(String value, ValidationContext context) {
+ boolean negative = false;
+ int days = 0, months = 0, years = 0;
+ int minutes = 0;
+ float seconds = 0.0f;
+ int len = value.length();
+ char expect = 'P';
+ boolean seenT = false;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && expect == 'P')
+ {
+ negative = true;
+ continue;
+ }
+ if (c == expect)
+ {
+ if (c == 'P')
+ expect = 'Y';
+ else if (c == 'Y')
+ {
+ expect = 'M';
+ years = Integer.parseInt(value.substring(start, i));
+ }
+ else if (c == 'M' && !seenT)
+ expect = 'D';
+ else if (c == 'D')
+ expect = 'T';
+ else if (c == 'T')
+ {
+ expect = 'H';
+ seenT = true;
+ }
+ else if (c == 'H')
+ expect = 'M';
+ else if (c == 'M' && seenT)
+ expect = 'S';
+ else if (c == 'S')
+ {
+ if (i + 1 != len)
+ return null;
+ }
+ start = i + 1;
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39 && expect != 'P' && expect != 'T')
+ continue;
+ return null;
+ }
+ if (negative)
+ {
+ days = days * -1;
+ minutes = minutes * -1;
+ seconds = seconds * -1.0f;
+ }
+ Duration duration = new Duration();
+ duration.days = days;
+ duration.minutes = minutes;
+ duration.seconds = seconds;
+ return duration;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/EntitiesType.java b/libjava/classpath/gnu/xml/validation/datatype/EntitiesType.java
new file mode 100644
index 00000000000..98554e1847a
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/EntitiesType.java
@@ -0,0 +1,107 @@
+/* EntitiesType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema ENTITIES type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class EntitiesType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ EntitiesType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "ENTITIES"),
+ TypeLibrary.ENTITY);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ StringBuffer buf = new StringBuffer();
+ int len = value.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == ' ')
+ {
+ String token = buf.toString();
+ if (token.length() > 0)
+ {
+ if (!context.isUnparsedEntity(token))
+ throw new DatatypeException(i, "invalid ENTITIES value");
+ }
+ buf.setLength(0);
+ }
+ else
+ buf.append(c);
+ }
+ String token = buf.toString();
+ if (token.length() == 0 || !context.isUnparsedEntity(token))
+ throw new DatatypeException("invalid ENTITIES value");
+ }
+
+ public boolean isContextDependent()
+ {
+ return true;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/EntityType.java b/libjava/classpath/gnu/xml/validation/datatype/EntityType.java
new file mode 100644
index 00000000000..f1443bcb983
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/EntityType.java
@@ -0,0 +1,88 @@
+/* EntityType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema ENTITY type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class EntityType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ EntityType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "ENTITY"),
+ TypeLibrary.NCNAME);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ if (value.length() == 0 || !context.isUnparsedEntity(value))
+ throw new DatatypeException("invalid ENTITY value");
+ }
+
+ public boolean isContextDependent()
+ {
+ return true;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/EnumerationFacet.java b/libjava/classpath/gnu/xml/validation/datatype/EnumerationFacet.java
new file mode 100644
index 00000000000..0ad3d3fa4d3
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/EnumerationFacet.java
@@ -0,0 +1,69 @@
+/* EnumerationFacet.java --
+ 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.xml.validation.datatype;
+
+/**
+ * The <code>enumeration</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class EnumerationFacet
+ extends Facet
+{
+
+ public final String value;
+
+ public EnumerationFacet(String value, Annotation annotation)
+ {
+ super(ENUMERATION, annotation);
+ this.value = value;
+ }
+
+ public int hashCode()
+ {
+ return value.hashCode();
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof EnumerationFacet &&
+ ((EnumerationFacet) other).value.equals(value));
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/Facet.java b/libjava/classpath/gnu/xml/validation/datatype/Facet.java
new file mode 100644
index 00000000000..490abf8eeb7
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/Facet.java
@@ -0,0 +1,78 @@
+/* Facet.java --
+ 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.xml.validation.datatype;
+
+/**
+ * An XML Schema constraining facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public abstract class Facet
+{
+
+ public static final int LENGTH = 1;
+ public static final int MIN_LENGTH = 2;
+ public static final int MAX_LENGTH = 3;
+ public static final int PATTERN = 4;
+ public static final int ENUMERATION = 5;
+ public static final int WHITESPACE = 6;
+ public static final int MAX_INCLUSIVE = 7;
+ public static final int MAX_EXCLUSIVE = 8;
+ public static final int MIN_EXCLUSIVE = 9;
+ public static final int MIN_INCLUSIVE = 10;
+ public static final int TOTAL_DIGITS = 11;
+ public static final int FRACTION_DIGITS = 12;
+
+ /**
+ * The type of this facet.
+ */
+ public final int type;
+
+ /**
+ * Optional annotation.
+ */
+ public Annotation annotation;
+
+ protected Facet(int type, Annotation annotation)
+ {
+ this.type = type;
+ this.annotation = annotation;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/FloatType.java b/libjava/classpath/gnu/xml/validation/datatype/FloatType.java
new file mode 100644
index 00000000000..a81a56c1a68
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/FloatType.java
@@ -0,0 +1,112 @@
+/* FloatType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema float type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class FloatType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final Set SPECIAL =
+ new TreeSet(Arrays.asList(new String[] {"INF", "-INF", "NaN"}));
+
+ FloatType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "float"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ if (SPECIAL.contains(value))
+ return;
+ try
+ {
+ Float.parseFloat(value);
+ }
+ catch (NumberFormatException e)
+ {
+ DatatypeException e2 = new DatatypeException("invalid float value");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Float(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/stream/StartEntityImpl.java b/libjava/classpath/gnu/xml/validation/datatype/FractionDigitsFacet.java
index 6e4ca257a2c..efd986200e5 100644
--- a/libjava/classpath/gnu/xml/stream/StartEntityImpl.java
+++ b/libjava/classpath/gnu/xml/validation/datatype/FractionDigitsFacet.java
@@ -1,5 +1,5 @@
-/* StartEntityImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+/* FractionDigitsFacet.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,45 +35,37 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.xml.stream;
-
-import java.io.IOException;
-import java.io.Writer;
-import javax.xml.stream.Location;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.StartEntity;
+package gnu.xml.validation.datatype;
/**
- * A start-entity event.
+ * The <code>fractionDigits</code> facet.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
-public class StartEntityImpl
- extends XMLEventImpl
- implements StartEntity
+public final class FractionDigitsFacet
+ extends Facet
{
+
+ public final int value;
- protected final String name;
+ public final boolean fixed;
- protected StartEntityImpl(Location location, String name)
+ public FractionDigitsFacet(int value, boolean fixed, Annotation annotation)
{
- super(location);
- this.name = name;
+ super(FRACTION_DIGITS, annotation);
+ this.value = value;
+ this.fixed = fixed;
}
-
- public int getEventType()
+
+ public int hashCode()
{
- return START_ENTITY;
+ return value;
}
- public String getName()
- {
- return name;
- }
-
- public void writeAsEncodedUnicode(Writer writer)
- throws XMLStreamException
+ public boolean equals(Object other)
{
+ return (other instanceof FractionDigitsFacet &&
+ ((FractionDigitsFacet) other).value == value);
}
}
diff --git a/libjava/classpath/gnu/xml/validation/datatype/GDayType.java b/libjava/classpath/gnu/xml/validation/datatype/GDayType.java
new file mode 100644
index 00000000000..009af35850b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/GDayType.java
@@ -0,0 +1,175 @@
+/* GDayType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema gDay type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class GDayType
+ extends AtomicSimpleType
+{
+
+ static class GDay
+ implements Comparable
+ {
+
+ int day;
+
+ public int hashCode()
+ {
+ return day;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other instanceof GDay)
+ return ((GDay) other).day == day;
+ return false;
+ }
+
+ public int compareTo(Object other)
+ {
+ if (other instanceof GDay)
+ {
+ GDay gd = (GDay) other;
+ if (gd.day == day)
+ return 0;
+ return (day < gd.day) ? -1 : 1;
+ }
+ return 0;
+ }
+
+ }
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ GDayType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "gDay"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 0: // year
+ if (c == '-')
+ {
+ switch (i)
+ {
+ case 0:
+ continue;
+ case 1:
+ state = 1;
+ start = i + 1;
+ continue;
+ default:
+ throw new DatatypeException(i, "invalid GDay value");
+ }
+ }
+ break;
+ case 1: // month
+ if (c == '-')
+ {
+ if (i - start != 0)
+ throw new DatatypeException(i, "invalid GDay value");
+ state = 2;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ throw new DatatypeException(i, "invalid GDay value");
+ }
+ switch (state)
+ {
+ case 2: // day
+ if (len - start != 2)
+ throw new DatatypeException("invalid GDay value");
+ break;
+ default:
+ throw new DatatypeException("invalid GDay value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ GDay ret = new GDay();
+ ret.day = Integer.parseInt(literal.substring(3));
+ return ret;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/GMonthDayType.java b/libjava/classpath/gnu/xml/validation/datatype/GMonthDayType.java
new file mode 100644
index 00000000000..a39a1cc4370
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/GMonthDayType.java
@@ -0,0 +1,184 @@
+/* GMonthDayType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema gMonthDay type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class GMonthDayType
+ extends AtomicSimpleType
+{
+
+ static class GMonthDay
+ implements Comparable
+ {
+
+ int month;
+ int day;
+
+ public int hashCode()
+ {
+ return month * 31 + day;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other instanceof GMonthDay)
+ {
+ GMonthDay gmd = (GMonthDay) other;
+ return gmd.month == month && gmd.day == day;
+ }
+ return false;
+ }
+
+ public int compareTo(Object other)
+ {
+ if (other instanceof GMonthDay)
+ {
+ GMonthDay gmd = (GMonthDay) other;
+ if (gmd.month == month)
+ {
+ if (gmd.day == day)
+ return 0;
+ return (day < gmd.day) ? -1 : 1;
+ }
+ return (month < gmd.month) ? -1 : 1;
+ }
+ return 0;
+ }
+
+ }
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ GMonthDayType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "gMonthDay"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 0: // year
+ if (c == '-')
+ {
+ switch (i)
+ {
+ case 0:
+ continue;
+ case 1:
+ state = 1;
+ start = i + 1;
+ continue;
+ default:
+ throw new DatatypeException(i, "illegal GMonthDay type");
+ }
+ }
+ break;
+ case 1: // month
+ if (c == '-')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "illegal GMonthDay type");
+ state = 2;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ throw new DatatypeException(i, "illegal GMonthDay type");
+ }
+ switch (state)
+ {
+ case 2: // day
+ if (len - start != 2)
+ throw new DatatypeException("illegal GMonthDay type");
+ break;
+ default:
+ throw new DatatypeException("illegal GMonthDay type");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ GMonthDay ret = new GMonthDay();
+ ret.month = Integer.parseInt(literal.substring(2, 5));
+ ret.day = Integer.parseInt(literal.substring(6));
+ return ret;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/GMonthType.java b/libjava/classpath/gnu/xml/validation/datatype/GMonthType.java
new file mode 100644
index 00000000000..5a08af2876a
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/GMonthType.java
@@ -0,0 +1,164 @@
+/* GMonthType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema gMonth type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class GMonthType
+ extends AtomicSimpleType
+{
+
+ static class GMonth
+ implements Comparable
+ {
+
+ int month;
+
+ public int hashCode()
+ {
+ return month;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other instanceof GMonth)
+ return ((GMonth) other).month == month;
+ return false;
+ }
+
+ public int compareTo(Object other)
+ {
+ if (other instanceof GMonth)
+ {
+ GMonth gm = (GMonth) other;
+ if (gm.month == month)
+ return 0;
+ return (month < gm.month) ? -1 : 1;
+ }
+ return 0;
+ }
+
+ }
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ GMonthType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "gMonth"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 0: // year
+ if (c == '-')
+ {
+ switch (i)
+ {
+ case 0:
+ continue;
+ case 1:
+ state = 1;
+ start = i + 1;
+ continue;
+ default:
+ throw new DatatypeException(i, "illegal GMonth value");
+ }
+ }
+ break;
+ }
+ throw new DatatypeException(i, "illegal GMonth value");
+ }
+ switch (state)
+ {
+ case 1: // month
+ if (len - start != 2)
+ throw new DatatypeException("illegal GMonth value");
+ break;
+ default:
+ throw new DatatypeException("illegal GMonth value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ GMonth ret = new GMonth();
+ ret.month = Integer.parseInt(literal.substring(2));
+ return ret;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/GYearMonthType.java b/libjava/classpath/gnu/xml/validation/datatype/GYearMonthType.java
new file mode 100644
index 00000000000..9ec38c0e7bc
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/GYearMonthType.java
@@ -0,0 +1,177 @@
+/* GYearMonthType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema gYearMonth type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class GYearMonthType
+ extends AtomicSimpleType
+{
+
+ static class GYearMonth
+ implements Comparable
+ {
+
+ int year;
+ int month;
+
+ public int hashCode()
+ {
+ return year * 31 + month;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other instanceof GYearMonth)
+ {
+ GYearMonth gmy = (GYearMonth) other;
+ return gmy.year == year && gmy.month == month;
+ }
+ return false;
+ }
+
+ public int compareTo(Object other)
+ {
+ if (other instanceof GYearMonth)
+ {
+ GYearMonth gmy = (GYearMonth) other;
+ if (gmy.year == year)
+ {
+ if (gmy.month == month)
+ return 0;
+ return (month < gmy.month) ? -1 : 1;
+ }
+ return (year < gmy.year) ? -1 : 1;
+ }
+ return 0;
+ }
+
+ }
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ GYearMonthType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "gYearMonth"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && i == 0)
+ {
+ start++;
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 0: // year
+ if (c == '-')
+ {
+ String year = value.substring(start, i);
+ if (year.length() < 4 || Integer.parseInt(year) == 0)
+ throw new DatatypeException(i, "illegal GYear value");
+ state = 1;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ throw new DatatypeException(i, "illegal GYear value");
+ }
+ switch (state)
+ {
+ case 1: // month
+ if (len - start != 2)
+ throw new DatatypeException("illegal GYear value");
+ break;
+ default:
+ throw new DatatypeException("illegal GYear value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ int offset = 5;
+ if (literal.charAt(0) == '-')
+ offset++;
+ GYearMonth ret = new GYearMonth();
+ ret.year = Integer.parseInt(literal.substring(0, offset));
+ ret.month = Integer.parseInt(literal.substring(offset + 1));
+ return ret;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/GYearType.java b/libjava/classpath/gnu/xml/validation/datatype/GYearType.java
new file mode 100644
index 00000000000..6dea89b76a5
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/GYearType.java
@@ -0,0 +1,152 @@
+/* GYearType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema gYear type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class GYearType
+ extends AtomicSimpleType
+{
+
+ static class GYear
+ implements Comparable
+ {
+
+ int year;
+
+ public int hashCode()
+ {
+ return year;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other instanceof GYear)
+ return ((GYear) other).year == year;
+ return false;
+ }
+
+ public int compareTo(Object other)
+ {
+ if (other instanceof GYear)
+ {
+ GYear gy = (GYear) other;
+ if (gy.year == year)
+ return 0;
+ return (year < gy.year) ? -1 : 1;
+ }
+ return 0;
+ }
+
+ }
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ GYearType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "gYear"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ int state = 0;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && i == 0)
+ {
+ start++;
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ throw new DatatypeException(i, "invalid GYear value");
+ }
+ switch (state)
+ {
+ case 0: // year
+ String year = value.substring(start, len);
+ if (year.length() < 4 || Integer.parseInt(year) == 0)
+ throw new DatatypeException("invalid GYear value");
+ break;
+ default:
+ throw new DatatypeException("invalid GYear value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ GYear ret = new GYear();
+ ret.year = Integer.parseInt(literal);
+ return ret;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/HexBinaryType.java b/libjava/classpath/gnu/xml/validation/datatype/HexBinaryType.java
new file mode 100644
index 00000000000..686e09d9801
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/HexBinaryType.java
@@ -0,0 +1,92 @@
+/* HexBinaryType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Collections;
+import java.util.Set;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema hexBinary type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class HexBinaryType
+ extends AtomicSimpleType
+{
+
+ static final String HEX = "0123456789ABCDEF";
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ HexBinaryType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "hexBinary"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (HEX.indexOf(c) == -1)
+ throw new DatatypeException(i, "invalid hexBinary value");
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/IDRefType.java b/libjava/classpath/gnu/xml/validation/datatype/IDRefType.java
new file mode 100644
index 00000000000..8ea9805b074
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/IDRefType.java
@@ -0,0 +1,87 @@
+/* IDRefType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema IDREF type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class IDRefType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ IDRefType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "IDREF"),
+ TypeLibrary.NCNAME);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ // TODO
+ }
+
+ public int getIdType()
+ {
+ return ID_TYPE_IDREF;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/IDRefsType.java b/libjava/classpath/gnu/xml/validation/datatype/IDRefsType.java
new file mode 100644
index 00000000000..57f7e56d7ce
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/IDRefsType.java
@@ -0,0 +1,87 @@
+/* IDRefsType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema IDREFS type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class IDRefsType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ IDRefsType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "IDREFS"),
+ TypeLibrary.IDREF);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ // TODO
+ }
+
+ public int getIdType()
+ {
+ return ID_TYPE_IDREFS;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/javax/crypto/GnuDHPrivateKey.java b/libjava/classpath/gnu/xml/validation/datatype/IDType.java
index f70cd7d2aec..c55601aaf8f 100644
--- a/libjava/classpath/gnu/javax/crypto/GnuDHPrivateKey.java
+++ b/libjava/classpath/gnu/xml/validation/datatype/IDType.java
@@ -1,5 +1,5 @@
-/* GnuDHPrivateKey.java -- a Diffie-Hellman private key.
- Copyright (C) 2005 Free Software Foundation, Inc.
+/* IDType.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,56 +35,53 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
+package gnu.xml.validation.datatype;
-package gnu.javax.crypto;
-
-import java.math.BigInteger;
-
-import javax.crypto.interfaces.DHKey;
-import javax.crypto.interfaces.DHPrivateKey;
-import javax.crypto.spec.DHParameterSpec;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
/**
- * A Diffie-Hellman private key.
+ * The XML Schema ID type.
*
- * @author Casey Marshall (csm@gnu.org)
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
-public class GnuDHPrivateKey implements DHPrivateKey
+final class IDType
+ extends AtomicSimpleType
{
- private final BigInteger x;
- private final DHParameterSpec params;
-
- public GnuDHPrivateKey (final BigInteger x, final DHParameterSpec params)
- {
- x.getClass ();
- params.getClass ();
- this.x = x;
- this.params = params;
- }
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
- public DHParameterSpec getParams()
+ IDType()
{
- return params;
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "ID"),
+ TypeLibrary.NCNAME);
}
- public String getAlgorithm()
+ public int[] getConstrainingFacets()
{
- return "DiffieHellman";
+ return CONSTRAINING_FACETS;
}
- public String getFormat ()
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
{
- return "NONE";
+ super.checkValid(value, context);
+ // TODO
}
- public byte[] getEncoded ()
+ public int getIdType()
{
- return null;
- }
-
- public BigInteger getX ()
- {
- return x;
+ return ID_TYPE_ID;
}
+
}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/IntType.java b/libjava/classpath/gnu/xml/validation/datatype/IntType.java
new file mode 100644
index 00000000000..6bf78660459
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/IntType.java
@@ -0,0 +1,133 @@
+/* IntType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema int type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class IntType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final String MAX_VALUE = "2147483647";
+ static final String MIN_VALUE = "2147483648";
+ static final int LENGTH = MAX_VALUE.length();
+
+ IntType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "int"),
+ TypeLibrary.LONG);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid int value");
+ int i = 0, off = 0;
+ boolean compare = false;
+ String compareTo = MAX_VALUE;
+ char c = value.charAt(0);
+ if (c == '+')
+ i++;
+ else if (c == '-')
+ {
+ compareTo = MIN_VALUE;
+ i++;
+ }
+ if (len - i > LENGTH)
+ throw new DatatypeException("invalid int value");
+ else if (len - i == LENGTH)
+ compare = true;
+ for (; i < len; i++)
+ {
+ c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ {
+ if (compare)
+ {
+ char d = compareTo.charAt(off);
+ if (Character.digit(c, 10) > Character.digit(d, 10))
+ throw new DatatypeException(i, "invalid int value");
+ }
+ off++;
+ continue;
+ }
+ throw new DatatypeException(i, "invalid int value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Integer(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/IntegerType.java b/libjava/classpath/gnu/xml/validation/datatype/IntegerType.java
new file mode 100644
index 00000000000..2098a7d8db8
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/IntegerType.java
@@ -0,0 +1,110 @@
+/* IntegerType.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigInteger;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema integer type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class IntegerType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ IntegerType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "integer"),
+ TypeLibrary.DECIMAL);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid integer value");
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ else if (c == '+' && i == 0)
+ continue;
+ else if (c == '-' && i == 0)
+ continue;
+ throw new DatatypeException(i, "invalid integer value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new BigInteger(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/LanguageType.java b/libjava/classpath/gnu/xml/validation/datatype/LanguageType.java
new file mode 100644
index 00000000000..3df903c48c6
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/LanguageType.java
@@ -0,0 +1,87 @@
+/* LanguageType.java --
+ 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.xml.validation.datatype;
+
+import java.util.regex.Pattern;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema language type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class LanguageType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ static final Pattern PATTERN =
+ Pattern.compile("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*");
+
+ LanguageType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "language"),
+ TypeLibrary.TOKEN);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ if (!PATTERN.matcher(value).matches())
+ throw new DatatypeException("invalid language value");
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/LengthFacet.java b/libjava/classpath/gnu/xml/validation/datatype/LengthFacet.java
new file mode 100644
index 00000000000..cab4496b12a
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/LengthFacet.java
@@ -0,0 +1,72 @@
+/* LengthFacet.java --
+ 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.xml.validation.datatype;
+
+/**
+ * The <code>length</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class LengthFacet
+ extends Facet
+{
+
+ public final int value;
+
+ public final boolean fixed;
+
+ public LengthFacet(int value, boolean fixed, Annotation annotation)
+ {
+ super(LENGTH, annotation);
+ this.value = value;
+ this.fixed = fixed;
+ }
+
+ public int hashCode()
+ {
+ return value;
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof LengthFacet &&
+ ((LengthFacet) other).value == value);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/ListSimpleType.java b/libjava/classpath/gnu/xml/validation/datatype/ListSimpleType.java
new file mode 100644
index 00000000000..1f0cb76fac6
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/ListSimpleType.java
@@ -0,0 +1,83 @@
+/* ListSimpleType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Set;
+import java.util.StringTokenizer;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * An XML Schema list simple type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class ListSimpleType
+ extends SimpleType
+{
+
+ /**
+ * The type of the items in this list (atomic or union).
+ */
+ public final SimpleType itemType;
+
+ public ListSimpleType(QName name, Set facets,
+ int fundamentalFacets, SimpleType baseType,
+ Annotation annotation, SimpleType itemType)
+ {
+ super(name, LIST, facets, fundamentalFacets, baseType, annotation);
+ this.itemType = itemType;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ StringTokenizer st = new StringTokenizer(value, " ");
+ if (!st.hasMoreTokens())
+ throw new DatatypeException("invalid list value");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ itemType.checkValid(token, context);
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/LongType.java b/libjava/classpath/gnu/xml/validation/datatype/LongType.java
new file mode 100644
index 00000000000..eaf69df38fa
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/LongType.java
@@ -0,0 +1,133 @@
+/* LongType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema long type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class LongType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final String MAX_VALUE = "9223372036854775807";
+ static final String MIN_VALUE = "9223372036854775808";
+ static final int LENGTH = MAX_VALUE.length();
+
+ LongType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "long"),
+ TypeLibrary.INTEGER);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid long value");
+ int i = 0, off = 0;
+ boolean compare = false;
+ String compareTo = MAX_VALUE;
+ char c = value.charAt(0);
+ if (c == '+')
+ i++;
+ else if (c == '-')
+ {
+ compareTo = MIN_VALUE;
+ i++;
+ }
+ if (len - i > LENGTH)
+ throw new DatatypeException(i, "invalid long value");
+ else if (len - i == LENGTH)
+ compare = true;
+ for (; i < len; i++)
+ {
+ c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ {
+ if (compare)
+ {
+ char d = compareTo.charAt(off);
+ if (Character.digit(c, 10) > Character.digit(d, 10))
+ throw new DatatypeException(i, "invalid long value");
+ }
+ off++;
+ continue;
+ }
+ throw new DatatypeException(i, "invalid long value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Long(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/MaxExclusiveFacet.java b/libjava/classpath/gnu/xml/validation/datatype/MaxExclusiveFacet.java
new file mode 100644
index 00000000000..7aac1f743b1
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/MaxExclusiveFacet.java
@@ -0,0 +1,111 @@
+/* MaxExclusiveFacet.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+/**
+ * The <code>maxExclusive</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class MaxExclusiveFacet
+ extends Facet
+{
+
+ public final Object value; // date or number
+
+ public final boolean fixed;
+
+ public MaxExclusiveFacet(Object value, boolean fixed, Annotation annotation)
+ {
+ super(MAX_EXCLUSIVE, annotation);
+ this.value = value;
+ this.fixed = fixed;
+ }
+
+ public int hashCode()
+ {
+ return value.hashCode();
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof MaxExclusiveFacet &&
+ ((MaxExclusiveFacet) other).value.equals(value));
+ }
+
+ boolean matches(Object test)
+ {
+ if (value instanceof Date)
+ {
+ Date dvalue = (Date) value;
+ if (!(test instanceof Date))
+ return false;
+ return ((Date) test).before(dvalue);
+ }
+ else if (value instanceof BigInteger)
+ {
+ BigInteger ivalue = (BigInteger) value;
+ if (!(test instanceof BigInteger))
+ return false;
+ return ((BigInteger) test).compareTo(ivalue) < 0;
+ }
+ else if (value instanceof BigDecimal)
+ {
+ BigDecimal dvalue = (BigDecimal) value;
+ if (!(test instanceof BigDecimal))
+ return false;
+ return ((BigDecimal) test).compareTo(dvalue) < 0;
+ }
+ else if (value instanceof Comparable)
+ {
+ if (!(test.getClass().equals(value.getClass())))
+ return false;
+ return ((Comparable) test).compareTo(value) < 0;
+ }
+ Number nvalue = (Number) value;
+ if (!(test instanceof Number))
+ return false;
+ return ((Number) test).doubleValue() < nvalue.doubleValue();
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/MaxInclusiveFacet.java b/libjava/classpath/gnu/xml/validation/datatype/MaxInclusiveFacet.java
new file mode 100644
index 00000000000..bb145ed4115
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/MaxInclusiveFacet.java
@@ -0,0 +1,112 @@
+/* MaxInclusiveFacet.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+/**
+ * The <code>maxInclusive</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class MaxInclusiveFacet
+ extends Facet
+{
+
+ public final Object value;
+
+ public final boolean fixed;
+
+ public MaxInclusiveFacet(Object value, boolean fixed, Annotation annotation)
+ {
+ super(MAX_INCLUSIVE, annotation);
+ this.value = value;
+ this.fixed = fixed;
+ }
+
+ public int hashCode()
+ {
+ return value.hashCode();
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof MaxInclusiveFacet &&
+ ((MaxInclusiveFacet) other).value.equals(value));
+ }
+
+ boolean matches(Object test)
+ {
+ if (value instanceof Date)
+ {
+ Date dvalue = (Date) value;
+ if (!(test instanceof Date))
+ return false;
+ Date dtest = (Date) test;
+ return dtest.equals(dvalue) || dtest.before(dvalue);
+ }
+ else if (value instanceof BigInteger)
+ {
+ BigInteger ivalue = (BigInteger) value;
+ if (!(test instanceof BigInteger))
+ return false;
+ return ((BigInteger) test).compareTo(ivalue) <= 0;
+ }
+ else if (value instanceof BigDecimal)
+ {
+ BigDecimal dvalue = (BigDecimal) value;
+ if (!(test instanceof BigDecimal))
+ return false;
+ return ((BigDecimal) test).compareTo(dvalue) <= 0;
+ }
+ else if (value instanceof Comparable)
+ {
+ if (!(test.getClass().equals(value.getClass())))
+ return false;
+ return ((Comparable) test).compareTo(value) <= 0;
+ }
+ Number nvalue = (Number) value;
+ if (!(test instanceof Number))
+ return false;
+ return ((Number) test).doubleValue() <= nvalue.doubleValue();
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/MaxLengthFacet.java b/libjava/classpath/gnu/xml/validation/datatype/MaxLengthFacet.java
new file mode 100644
index 00000000000..d0332631152
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/MaxLengthFacet.java
@@ -0,0 +1,72 @@
+/* MaxLengthFacet.java --
+ 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.xml.validation.datatype;
+
+/**
+ * The <code>maxLength</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class MaxLengthFacet
+ extends Facet
+{
+
+ public final int value;
+
+ public final boolean fixed;
+
+ public MaxLengthFacet(int value, boolean fixed, Annotation annotation)
+ {
+ super(MAX_LENGTH, annotation);
+ this.value = value;
+ this.fixed = fixed;
+ }
+
+ public int hashCode()
+ {
+ return value;
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof MaxLengthFacet &&
+ ((MaxLengthFacet) other).value == value);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/MinExclusiveFacet.java b/libjava/classpath/gnu/xml/validation/datatype/MinExclusiveFacet.java
new file mode 100644
index 00000000000..2289bb11c61
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/MinExclusiveFacet.java
@@ -0,0 +1,111 @@
+/* MinExclusiveFacet.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+/**
+ * The <code>minExclusive</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class MinExclusiveFacet
+ extends Facet
+{
+
+ public final Object value;
+
+ public final boolean fixed;
+
+ public MinExclusiveFacet(Object value, boolean fixed, Annotation annotation)
+ {
+ super(MIN_EXCLUSIVE, annotation);
+ this.value = value;
+ this.fixed = fixed;
+ }
+
+ public int hashCode()
+ {
+ return value.hashCode();
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof MinExclusiveFacet &&
+ ((MinExclusiveFacet) other).value.equals(value));
+ }
+
+ boolean matches(Object test)
+ {
+ if (value instanceof Date)
+ {
+ Date dvalue = (Date) value;
+ if (!(test instanceof Date))
+ return false;
+ return ((Date) test).after(dvalue);
+ }
+ else if (value instanceof BigInteger)
+ {
+ BigInteger ivalue = (BigInteger) value;
+ if (!(test instanceof BigInteger))
+ return false;
+ return ((BigInteger) test).compareTo(ivalue) > 0;
+ }
+ else if (value instanceof BigDecimal)
+ {
+ BigDecimal dvalue = (BigDecimal) value;
+ if (!(test instanceof BigDecimal))
+ return false;
+ return ((BigDecimal) test).compareTo(dvalue) > 0;
+ }
+ else if (value instanceof Comparable)
+ {
+ if (!(test.getClass().equals(value.getClass())))
+ return false;
+ return ((Comparable) test).compareTo(value) > 0;
+ }
+ Number nvalue = (Number) value;
+ if (!(test instanceof Number))
+ return false;
+ return ((Number) test).doubleValue() > nvalue.doubleValue();
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/MinInclusiveFacet.java b/libjava/classpath/gnu/xml/validation/datatype/MinInclusiveFacet.java
new file mode 100644
index 00000000000..6c07c3644a8
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/MinInclusiveFacet.java
@@ -0,0 +1,112 @@
+/* MinInclusiveFacet.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+/**
+ * The <code>minInclusive</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class MinInclusiveFacet
+ extends Facet
+{
+
+ public final Object value;
+
+ public final boolean fixed;
+
+ public MinInclusiveFacet(Object value, boolean fixed, Annotation annotation)
+ {
+ super(MIN_INCLUSIVE, annotation);
+ this.value = value;
+ this.fixed = fixed;
+ }
+
+ public int hashCode()
+ {
+ return value.hashCode();
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof MinInclusiveFacet &&
+ ((MinInclusiveFacet) other).value.equals(value));
+ }
+
+ boolean matches(Object test)
+ {
+ if (value instanceof Date)
+ {
+ Date dvalue = (Date) value;
+ if (!(test instanceof Date))
+ return false;
+ Date dtest = (Date) test;
+ return dtest.equals(dvalue) || dtest.after(dvalue);
+ }
+ else if (value instanceof BigInteger)
+ {
+ BigInteger ivalue = (BigInteger) value;
+ if (!(test instanceof BigInteger))
+ return false;
+ return ((BigInteger) test).compareTo(ivalue) >= 0;
+ }
+ else if (value instanceof BigDecimal)
+ {
+ BigDecimal dvalue = (BigDecimal) value;
+ if (!(test instanceof BigDecimal))
+ return false;
+ return ((BigDecimal) test).compareTo(dvalue) >= 0;
+ }
+ else if (value instanceof Comparable)
+ {
+ if (!(test.getClass().equals(value.getClass())))
+ return false;
+ return ((Comparable) test).compareTo(value) >= 0;
+ }
+ Number nvalue = (Number) value;
+ if (!(test instanceof Number))
+ return false;
+ return ((Number) test).doubleValue() >= nvalue.doubleValue();
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/MinLengthFacet.java b/libjava/classpath/gnu/xml/validation/datatype/MinLengthFacet.java
new file mode 100644
index 00000000000..c7dee200bad
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/MinLengthFacet.java
@@ -0,0 +1,72 @@
+/* MinLengthFacet.java --
+ 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.xml.validation.datatype;
+
+/**
+ * The <code>minLength</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class MinLengthFacet
+ extends Facet
+{
+
+ public final int value;
+
+ public final boolean fixed;
+
+ public MinLengthFacet(int value, boolean fixed, Annotation annotation)
+ {
+ super(MIN_LENGTH, annotation);
+ this.value = value;
+ this.fixed = fixed;
+ }
+
+ public int hashCode()
+ {
+ return value;
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof MinLengthFacet &&
+ ((MinLengthFacet) other).value == value);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NCNameType.java b/libjava/classpath/gnu/xml/validation/datatype/NCNameType.java
new file mode 100644
index 00000000000..4188d886af7
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NCNameType.java
@@ -0,0 +1,111 @@
+/* NCNameType.java --
+ 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.xml.validation.datatype;
+
+import java.io.IOException;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+import gnu.xml.stream.UnicodeReader;
+import gnu.xml.stream.XMLParser;
+
+/**
+ * The XML Schema NCName type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NCNameType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ NCNameType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "NCName"),
+ TypeLibrary.NAME);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ try
+ {
+ int[] cp = UnicodeReader.toCodePointArray(value);
+ if (cp.length == 0)
+ throw new DatatypeException("invalid NCName value");
+ // XXX XML 1.1 documents?
+ if (cp[0] == ':' || !XMLParser.isNameStartCharacter(cp[0], false))
+ throw new DatatypeException(0, "invalid NCName value");
+ boolean seenColon = false;
+ for (int i = 1; i < cp.length; i++)
+ {
+ if (cp[i] == ':')
+ {
+ if (seenColon || (i + 1 == cp.length))
+ throw new DatatypeException(i, "invalid NCName value");
+ seenColon = true;
+ }
+ else if (!XMLParser.isNameCharacter(cp[i], false))
+ throw new DatatypeException(i, "invalid NCName value");
+ }
+ }
+ catch (IOException e)
+ {
+ DatatypeException e2 = new DatatypeException("invalid NCName value");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NMTokenType.java b/libjava/classpath/gnu/xml/validation/datatype/NMTokenType.java
new file mode 100644
index 00000000000..4498fecfa1b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NMTokenType.java
@@ -0,0 +1,102 @@
+/* NMTokenType.java --
+ 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.xml.validation.datatype;
+
+import java.io.IOException;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+import gnu.xml.stream.UnicodeReader;
+import gnu.xml.stream.XMLParser;
+
+/**
+ * The XML Schema NMTOKEN type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NMTokenType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ NMTokenType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "NMTOKEN"),
+ TypeLibrary.TOKEN);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ try
+ {
+ int[] cp = UnicodeReader.toCodePointArray(value);
+ if (cp.length == 0)
+ throw new DatatypeException("invalid NMTOKEN value");
+ for (int i = 0; i < cp.length; i++)
+ {
+ // XXX XML 1.1 documents?
+ if (!XMLParser.isNameCharacter(cp[i], false))
+ throw new DatatypeException(i, "invalid NMTOKEN value");
+ }
+ }
+ catch (IOException e)
+ {
+ DatatypeException e2 = new DatatypeException("invalid NMTOKEN value");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NMTokensType.java b/libjava/classpath/gnu/xml/validation/datatype/NMTokensType.java
new file mode 100644
index 00000000000..62524edf7cb
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NMTokensType.java
@@ -0,0 +1,124 @@
+/* NMTokensType.java --
+ 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.xml.validation.datatype;
+
+import java.io.IOException;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+import gnu.xml.stream.UnicodeReader;
+import gnu.xml.stream.XMLParser;
+
+/**
+ * The XML Schema NMTOKENS type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NMTokensType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ NMTokensType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "NMTOKENS"),
+ TypeLibrary.NMTOKEN);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == ' ')
+ {
+ String token = buf.toString();
+ if (token.length() > 0)
+ checkNmtoken(token, i);
+ buf.setLength(0);
+ }
+ else
+ buf.append(c);
+ }
+ checkNmtoken(buf.toString(), len);
+ }
+
+ private void checkNmtoken(String text, int i)
+ throws DatatypeException
+ {
+ try
+ {
+ int[] cp = UnicodeReader.toCodePointArray(text);
+ if (cp.length == 0)
+ throw new DatatypeException("invalid NMTOKEN value");
+ for (int j = 0; j < cp.length; j++)
+ {
+ // XXX XML 1.1 documents?
+ if (!XMLParser.isNameCharacter(cp[j], false))
+ throw new DatatypeException(i, "invalid NMTOKEN value");
+ }
+ }
+ catch (IOException e)
+ {
+ DatatypeException e2 = new DatatypeException("invalid NMTOKEN value");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NameType.java b/libjava/classpath/gnu/xml/validation/datatype/NameType.java
new file mode 100644
index 00000000000..a2fbb9d5bb5
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NameType.java
@@ -0,0 +1,104 @@
+/* NameType.java --
+ 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.xml.validation.datatype;
+
+import java.io.IOException;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+import gnu.xml.stream.UnicodeReader;
+import gnu.xml.stream.XMLParser;
+
+/**
+ * The XML Schema Name type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NameType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ NameType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "Name"),
+ TypeLibrary.TOKEN);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ try
+ {
+ int[] cp = UnicodeReader.toCodePointArray(value);
+ if (cp.length == 0)
+ throw new DatatypeException("invalid Name value");
+ // XXX XML 1.1 documents?
+ if (!XMLParser.isNameStartCharacter(cp[0], false))
+ throw new DatatypeException(0, "invalid Name value");
+ for (int i = 1; i < cp.length; i++)
+ {
+ if (!XMLParser.isNameCharacter(cp[i], false))
+ throw new DatatypeException(i, "invalid Name value");
+ }
+ }
+ catch (IOException e)
+ {
+ DatatypeException e2 = new DatatypeException("invalid Name value");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NegativeIntegerType.java b/libjava/classpath/gnu/xml/validation/datatype/NegativeIntegerType.java
new file mode 100644
index 00000000000..fd436cb55b2
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NegativeIntegerType.java
@@ -0,0 +1,111 @@
+/* NegativeIntegerType.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigInteger;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema negativeInteger type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NegativeIntegerType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ NegativeIntegerType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "negativeInteger"),
+ TypeLibrary.NON_POSITIVE_INTEGER);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValue(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid negative integer value");
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-')
+ {
+ if (i == 0)
+ continue;
+ }
+ else if (c >= 0x30 && c <= 0x39)
+ continue;
+ throw new DatatypeException(i, "invalid negative integer value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new BigInteger(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NonNegativeIntegerType.java b/libjava/classpath/gnu/xml/validation/datatype/NonNegativeIntegerType.java
new file mode 100644
index 00000000000..8577785829c
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NonNegativeIntegerType.java
@@ -0,0 +1,121 @@
+/* NonNegativeIntegerType.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigInteger;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema nonNegativeInteger type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NonNegativeIntegerType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ NonNegativeIntegerType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "nonNegativeInteger"),
+ TypeLibrary.INTEGER);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid non-negative integer value");
+ boolean negative = false;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == 0x30)
+ continue;
+ else if (c >= 0x31 && c <= 0x39)
+ {
+ if (negative)
+ throw new DatatypeException(i,
+ "invalid non-negative integer value");
+ continue;
+ }
+ else if (c == '+' && i == 0)
+ continue;
+ else if (c == '-' && i == 0)
+ {
+ negative = true;
+ continue;
+ }
+ throw new DatatypeException(i, "invalid non-negative integer value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new BigInteger(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NonPositiveIntegerType.java b/libjava/classpath/gnu/xml/validation/datatype/NonPositiveIntegerType.java
new file mode 100644
index 00000000000..0b43d5227d6
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NonPositiveIntegerType.java
@@ -0,0 +1,121 @@
+/* NonPositiveIntegerType.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigInteger;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema nonPositiveInteger type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NonPositiveIntegerType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ NonPositiveIntegerType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "nonPositiveInteger"),
+ TypeLibrary.INTEGER);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid non-positive integer value");
+ boolean positive = true;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == 0x30)
+ continue;
+ else if (c >= 0x31 && c <= 0x39)
+ {
+ if (positive)
+ throw new DatatypeException(i,
+ "invalid non-positive integer value");
+ continue;
+ }
+ else if (c == '+' && i == 0)
+ continue;
+ else if (c == '-' && i == 0)
+ {
+ positive = false;
+ continue;
+ }
+ throw new DatatypeException(i, "invalid non-positive integer value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new BigInteger(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NormalizedStringType.java b/libjava/classpath/gnu/xml/validation/datatype/NormalizedStringType.java
new file mode 100644
index 00000000000..a74312d11d3
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NormalizedStringType.java
@@ -0,0 +1,88 @@
+/* NormalizedStringType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema normalizedString type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NormalizedStringType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ NormalizedStringType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "normalizedString"),
+ TypeLibrary.STRING);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == 0x0a || c == 0x0d || c == 0x09)
+ throw new DatatypeException(i, "invalid normalized-string value");
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/NotationType.java b/libjava/classpath/gnu/xml/validation/datatype/NotationType.java
new file mode 100644
index 00000000000..59c7f25e538
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/NotationType.java
@@ -0,0 +1,90 @@
+/* NotationType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Collections;
+import java.util.Set;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema NOTATION type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class NotationType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ NotationType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "NOTATION"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ if (!context.isNotation(value))
+ throw new DatatypeException("invalid NOTATION value");
+ }
+
+ public boolean isContextDependent()
+ {
+ return true;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/PatternFacet.java b/libjava/classpath/gnu/xml/validation/datatype/PatternFacet.java
new file mode 100644
index 00000000000..d594b26b938
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/PatternFacet.java
@@ -0,0 +1,71 @@
+/* PatternFacet.java --
+ 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.xml.validation.datatype;
+
+import java.util.regex.Pattern;
+
+/**
+ * The <code>pattern</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class PatternFacet
+ extends Facet
+{
+
+ public final Pattern value;
+
+ public PatternFacet(Pattern value, Annotation annotation)
+ {
+ super(PATTERN, annotation);
+ this.value = value;
+ }
+
+ public int hashCode()
+ {
+ return value.hashCode();
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof PatternFacet &&
+ ((PatternFacet) other).value.equals(value));
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/PositiveIntegerType.java b/libjava/classpath/gnu/xml/validation/datatype/PositiveIntegerType.java
new file mode 100644
index 00000000000..0c10df3ab8d
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/PositiveIntegerType.java
@@ -0,0 +1,111 @@
+/* PositiveIntegerType.java --
+ 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.xml.validation.datatype;
+
+import java.math.BigInteger;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema positiveInteger type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class PositiveIntegerType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ PositiveIntegerType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "positiveInteger"),
+ TypeLibrary.NON_NEGATIVE_INTEGER);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid positive integer value");
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '+')
+ {
+ if (i == 0)
+ continue;
+ }
+ else if (c >= 0x30 && c <= 0x39)
+ continue;
+ throw new DatatypeException(i, "invalid positive integer value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new BigInteger(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/QNameType.java b/libjava/classpath/gnu/xml/validation/datatype/QNameType.java
new file mode 100644
index 00000000000..1eaa518954d
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/QNameType.java
@@ -0,0 +1,122 @@
+/* QNameType.java --
+ 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.xml.validation.datatype;
+
+import java.io.IOException;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+import gnu.xml.stream.UnicodeReader;
+import gnu.xml.stream.XMLParser;
+
+/**
+ * The XML Schema QName type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class QNameType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ QNameType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "QName"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int ci = -1;
+ try
+ {
+ int[] cp = UnicodeReader.toCodePointArray(value);
+ if (cp.length == 0)
+ throw new DatatypeException("invalid NCName value");
+ // XXX XML 1.1 documents?
+ if (cp[0] == ':' || !XMLParser.isNameStartCharacter(cp[0], false))
+ throw new DatatypeException(0, "invalid NCName value");
+ for (int i = 1; i < cp.length; i++)
+ {
+ if (cp[i] == ':')
+ {
+ if (ci != -1 || (i + 1 == cp.length))
+ throw new DatatypeException(i, "invalid NCName value");
+ ci = i;
+ }
+ else if (!XMLParser.isNameCharacter(cp[i], false))
+ throw new DatatypeException(i, "invalid NCName value");
+ }
+ }
+ catch (IOException e)
+ {
+ DatatypeException e2 = new DatatypeException("invalid NCName value");
+ e2.initCause(e);
+ throw e2;
+ }
+ if (ci != -1)
+ {
+ String prefix = value.substring(0, ci);
+ if (context.resolveNamespacePrefix(prefix) == null)
+ throw new DatatypeException("invalid namespace prefix");
+ }
+ }
+
+ public boolean isContextDependent()
+ {
+ return true;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/ShortType.java b/libjava/classpath/gnu/xml/validation/datatype/ShortType.java
new file mode 100644
index 00000000000..3179c8dae99
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/ShortType.java
@@ -0,0 +1,133 @@
+/* ShortType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema short type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class ShortType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final String MAX_VALUE = "32767";
+ static final String MIN_VALUE = "32768";
+ static final int LENGTH = MAX_VALUE.length();
+
+ ShortType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "short"),
+ TypeLibrary.INT);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid short value");
+ int i = 0, off = 0;
+ boolean compare = false;
+ String compareTo = MAX_VALUE;
+ char c = value.charAt(0);
+ if (c == '+')
+ i++;
+ else if (c == '-')
+ {
+ compareTo = MIN_VALUE;
+ i++;
+ }
+ if (len - i > LENGTH)
+ throw new DatatypeException(i, "invalid short value");
+ else if (len - i == LENGTH)
+ compare = true;
+ for (; i < len; i++)
+ {
+ c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ {
+ if (compare)
+ {
+ char d = compareTo.charAt(off);
+ if (Character.digit(c, 10) > Character.digit(d, 10))
+ throw new DatatypeException(i, "invalid short value");
+ }
+ off++;
+ continue;
+ }
+ throw new DatatypeException(i, "invalid short value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Short(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/SimpleType.java b/libjava/classpath/gnu/xml/validation/datatype/SimpleType.java
new file mode 100644
index 00000000000..6554f2fe066
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/SimpleType.java
@@ -0,0 +1,257 @@
+/* SimpleType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Iterator;
+import java.util.Set;
+import java.util.regex.Matcher;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.Datatype;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.DatatypeStreamingValidator;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * An XML Schema simple type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class SimpleType
+ extends Type
+ implements Datatype
+{
+
+ /**
+ * The variety of the <code>anySimpleType</code> datatype.
+ */
+ public static final int ANY = 0;
+
+ /**
+ * The atomic variety.
+ */
+ public static final int ATOMIC = 1;
+
+ /**
+ * The list variety.
+ */
+ public static final int LIST = 2;
+
+ /**
+ * The union variety.
+ */
+ public static final int UNION = 3;
+
+ public static final int ID_TYPE_NULL = 0;
+ public static final int ID_TYPE_ID = 1;
+ public static final int ID_TYPE_IDREF = 2;
+ public static final int ID_TYPE_IDREFS = 3;
+
+ /**
+ * The variety of this simple type.
+ */
+ public final int variety;
+
+ /**
+ * The facets of this simple type.
+ */
+ public Set facets;
+
+ /**
+ * The fundamental facets of this simple type.
+ */
+ public int fundamentalFacets;
+
+ /**
+ * If this datatype has been derived by restriction, then the component
+ * from which it was derived.
+ */
+ public final SimpleType baseType;
+
+ /**
+ * Optional annotation.
+ */
+ public final Annotation annotation;
+
+ public SimpleType(QName name, int variety, Set facets,
+ int fundamentalFacets, SimpleType baseType,
+ Annotation annotation)
+ {
+ super(name);
+ this.variety = variety;
+ this.facets = facets;
+ this.fundamentalFacets = fundamentalFacets;
+ this.baseType = baseType;
+ this.annotation = annotation;
+ }
+
+ /**
+ * Indicates whether this type permits the specified value.
+ */
+ public boolean isValid(String value, ValidationContext context)
+ {
+ try
+ {
+ checkValid(value, context);
+ return true;
+ }
+ catch (DatatypeException e)
+ {
+ return false;
+ }
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ if (facets != null && !facets.isEmpty())
+ {
+ Object parsedValue = createValue(value, context);
+ for (Iterator i = facets.iterator(); i.hasNext(); )
+ {
+ Facet facet = (Facet) i.next();
+ switch (facet.type)
+ {
+ case Facet.LENGTH:
+ LengthFacet lf = (LengthFacet) facet;
+ if (value.length() != lf.value)
+ throw new DatatypeException("invalid length");
+ break;
+ case Facet.MIN_LENGTH:
+ MinLengthFacet nlf = (MinLengthFacet) facet;
+ if (value.length() < nlf.value)
+ throw new DatatypeException("invalid minimum length");
+ break;
+ case Facet.MAX_LENGTH:
+ MaxLengthFacet xlf = (MaxLengthFacet) facet;
+ if (value.length() > xlf.value)
+ throw new DatatypeException("invalid maximum length");
+ break;
+ case Facet.PATTERN:
+ PatternFacet pf = (PatternFacet) facet;
+ Matcher matcher = pf.value.matcher(value);
+ if (!matcher.find())
+ throw new DatatypeException("invalid match for pattern");
+ break;
+ case Facet.ENUMERATION:
+ // TODO
+ break;
+ case Facet.WHITESPACE:
+ // TODO
+ break;
+ case Facet.MAX_INCLUSIVE:
+ MaxInclusiveFacet xif = (MaxInclusiveFacet) facet;
+ if (!xif.matches(parsedValue))
+ throw new DatatypeException("beyond upper bound");
+ break;
+ case Facet.MAX_EXCLUSIVE:
+ MaxExclusiveFacet xef = (MaxExclusiveFacet) facet;
+ if (!xef.matches(parsedValue))
+ throw new DatatypeException("beyond upper bound");
+ break;
+ case Facet.MIN_EXCLUSIVE:
+ MinExclusiveFacet nef = (MinExclusiveFacet) facet;
+ if (!nef.matches(parsedValue))
+ throw new DatatypeException("beyond lower bound");
+ break;
+ case Facet.MIN_INCLUSIVE:
+ MinInclusiveFacet nif = (MinInclusiveFacet) facet;
+ if (!nif.matches(parsedValue))
+ throw new DatatypeException("beyond lower bound");
+ break;
+ case Facet.TOTAL_DIGITS:
+ TotalDigitsFacet tdf = (TotalDigitsFacet) facet;
+ if (countDigits(value, true) > tdf.value)
+ throw new DatatypeException("too many digits");
+ break;
+ case Facet.FRACTION_DIGITS:
+ FractionDigitsFacet fdf = (FractionDigitsFacet) facet;
+ if (countDigits(value, false) > fdf.value)
+ throw new DatatypeException("too many fraction digits");
+ break;
+ }
+ }
+ }
+ }
+
+ private static int countDigits(String value, boolean any)
+ {
+ int count = 0;
+ int len = value.length();
+ boolean seenDecimal = false;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == 0x2e)
+ seenDecimal = true;
+ else if (c >= 0x30 && c <= 0x39 && (any || seenDecimal))
+ count++;
+ }
+ return count;
+ }
+
+ // TODO createStreamingValidator
+ public DatatypeStreamingValidator createStreamingValidator(ValidationContext context)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ return literal;
+ }
+
+ public boolean sameValue(Object value1, Object value2) {
+ return value1.equals(value2);
+ }
+
+ public int valueHashCode(Object value) {
+ return value.hashCode();
+ }
+
+ public int getIdType()
+ {
+ return ID_TYPE_NULL;
+ }
+
+ public boolean isContextDependent()
+ {
+ return false;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/StringType.java b/libjava/classpath/gnu/xml/validation/datatype/StringType.java
new file mode 100644
index 00000000000..a2235f2df66
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/StringType.java
@@ -0,0 +1,77 @@
+/* StringType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Collections;
+import java.util.Set;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema string type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class StringType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ StringType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "string"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/TimeType.java b/libjava/classpath/gnu/xml/validation/datatype/TimeType.java
new file mode 100644
index 00000000000..0152e11717d
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/TimeType.java
@@ -0,0 +1,303 @@
+/* TimeType.java --
+ 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.xml.validation.datatype;
+
+import java.util.TimeZone;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema time type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class TimeType
+ extends AtomicSimpleType
+{
+
+ static class Time
+ implements Comparable
+ {
+ int minutes;
+ float seconds;
+
+ public int hashCode()
+ {
+ return minutes * 31 + new Float(seconds).hashCode();
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other instanceof Time)
+ {
+ Time time = (Time) other;
+ return time.minutes == minutes && time.seconds == seconds;
+ }
+ return false;
+ }
+
+ public int compareTo(Object other)
+ {
+ if (other instanceof Time)
+ {
+ Time time = (Time) other;
+ if (time.minutes != minutes)
+ return minutes - time.minutes;
+ if (time.seconds == seconds)
+ return 0;
+ return (seconds < time.seconds) ? -1 : 1;
+ }
+ return 0;
+ }
+
+ }
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ TimeType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "time"),
+ TypeLibrary.ANY_SIMPLE_TYPE);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ int state = 3;
+ int start = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == '-' && state == 0)
+ {
+ start++;
+ continue;
+ }
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 3: // hour
+ if (c == ':')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid time value");
+ state = 4;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 4: // minute
+ if (c == ':')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid time value");
+ state = 5;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 5: // second
+ if (c == '.')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid time value");
+ state = 6;
+ start = i + 1;
+ continue;
+ }
+ else if (c == ' ')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid time value");
+ state = 7;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 6: // second fraction
+ if (c == ' ')
+ {
+ state = 7;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 7: // timezone 1
+ if (start == i)
+ {
+ if (c == '+' || c == '-')
+ continue;
+ else if (c == 'Z')
+ {
+ state = 9;
+ start = i + 1;
+ continue;
+ }
+ }
+ if (c == ':')
+ {
+ if (i - start != 2)
+ throw new DatatypeException(i, "invalid time value");
+ state = 8;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ throw new DatatypeException(i, "invalid time value");
+ }
+ switch (state)
+ {
+ case 5: // second
+ if (len - start != 2)
+ throw new DatatypeException(len, "invalid time value");
+ break;
+ case 6: // second fraction
+ break;
+ case 8: // timezone 2
+ if (len - start != 2)
+ throw new DatatypeException(len, "invalid time value");
+ break;
+ case 9: // post Z
+ break;
+ default:
+ throw new DatatypeException(len, "invalid time value");
+ }
+ }
+
+ public Object createValue(String value, ValidationContext context) {
+ int len = value.length();
+ int state = 3;
+ int start = 0;
+ Time time = new Time();
+ try
+ {
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ continue;
+ switch (state)
+ {
+ case 3: // hour
+ if (c == ':')
+ {
+ time.minutes =
+ Integer.parseInt(value.substring(start, i)) * 60;
+ state = 4;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 4: // minute
+ if (c == ':')
+ {
+ time.minutes +=
+ Integer.parseInt(value.substring(start, i));
+ state = 5;
+ start = i + 1;
+ continue;
+ }
+ break;
+ case 5: // second
+ if (c == ' ')
+ {
+ time.seconds =
+ Float.parseFloat(value.substring(start, i));
+ state = 7;
+ start = i + 1;
+ continue;
+ }
+ break;
+ }
+ }
+ // end of input
+ if (len - start > 0 && state == 7)
+ {
+ // Timezone
+ String timezone = value.substring(len - start);
+ int i = timezone.indexOf(':');
+ if (i == -1)
+ {
+ if ("Z".equals(timezone))
+ timezone = "UTC";
+ TimeZone tz = TimeZone.getTimeZone(timezone);
+ if (tz == null)
+ return null;
+ time.minutes += tz.getRawOffset();
+ }
+ else
+ {
+ String tzh = timezone.substring(0, i);
+ String tzm = timezone.substring(i + 1);
+ int offset = Integer.parseInt(tzh) * 60;
+ if (offset < 0)
+ offset -= Integer.parseInt(tzm);
+ else
+ offset += Integer.parseInt(tzm);
+ time.minutes += offset;
+ }
+ }
+ return time;
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/TokenType.java b/libjava/classpath/gnu/xml/validation/datatype/TokenType.java
new file mode 100644
index 00000000000..18e1e8ad53a
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/TokenType.java
@@ -0,0 +1,96 @@
+/* TokenType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema token type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class TokenType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.LENGTH,
+ Facet.MIN_LENGTH,
+ Facet.MAX_LENGTH,
+ Facet.PATTERN,
+ Facet.ENUMERATION,
+ Facet.WHITESPACE
+ };
+
+ TokenType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "token"),
+ TypeLibrary.NORMALIZED_STRING);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid token value");
+ if (value.charAt(0) == ' ' || value.charAt(len - 1) == ' ')
+ throw new DatatypeException(0, "invalid token value");
+ char last = '\u0000';
+ for (int i = 0; i < len; i++)
+ {
+ char c = value.charAt(i);
+ if (c == 0x0a || c == 0x0d || c == 0x09)
+ throw new DatatypeException(i, "invalid token value");
+ if (c == ' ' && last == ' ')
+ throw new DatatypeException(i, "invalid token value");
+ last = c;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/TotalDigitsFacet.java b/libjava/classpath/gnu/xml/validation/datatype/TotalDigitsFacet.java
new file mode 100644
index 00000000000..4debc638e5e
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/TotalDigitsFacet.java
@@ -0,0 +1,72 @@
+/* TotalDigitsFacet.java --
+ 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.xml.validation.datatype;
+
+/**
+ * The <code>totalDigits</code> facet.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public final class TotalDigitsFacet
+ extends Facet
+{
+
+ public final int value;
+
+ public final boolean fixed;
+
+ public TotalDigitsFacet(int value, boolean fixed, Annotation annotation)
+ {
+ super(TOTAL_DIGITS, annotation);
+ this.value = value;
+ this.fixed = fixed;
+ }
+
+ public int hashCode()
+ {
+ return value;
+ }
+
+ public boolean equals(Object other)
+ {
+ return (other instanceof TotalDigitsFacet &&
+ ((TotalDigitsFacet) other).value == value);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/Type.java b/libjava/classpath/gnu/xml/validation/datatype/Type.java
new file mode 100644
index 00000000000..e0662761f37
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/Type.java
@@ -0,0 +1,65 @@
+/* Type.java --
+ 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.xml.validation.datatype;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.namespace.QName;
+/**
+ * Abstract base class for XML Schema datatypes.
+ * @see http://www.w3.org/TR/xmlschema-2/
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public abstract class Type
+{
+
+ public static final Type ANY_TYPE = new AnyType();
+
+ /**
+ * The name of this type.
+ */
+ public final QName name;
+
+ public Type(QName name)
+ {
+ this.name = name;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/TypeBuilder.java b/libjava/classpath/gnu/xml/validation/datatype/TypeBuilder.java
new file mode 100644
index 00000000000..606fd0e62fb
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/TypeBuilder.java
@@ -0,0 +1,279 @@
+/* TypeBuilder.java --
+ 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.xml.validation.datatype;
+
+import java.util.LinkedHashSet;
+import java.util.regex.Pattern;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.Datatype;
+import org.relaxng.datatype.DatatypeBuilder;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * Datatype builder.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class TypeBuilder
+ implements DatatypeBuilder
+{
+
+ final SimpleType type;
+
+ TypeBuilder(SimpleType type)
+ {
+ this.type = type;
+ // TODO fundamental facets
+ type.facets = new LinkedHashSet();
+ }
+
+ public void addParameter(String name, String value, ValidationContext context)
+ throws DatatypeException
+ {
+ // TODO fundamental facets
+ if ("length".equals(name))
+ type.facets.add(parseLengthFacet(value));
+ else if ("minLength".equals(name))
+ type.facets.add(parseMinLengthFacet(value));
+ else if ("maxLength".equals(name))
+ type.facets.add(parseMaxLengthFacet(value));
+ else if ("pattern".equals(name))
+ type.facets.add(parsePatternFacet(value));
+ else if ("enumeration".equals(name))
+ type.facets.add(parseEnumerationFacet(value));
+ else if ("whiteSpace".equals(name))
+ type.facets.add(parseWhiteSpaceFacet(value));
+ else if ("maxInclusive".equals(name))
+ type.facets.add(parseMaxInclusiveFacet(value, context));
+ else if ("maxExclusive".equals(name))
+ type.facets.add(parseMaxExclusiveFacet(value, context));
+ else if ("minExclusive".equals(name))
+ type.facets.add(parseMinExclusiveFacet(value, context));
+ else if ("minInclusive".equals(name))
+ type.facets.add(parseMinInclusiveFacet(value, context));
+ else if ("totalDigits".equals(name))
+ type.facets.add(parseTotalDigitsFacet(value));
+ else if ("fractionDigits".equals(name))
+ type.facets.add(parseFractionDigitsFacet(value));
+ }
+
+ LengthFacet parseLengthFacet(String value)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ return new LengthFacet(Integer.parseInt(value), fixed, null);
+ }
+
+ MinLengthFacet parseMinLengthFacet(String value)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ return new MinLengthFacet(Integer.parseInt(value), fixed, null);
+ }
+
+ MaxLengthFacet parseMaxLengthFacet(String value)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ return new MaxLengthFacet(Integer.parseInt(value), fixed, null);
+ }
+
+ PatternFacet parsePatternFacet(String value)
+ throws DatatypeException
+ {
+ return new PatternFacet(Pattern.compile(value), null);
+ }
+
+ EnumerationFacet parseEnumerationFacet(String value)
+ throws DatatypeException
+ {
+ return new EnumerationFacet(value, null);
+ }
+
+ WhiteSpaceFacet parseWhiteSpaceFacet(String value)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ if ("preserve".equals(value))
+ return new WhiteSpaceFacet(WhiteSpaceFacet.PRESERVE, fixed, null);
+ if ("replace".equals(value))
+ return new WhiteSpaceFacet(WhiteSpaceFacet.REPLACE, fixed, null);
+ if ("collapse".equals(value))
+ return new WhiteSpaceFacet(WhiteSpaceFacet.COLLAPSE, fixed, null);
+ throw new DatatypeException("argument must be preserve, replace, or collapse");
+ }
+
+ MaxInclusiveFacet parseMaxInclusiveFacet(String value,
+ ValidationContext context)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ return new MaxInclusiveFacet(type.createValue(value, context), fixed, null);
+ }
+
+ MaxExclusiveFacet parseMaxExclusiveFacet(String value,
+ ValidationContext context)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ return new MaxExclusiveFacet(type.createValue(value, context), fixed, null);
+ }
+
+ MinExclusiveFacet parseMinExclusiveFacet(String value,
+ ValidationContext context)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ return new MinExclusiveFacet(type.createValue(value, context), fixed, null);
+ }
+
+ MinInclusiveFacet parseMinInclusiveFacet(String value,
+ ValidationContext context)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ return new MinInclusiveFacet(type.createValue(value, context), fixed, null);
+ }
+
+ TotalDigitsFacet parseTotalDigitsFacet(String value)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ int val = Integer.parseInt(value);
+ if (val < 0)
+ throw new DatatypeException("value must be a positiveInteger");
+ return new TotalDigitsFacet(val, fixed, null);
+ }
+
+ FractionDigitsFacet parseFractionDigitsFacet(String value)
+ throws DatatypeException
+ {
+ int si = value.indexOf(' ');
+ boolean fixed = false;
+ if (si != -1)
+ {
+ if (!"FIXED".equalsIgnoreCase(value.substring(si + 1)))
+ throw new DatatypeException("second argument must be FIXED if present");
+ fixed = true;
+ value = value.substring(0, si);
+ }
+ int val = Integer.parseInt(value);
+ if (val < 0)
+ throw new DatatypeException("value must be a positiveInteger");
+ return new FractionDigitsFacet(val, fixed, null);
+ }
+
+ public Datatype createDatatype()
+ {
+ return type;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/validation/datatype/TypeLibrary.java b/libjava/classpath/gnu/xml/validation/datatype/TypeLibrary.java
new file mode 100644
index 00000000000..f1daecebd97
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/TypeLibrary.java
@@ -0,0 +1,173 @@
+/* TypeLibrary.java --
+ 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.xml.validation.datatype;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.relaxng.datatype.Datatype;
+import org.relaxng.datatype.DatatypeBuilder;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.DatatypeLibrary;
+
+/**
+ * Datatype library for XML Schema datatypes.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class TypeLibrary
+ implements DatatypeLibrary
+{
+
+ public static final SimpleType ANY_SIMPLE_TYPE = new AnySimpleType();
+
+ public static final SimpleType STRING = new StringType();
+ public static final SimpleType BOOLEAN = new BooleanType();
+ public static final SimpleType DECIMAL = new DecimalType();
+ public static final SimpleType FLOAT = new FloatType();
+ public static final SimpleType DOUBLE = new DoubleType();
+ public static final SimpleType DURATION = new DurationType();
+ public static final SimpleType DATE_TIME = new DateTimeType();
+ public static final SimpleType TIME = new TimeType();
+ public static final SimpleType DATE = new DateType();
+ public static final SimpleType G_YEAR_MONTH = new GYearMonthType();
+ public static final SimpleType G_YEAR = new GYearType();
+ public static final SimpleType G_MONTH_DAY = new GMonthDayType();
+ public static final SimpleType G_DAY = new GDayType();
+ public static final SimpleType G_MONTH = new GMonthType();
+ public static final SimpleType HEX_BINARY = new HexBinaryType();
+ public static final SimpleType BASE64_BINARY = new Base64BinaryType();
+ public static final SimpleType ANY_URI = new AnyURIType();
+ public static final SimpleType QNAME = new QNameType();
+ public static final SimpleType NOTATION = new NotationType();
+
+ public static final SimpleType NORMALIZED_STRING = new NormalizedStringType();
+ public static final SimpleType TOKEN = new TokenType();
+ public static final SimpleType LANGUAGE = new LanguageType();
+ public static final SimpleType NMTOKEN = new NMTokenType();
+ public static final SimpleType NMTOKENS = new NMTokensType();
+ public static final SimpleType NAME = new NameType();
+ public static final SimpleType NCNAME = new NCNameType();
+ public static final SimpleType ID = new IDType();
+ public static final SimpleType IDREF = new IDRefType();
+ public static final SimpleType IDREFS = new IDRefsType();
+ public static final SimpleType ENTITY = new EntityType();
+ public static final SimpleType ENTITIES = new EntitiesType();
+ public static final SimpleType INTEGER = new IntegerType();
+ public static final SimpleType NON_POSITIVE_INTEGER = new NonPositiveIntegerType();
+ public static final SimpleType NEGATIVE_INTEGER = new NegativeIntegerType();
+ public static final SimpleType LONG = new LongType();
+ public static final SimpleType INT = new IntType();
+ public static final SimpleType SHORT = new ShortType();
+ public static final SimpleType BYTE = new ByteType();
+ public static final SimpleType NON_NEGATIVE_INTEGER = new NonNegativeIntegerType();
+ public static final SimpleType UNSIGNED_LONG = new UnsignedLongType();
+ public static final SimpleType UNSIGNED_INT = new UnsignedIntType();
+ public static final SimpleType UNSIGNED_SHORT = new UnsignedShortType();
+ public static final SimpleType UNSIGNED_BYTE = new UnsignedByteType();
+ public static final SimpleType POSITIVE_INTEGER = new PositiveIntegerType();
+
+ private static Map byName;
+ static
+ {
+ byName = new HashMap();
+ byName.put("anySimpleType", ANY_SIMPLE_TYPE);
+ byName.put("string", STRING);
+ byName.put("boolean", BOOLEAN);
+ byName.put("decimal", DECIMAL);
+ byName.put("float", FLOAT);
+ byName.put("double", DOUBLE);
+ byName.put("duration", DURATION);
+ byName.put("dateTime", DATE_TIME);
+ byName.put("time", TIME);
+ byName.put("date", DATE);
+ byName.put("gYearMonth", G_YEAR_MONTH);
+ byName.put("gYear", G_YEAR);
+ byName.put("gMonthDay", G_MONTH_DAY);
+ byName.put("gDay", G_DAY);
+ byName.put("gMonth",G_MONTH);
+ byName.put("hexBinary", HEX_BINARY);
+ byName.put("base64Binary", BASE64_BINARY);
+ byName.put("anyURI", ANY_URI);
+ byName.put("QName", QNAME);
+ byName.put("NOTATION", NOTATION);
+ byName.put("normalizedString", NORMALIZED_STRING);
+ byName.put("token", TOKEN);
+ byName.put("language", LANGUAGE);
+ byName.put("NMTOKEN", NMTOKEN);
+ byName.put("NMTOKENS", NMTOKENS);
+ byName.put("Name", NAME);
+ byName.put("NCName", NCNAME);
+ byName.put("ID", ID);
+ byName.put("IDREF", IDREF);
+ byName.put("IDREFS", IDREFS);
+ byName.put("ENTITY", ENTITY);
+ byName.put("ENTITIES", ENTITIES);
+ byName.put("integer", INTEGER);
+ byName.put("nonPositiveInteger", NON_POSITIVE_INTEGER);
+ byName.put("negativeInteger", NEGATIVE_INTEGER);
+ byName.put("long", LONG);
+ byName.put("int", INT);
+ byName.put("short", SHORT);
+ byName.put("byte", BYTE);
+ byName.put("nonNegativeInteger", NON_NEGATIVE_INTEGER);
+ byName.put("unsignedLong", UNSIGNED_LONG);
+ byName.put("unsignedInt", UNSIGNED_INT);
+ byName.put("unsignedShort", UNSIGNED_SHORT);
+ byName.put("unsignedByte", UNSIGNED_BYTE);
+ byName.put("positiveInteger", POSITIVE_INTEGER);
+ }
+
+ public DatatypeBuilder createDatatypeBuilder(String baseTypeLocalName)
+ throws DatatypeException
+ {
+ SimpleType type = (SimpleType) byName.get(baseTypeLocalName);
+ if (type == null)
+ throw new DatatypeException("Unknown type name: " + baseTypeLocalName);
+ return new TypeBuilder(type);
+ }
+
+ public Datatype createDatatype(String typeLocalName)
+ throws DatatypeException
+ {
+ SimpleType type = (SimpleType) byName.get(typeLocalName);
+ if (type == null)
+ throw new DatatypeException("Unknown type name: " + typeLocalName);
+ return type;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/validation/datatype/TypeLibraryFactory.java b/libjava/classpath/gnu/xml/validation/datatype/TypeLibraryFactory.java
new file mode 100644
index 00000000000..21ee6422409
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/TypeLibraryFactory.java
@@ -0,0 +1,60 @@
+/* TypeLibraryFactory.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import org.relaxng.datatype.DatatypeLibrary;
+import org.relaxng.datatype.DatatypeLibraryFactory;
+
+/**
+ * Datatype library factory for XML Schema datatypes.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class TypeLibraryFactory
+ implements DatatypeLibraryFactory
+{
+
+ public DatatypeLibrary createDatatypeLibrary(String namespaceURI)
+ {
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(namespaceURI))
+ return new TypeLibrary();
+ return null;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/validation/datatype/UnionSimpleType.java b/libjava/classpath/gnu/xml/validation/datatype/UnionSimpleType.java
new file mode 100644
index 00000000000..d87c2aa7a1b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/UnionSimpleType.java
@@ -0,0 +1,83 @@
+/* UnionSimpleType.java --
+ 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.xml.validation.datatype;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * An XML Schema union simple type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class UnionSimpleType
+ extends SimpleType
+{
+
+ /**
+ * The member types in this union.
+ */
+ public final List memberTypes;
+
+ public UnionSimpleType(QName name, Set facets,
+ int fundamentalFacets, SimpleType baseType,
+ Annotation annotation, List memberTypes)
+ {
+ super(name, UNION, facets, fundamentalFacets, baseType, annotation);
+ this.memberTypes = memberTypes;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ for (Iterator i = memberTypes.iterator(); i.hasNext(); )
+ {
+ SimpleType type = (SimpleType) i.next();
+ if (type.isValid(value, context))
+ return;
+ }
+ throw new DatatypeException("invalid union type value");
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/UnsignedByteType.java b/libjava/classpath/gnu/xml/validation/datatype/UnsignedByteType.java
new file mode 100644
index 00000000000..772c9cc0a9b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/UnsignedByteType.java
@@ -0,0 +1,121 @@
+/* UnsignedByteType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema unsignedByte type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class UnsignedByteType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final String MAX_VALUE = "255";
+ static final int LENGTH = MAX_VALUE.length();
+
+ UnsignedByteType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "unsignedByte"),
+ TypeLibrary.UNSIGNED_SHORT);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid unsigned byte value");
+ boolean compare = false;
+ for (int i = 0; i < len; i++)
+ {
+ if (len - i > LENGTH)
+ throw new DatatypeException(i, "invalid unsigned byte value");
+ else if (len - i == LENGTH)
+ compare = true;
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ {
+ if (compare)
+ {
+ char d = MAX_VALUE.charAt(i);
+ if (Character.digit(c, 10) > Character.digit(d, 10))
+ throw new DatatypeException(i, "invalid unsigned byte value");
+ }
+ continue;
+ }
+ throw new DatatypeException(i, "invalid unsigned byte value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Byte(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/UnsignedIntType.java b/libjava/classpath/gnu/xml/validation/datatype/UnsignedIntType.java
new file mode 100644
index 00000000000..a4e8a68201c
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/UnsignedIntType.java
@@ -0,0 +1,121 @@
+/* UnsignedIntType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema unsignedInt type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class UnsignedIntType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final String MAX_VALUE = "4294967295";
+ static final int LENGTH = MAX_VALUE.length();
+
+ UnsignedIntType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "unsignedInt"),
+ TypeLibrary.UNSIGNED_LONG);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid unsigned int value");
+ boolean compare = false;
+ for (int i = 0; i < len; i++)
+ {
+ if (len - i > LENGTH)
+ throw new DatatypeException(i, "invalid unsigned int value");
+ else if (len - i == LENGTH)
+ compare = true;
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ {
+ if (compare)
+ {
+ char d = MAX_VALUE.charAt(i);
+ if (Character.digit(c, 10) > Character.digit(d, 10))
+ throw new DatatypeException(i, "invalid unsigned int value");
+ }
+ continue;
+ }
+ throw new DatatypeException(i, "invalid unsigned int value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Integer(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/UnsignedLongType.java b/libjava/classpath/gnu/xml/validation/datatype/UnsignedLongType.java
new file mode 100644
index 00000000000..5a36d8a3170
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/UnsignedLongType.java
@@ -0,0 +1,121 @@
+/* UnsignedLongType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema unsignedLong type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class UnsignedLongType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final String MAX_VALUE = "18446744073709551615";
+ static final int LENGTH = MAX_VALUE.length();
+
+ UnsignedLongType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "unsignedLong"),
+ TypeLibrary.NON_NEGATIVE_INTEGER);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid unsigned long value");
+ boolean compare = false;
+ for (int i = 0; i < len; i++)
+ {
+ if (len - i > LENGTH)
+ throw new DatatypeException(i, "invalid unsigned long value");
+ else if (len - i == LENGTH)
+ compare = true;
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ {
+ if (compare)
+ {
+ char d = MAX_VALUE.charAt(i);
+ if (Character.digit(c, 10) > Character.digit(d, 10))
+ throw new DatatypeException(i, "invalid unsigned long value");
+ }
+ continue;
+ }
+ throw new DatatypeException(i, "invalid unsigned long value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Long(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/datatype/UnsignedShortType.java b/libjava/classpath/gnu/xml/validation/datatype/UnsignedShortType.java
new file mode 100644
index 00000000000..49f621be771
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/datatype/UnsignedShortType.java
@@ -0,0 +1,122 @@
+/* UnsignedShortType.java --
+ 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.xml.validation.datatype;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.ValidationContext;
+
+/**
+ * The XML Schema unsignedShort type.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class UnsignedShortType
+ extends AtomicSimpleType
+{
+
+ static final int[] CONSTRAINING_FACETS = {
+ Facet.TOTAL_DIGITS,
+ Facet.FRACTION_DIGITS,
+ Facet.PATTERN,
+ Facet.WHITESPACE,
+ Facet.ENUMERATION,
+ Facet.MAX_INCLUSIVE,
+ Facet.MAX_EXCLUSIVE,
+ Facet.MIN_INCLUSIVE,
+ Facet.MIN_EXCLUSIVE
+ };
+
+ static final String MAX_VALUE = "65535";
+ static final int LENGTH = MAX_VALUE.length();
+
+ UnsignedShortType()
+ {
+ super(new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "unsignedShort"),
+ TypeLibrary.UNSIGNED_INT);
+ }
+
+ public int[] getConstrainingFacets()
+ {
+ return CONSTRAINING_FACETS;
+ }
+
+ public void checkValid(String value, ValidationContext context)
+ throws DatatypeException
+ {
+ super.checkValid(value, context);
+ int len = value.length();
+ if (len == 0)
+ throw new DatatypeException(0, "invalid unsigned short value");
+ boolean compare = false;
+ for (int i = 0; i < len; i++)
+ {
+ if (len - i > LENGTH)
+ throw new DatatypeException(i, "invalid unsigned short value");
+ else if (len - i == LENGTH)
+ compare = true;
+ char c = value.charAt(i);
+ if (c >= 0x30 && c <= 0x39)
+ {
+ if (compare)
+ {
+ char d = MAX_VALUE.charAt(i);
+ if (Character.digit(c, 10) > Character.digit(d, 10))
+ throw new DatatypeException(i,
+ "invalid unsigned short value");
+ }
+ continue;
+ }
+ throw new DatatypeException(i, "invalid unsigned short value");
+ }
+ }
+
+ public Object createValue(String literal, ValidationContext context) {
+ try
+ {
+ return new Short(literal);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/stream/LocationImpl.java b/libjava/classpath/gnu/xml/validation/datatype/WhiteSpaceFacet.java
index 1900aeb45c3..5920e1c88b6 100644
--- a/libjava/classpath/gnu/xml/stream/LocationImpl.java
+++ b/libjava/classpath/gnu/xml/validation/datatype/WhiteSpaceFacet.java
@@ -1,5 +1,5 @@
-/* LocationImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+/* WhiteSpaceFacet.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,54 +35,40 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.xml.stream;
-
-import javax.xml.stream.Location;
+package gnu.xml.validation.datatype;
/**
- * Information about the location of an XML event within the underlying
- * stream.
+ * The <code>whiteSpace</code> facet.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
-public class LocationImpl
- implements Location
+public final class WhiteSpaceFacet
+ extends Facet
{
+
+ public static final int PRESERVE = 0;
+ public static final int REPLACE = 1;
+ public static final int COLLAPSE = 2;
+
+ public final int value;
+ public final boolean fixed;
- protected final int offset;
-
- protected final int col;
-
- protected final int line;
-
- protected final String systemId;
-
- protected LocationImpl(int offset, int col, int line, String systemId)
- {
- this.offset = offset;
- this.col = col;
- this.line = line;
- this.systemId = systemId;
- }
-
- public int getLineNumber()
- {
- return line;
- }
-
- public int getColumnNumber()
+ public WhiteSpaceFacet(int value, boolean fixed, Annotation annotation)
{
- return col;
+ super(WHITESPACE, annotation);
+ this.value = value;
+ this.fixed = fixed;
}
-
- public int getCharacterOffset()
+
+ public int hashCode()
{
- return offset;
+ return value;
}
- public String getLocationURI()
+ public boolean equals(Object other)
{
- return systemId;
+ return (other instanceof WhiteSpaceFacet &&
+ ((WhiteSpaceFacet) other).value == value);
}
}
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/AnyNameNameClass.java b/libjava/classpath/gnu/xml/validation/relaxng/AnyNameNameClass.java
new file mode 100644
index 00000000000..ecc016d4bd4
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/AnyNameNameClass.java
@@ -0,0 +1,58 @@
+/* AnyNameNameClass.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG anyName element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class AnyNameNameClass
+ extends NameClass
+{
+
+ NameClass exceptNameClass;
+
+ boolean matchesName(String uri, String localName)
+ {
+ return (exceptNameClass == null) ? true :
+ !exceptNameClass.matchesName(uri, localName);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/AttributePattern.java b/libjava/classpath/gnu/xml/validation/relaxng/AttributePattern.java
new file mode 100644
index 00000000000..48443d61b11
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/AttributePattern.java
@@ -0,0 +1,53 @@
+/* AttributePattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG attribute element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class AttributePattern
+ extends Pattern
+{
+
+ NameClass nameClass;
+ Pattern pattern;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/ChoiceNameClass.java b/libjava/classpath/gnu/xml/validation/relaxng/ChoiceNameClass.java
new file mode 100644
index 00000000000..e196cd4eee3
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/ChoiceNameClass.java
@@ -0,0 +1,59 @@
+/* ChoiceNameClass.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG choice element (in the context of a name class).
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class ChoiceNameClass
+ extends NameClass
+{
+
+ NameClass name1;
+ NameClass name2;
+
+ boolean matchesName(String uri, String localName)
+ {
+ return name1.matchesName(uri, localName) ||
+ name2.matchesName(uri, localName);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/ChoicePattern.java b/libjava/classpath/gnu/xml/validation/relaxng/ChoicePattern.java
new file mode 100644
index 00000000000..54739b27008
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/ChoicePattern.java
@@ -0,0 +1,53 @@
+/* ChoicePattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG choice element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class ChoicePattern
+ extends Pattern
+{
+
+ Pattern pattern1;
+ Pattern pattern2;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/DataPattern.java b/libjava/classpath/gnu/xml/validation/relaxng/DataPattern.java
new file mode 100644
index 00000000000..2315b2ce609
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/DataPattern.java
@@ -0,0 +1,60 @@
+/* DataPattern.java --
+ 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.xml.validation.relaxng;
+
+import java.util.LinkedList;
+import java.util.List;
+import org.relaxng.datatype.Datatype;
+import org.relaxng.datatype.DatatypeLibrary;
+
+/**
+ * A RELAX NG data element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class DataPattern
+ extends Pattern
+{
+
+ Datatype type;
+ DatatypeLibrary datatypeLibrary;
+ List params = new LinkedList();
+ Pattern exceptPattern;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/Define.java b/libjava/classpath/gnu/xml/validation/relaxng/Define.java
new file mode 100644
index 00000000000..8801d581e28
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/Define.java
@@ -0,0 +1,52 @@
+/* Define.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG define.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class Define
+{
+
+ String name;
+ ElementPattern element;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/ElementPattern.java b/libjava/classpath/gnu/xml/validation/relaxng/ElementPattern.java
new file mode 100644
index 00000000000..9ff3570755a
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/ElementPattern.java
@@ -0,0 +1,53 @@
+/* ElementPattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class ElementPattern
+ extends Pattern
+{
+
+ NameClass nameClass;
+ Pattern pattern;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/EmptyPattern.java b/libjava/classpath/gnu/xml/validation/relaxng/EmptyPattern.java
new file mode 100644
index 00000000000..ce568f84b34
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/EmptyPattern.java
@@ -0,0 +1,52 @@
+/* EmptyPattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG empty element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class EmptyPattern
+ extends Pattern
+{
+
+ static final EmptyPattern INSTANCE = new EmptyPattern();
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/FullSyntaxBuilder.java b/libjava/classpath/gnu/xml/validation/relaxng/FullSyntaxBuilder.java
new file mode 100644
index 00000000000..2a6833737bb
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/FullSyntaxBuilder.java
@@ -0,0 +1,1651 @@
+/* FullSyntaxBuilder.java --
+ 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.xml.validation.relaxng;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.DatatypeLibrary;
+import org.relaxng.datatype.helpers.DatatypeLibraryLoader;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import gnu.xml.stream.XMLParser;
+
+/**
+ * Parses a RELAX NG XML DOM tree, constructing a compiled internal
+ * representation.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class FullSyntaxBuilder
+{
+
+ /**
+ * Complete vocabulary (elements and attributes) of the full syntax.
+ */
+ static final Map VOCABULARY = new HashMap();
+ static final Set STRIPPED_ATTRIBUTES = new HashSet();
+ static final Set PATTERN_ELEMENTS = new HashSet();
+ static
+ {
+ Set elementAttrs = Collections.singleton("name");
+ Set dataAttrs = new HashSet();
+ dataAttrs.add("type");
+ dataAttrs.add("datatypeLibrary");
+ Set valueAttrs = new HashSet();
+ valueAttrs.add("type");
+ valueAttrs.add("datatypeLibrary");
+ valueAttrs.add("ns");
+ Set externalAttrs = Collections.singleton("href");
+ Set startAttrs = Collections.singleton("combine");
+ Set defineAttrs = new HashSet();
+ defineAttrs.add("name");
+ defineAttrs.add("combine");
+ Set nsAttrs = Collections.singleton("ns");
+
+ VOCABULARY.put("element", elementAttrs);
+ VOCABULARY.put("attribute", elementAttrs);
+ VOCABULARY.put("group", Collections.EMPTY_SET);
+ VOCABULARY.put("interleave", Collections.EMPTY_SET);
+ VOCABULARY.put("choice", Collections.EMPTY_SET);
+ VOCABULARY.put("optional", Collections.EMPTY_SET);
+ VOCABULARY.put("zeroOrMore", Collections.EMPTY_SET);
+ VOCABULARY.put("oneOrMore", Collections.EMPTY_SET);
+ VOCABULARY.put("list", Collections.EMPTY_SET);
+ VOCABULARY.put("mixed", Collections.EMPTY_SET);
+ VOCABULARY.put("ref", elementAttrs);
+ VOCABULARY.put("parentRef", elementAttrs);
+ VOCABULARY.put("empty", Collections.EMPTY_SET);
+ VOCABULARY.put("text", Collections.EMPTY_SET);
+ VOCABULARY.put("value", valueAttrs);
+ VOCABULARY.put("data", dataAttrs);
+ VOCABULARY.put("notAllowed", Collections.EMPTY_SET);
+ VOCABULARY.put("externalRef", externalAttrs);
+ VOCABULARY.put("grammar", Collections.EMPTY_SET);
+ VOCABULARY.put("param", elementAttrs);
+ VOCABULARY.put("except", Collections.EMPTY_SET);
+ VOCABULARY.put("div", Collections.EMPTY_SET);
+ VOCABULARY.put("include", externalAttrs);
+ VOCABULARY.put("start", startAttrs);
+ VOCABULARY.put("define", defineAttrs);
+ VOCABULARY.put("name", nsAttrs);
+ VOCABULARY.put("anyName", Collections.EMPTY_SET);
+ VOCABULARY.put("nsName", nsAttrs);
+
+ STRIPPED_ATTRIBUTES.add("name");
+ STRIPPED_ATTRIBUTES.add("type");
+ STRIPPED_ATTRIBUTES.add("combine");
+
+ PATTERN_ELEMENTS.add("element");
+ PATTERN_ELEMENTS.add("attribute");
+ PATTERN_ELEMENTS.add("group");
+ PATTERN_ELEMENTS.add("interleave");
+ PATTERN_ELEMENTS.add("choice");
+ PATTERN_ELEMENTS.add("optional");
+ PATTERN_ELEMENTS.add("zeroOrMore");
+ PATTERN_ELEMENTS.add("oneOrMore");
+ PATTERN_ELEMENTS.add("list");
+ PATTERN_ELEMENTS.add("mixed");
+ PATTERN_ELEMENTS.add("ref");
+ PATTERN_ELEMENTS.add("parentRef");
+ PATTERN_ELEMENTS.add("empty");
+ PATTERN_ELEMENTS.add("text");
+ PATTERN_ELEMENTS.add("value");
+ PATTERN_ELEMENTS.add("data");
+ PATTERN_ELEMENTS.add("notAllowed");
+ PATTERN_ELEMENTS.add("externalRef");
+ PATTERN_ELEMENTS.add("grammar");
+ }
+
+ private Set urls; // recursion checking
+ private int refCount; // creation of ref names
+ private Map datatypeLibraries;
+
+ /**
+ * Parse the specified document into a grammar.
+ */
+ synchronized Grammar parse(Document doc)
+ throws IOException
+ {
+ urls = new HashSet();
+ refCount = 1;
+
+ doc.normalizeDocument(); // Normalize XML document
+ transform(doc); // Apply transformation rules to provide simple syntax
+
+ // 4.18. grammar element
+ Element p = doc.getDocumentElement();
+ Element grammar =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "grammar");
+ Element start =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "start");
+ doc.removeChild(p);
+ doc.appendChild(grammar);
+ grammar.appendChild(start);
+ start.appendChild(p);
+ transformGrammar(grammar, p);
+ Element define = getNextSiblingElement(start);
+ while (define != null)
+ {
+ Element next = getNextSiblingElement(define);
+ String name = define.getAttribute("new-name");
+ if (name != null)
+ {
+ define.setAttribute("name", name);
+ define.removeAttribute("new-name");
+ }
+ else
+ grammar.removeChild(define); // unreferenced
+ define = next;
+ }
+
+ // 4.19. define and ref elements
+ Set allDefines = new HashSet(), reachableDefines = new HashSet();
+ getDefines(allDefines, grammar, grammar, false);
+ getDefines(reachableDefines, grammar, start, true);
+ allDefines.removeAll(reachableDefines);
+ for (Iterator i = allDefines.iterator(); i.hasNext(); )
+ {
+ // remove unreachable defines
+ Element d = (Element) i.next();
+ Node parent = d.getParentNode();
+ parent.removeChild(d);
+ }
+ // replace all elements that are not children of defines by refs to new
+ // defines
+ Set elements = new HashSet();
+ getElements(elements, grammar, grammar);
+ for (Iterator i = elements.iterator(); i.hasNext(); )
+ {
+ Element element = (Element) i.next();
+ Node parent = element.getParentNode();
+ if (!reachableDefines.contains(parent))
+ {
+ define =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "define");
+ Element ref =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "ref");
+ String name = createRefName();
+ define.setAttribute("name", name);
+ ref.setAttribute("name", name);
+ parent.insertBefore(ref, element);
+ define.appendChild(element);
+ grammar.appendChild(define);
+ reachableDefines.add(define);
+ }
+ }
+ // Get defines that don't have element children
+ for (Iterator i = reachableDefines.iterator(); i.hasNext(); )
+ {
+ Element d = (Element) i.next();
+ Element child = getFirstChildElement(d);
+ if (child != null && "element".equals(child.getLocalName()))
+ i.remove();
+ }
+ // Expand refs that refer to these defines
+ expandRefs(reachableDefines, grammar);
+ // Remove any defines that don't have element children
+ for (Iterator i = reachableDefines.iterator(); i.hasNext(); )
+ {
+ Element d = (Element) i.next();
+ Node parent = d.getParentNode();
+ parent.removeChild(d);
+ }
+
+ transform2(p); // Apply second stage transformation rules
+
+ Grammar ret = parseGrammar(grammar);
+ datatypeLibraries = null; // free datatype libraries cache
+ return ret;
+ }
+
+ private void getDefines(Set defines, Element grammar, Element node,
+ boolean followRefs)
+ {
+ String elementName = node.getLocalName();
+ if ("define".equals(elementName))
+ defines.add(node);
+ else if ("ref".equals(elementName) && followRefs)
+ {
+ String rname = node.getAttribute("name");
+ Element define = getFirstChildElement(grammar);
+ define = getNextSiblingElement(define);
+ while (define != null)
+ {
+ String dname = define.getAttribute("name");
+ if (rname.equals(dname))
+ {
+ getDefines(defines, grammar, node, followRefs);
+ break;
+ }
+ define = getNextSiblingElement(define);
+ }
+ }
+ for (Element child = getFirstChildElement(node); child != null;
+ child = getNextSiblingElement(child))
+ getDefines(defines, grammar, child, followRefs);
+ }
+
+ private void getElements(Set elements, Element grammar, Element node)
+ {
+ String elementName = node.getLocalName();
+ if ("element".equals(elementName))
+ elements.add(node);
+ for (Element child = getFirstChildElement(node); child != null;
+ child = getNextSiblingElement(child))
+ getElements(elements, grammar, child);
+ }
+
+ private void expandRefs(Set defines, Element node)
+ throws GrammarException
+ {
+ String elementName = node.getLocalName();
+ if ("ref".equals(elementName))
+ {
+ String rname = node.getAttribute("name");
+ for (Iterator i = defines.iterator(); i.hasNext(); )
+ {
+ Element define = (Element) i.next();
+ String dname = define.getAttribute("name");
+ if (rname.equals(dname))
+ {
+ Element child = getFirstChildElement(define);
+ forbidRefs(child, rname);
+ Element refChild = (Element) child.cloneNode(true);
+ Node parent = node.getParentNode();
+ parent.insertBefore(refChild, node);
+ parent.removeChild(node);
+ node = refChild;
+ break;
+ }
+ }
+ }
+ for (Element child = getFirstChildElement(node); child != null;
+ child = getNextSiblingElement(child))
+ expandRefs(defines, child);
+ }
+
+ private void forbidRefs(Element node, String name)
+ throws GrammarException
+ {
+ String elementName = node.getLocalName();
+ if ("ref".equals(elementName))
+ {
+ String rname = node.getAttribute("name");
+ if (name.equals(rname))
+ throw new GrammarException("cannot expand ref with name '" + name +
+ "' due to circularity");
+ }
+ for (Element child = getFirstChildElement(node); child != null;
+ child = getNextSiblingElement(child))
+ forbidRefs(child, name);
+ }
+
+ private void transform(Node node)
+ throws IOException
+ {
+ Node parent = node.getParentNode();
+ switch (node.getNodeType())
+ {
+ case Node.ELEMENT_NODE:
+ // 4.1 Annotations
+ String elementNs = node.getNamespaceURI();
+ String elementName = node.getLocalName();
+ if (!XMLConstants.RELAXNG_NS_URI.equals(elementNs) ||
+ !VOCABULARY.containsKey(elementName))
+ parent.removeChild(node);
+ else
+ {
+ Set allowedAttrs = (Set) VOCABULARY.get(elementName);
+ NamedNodeMap attrs = node.getAttributes();
+ int len = attrs.getLength();
+ for (int i = len - 1; i >= 0; i--)
+ {
+ Node attr = attrs.item(i);
+ String attrNs = attr.getNamespaceURI();
+ String attrName = attr.getLocalName();
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attrNs))
+ continue; // ignore namespace nodes
+ if (!(XMLConstants.RELAXNG_NS_URI.equals(attrNs) ||
+ attrNs == null) ||
+ !allowedAttrs.contains(attrName))
+ attrs.removeNamedItemNS(attrNs, attrName);
+ else
+ {
+ // 4.2 Whitespace
+ if (STRIPPED_ATTRIBUTES.contains(attrName))
+ attr.setNodeValue(attr.getNodeValue().trim());
+ // 4.3 datatypeLibrary attribute
+ else if ("datatypeLibrary".equals(attrName))
+ {
+ String dl = attr.getNodeValue();
+ attr.setNodeValue(escapeURL(dl));
+ }
+ // 4.5. href attribute
+ else if ("href".equals(attrName))
+ {
+ String href = attr.getNodeValue();
+ href = XMLParser.absolutize(node.getBaseURI(),
+ escapeURL(href));
+ attr.setNodeValue(href);
+ }
+ }
+ }
+ // 4.3 datatypeLibrary attribute
+ if ("data".equals(elementName) || "value".equals(elementName))
+ {
+ Element element = (Element) node;
+ String dl = element.getAttribute("datatypeLibrary");
+ if (dl == null)
+ {
+ Node p = parent;
+ while (dl == null && p != null &&
+ p.getNodeType() == Node.ELEMENT_NODE)
+ {
+ dl = ((Element) p)
+ .getAttribute("datatypeLibrary");
+ p = p.getParentNode();
+ }
+ if (dl == null)
+ dl = "";
+ element.setAttribute("datatypeLibrary", dl);
+ }
+ // 4.4. type attribute of value element
+ if ("value".equals(elementName))
+ {
+ String type = element.getAttribute("type");
+ if (type == null)
+ {
+ element.setAttribute("type", "token");
+ element.setAttribute("datatypeLibrary", "");
+ }
+ }
+ // 4.16. Constraints
+ // TODO validate type
+ }
+ // 4.6. externalRef element
+ else if ("externalRef".equals(elementName))
+ {
+ Element externalRef = (Element) node;
+ String href = externalRef.getAttribute("href");
+ // check for recursion
+ if (urls.contains(href))
+ throw new GrammarException("recursive href");
+ urls.add(href);
+ Element element = resolve(href);
+ String eNs = element.getNamespaceURI();
+ String eName = element.getLocalName();
+ if (!(XMLConstants.RELAXNG_NS_URI.equals(eNs) ||
+ eNs == null) ||
+ !PATTERN_ELEMENTS.contains(eName))
+ throw new GrammarException("externally referenced element " +
+ "is not a pattern");
+ transform(element);
+ urls.remove(href);
+ String ns = element.getAttribute("ns");
+ if (ns != null)
+ element.setAttribute("ns",
+ externalRef.getAttribute("ns"));
+ element = (Element) externalRef.getOwnerDocument()
+ .importNode(element, true);
+ parent.replaceChild(element, externalRef);
+ return;
+ }
+ // 4.7 include element
+ else if ("include".equals(elementName))
+ {
+ Element include = (Element) node;
+ String href = include.getAttribute("href");
+ // check for recursion
+ if (urls.contains(href))
+ throw new GrammarException("recursive href");
+ urls.add(href);
+ Element element = resolve(href);
+ String eNs = element.getNamespaceURI();
+ String eName = element.getLocalName();
+ if (!(XMLConstants.RELAXNG_NS_URI.equals(eNs) ||
+ eNs == null) ||
+ !"grammar".equals(eName))
+ throw new GrammarException("included element is not " +
+ "a grammar");
+
+ transform(element);
+ urls.remove(href);
+ // handle components
+ List includeComponents = getComponents(include);
+ List grammarComponents = getComponents(element);
+ for (Iterator i = includeComponents.iterator(); i.hasNext(); )
+ {
+ Element comp = (Element) i.next();
+ String compName = comp.getLocalName();
+ if ("start".equals(compName))
+ {
+ boolean found = false;
+ for (Iterator j = grammarComponents.iterator();
+ j.hasNext(); )
+ {
+ Element c2 = (Element) j.next();
+ if ("start".equals(c2.getLocalName()))
+ {
+ c2.getParentNode().removeChild(c2);
+ found = true;
+ }
+ }
+ if (!found)
+ throw new GrammarException("no start component in " +
+ "included grammar");
+ }
+ else if ("define".equals(compName))
+ {
+ String name = comp.getAttribute("name");
+ boolean found = false;
+ for (Iterator j = grammarComponents.iterator();
+ j.hasNext(); )
+ {
+ Element c2 = (Element) j.next();
+ if ("define".equals(c2.getLocalName()) &&
+ name.equals(c2.getAttribute("name")))
+ {
+ c2.getParentNode().removeChild(c2);
+ found = true;
+ }
+ }
+ if (!found)
+ throw new GrammarException("no define component " +
+ "with name '" + name +
+ "' in included grammar");
+ }
+ }
+ // transform to div element
+ Document doc = include.getOwnerDocument();
+ Element includeDiv =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "div");
+ Element grammarDiv =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "div");
+ // XXX copy include non-href attributes (none defined?)
+ element = (Element) doc.importNode(element, true);
+ Node ctx = element.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ grammarDiv.appendChild(ctx);
+ ctx = next;
+ }
+ includeDiv.appendChild(grammarDiv);
+ ctx = include.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ includeDiv.appendChild(ctx);
+ ctx = next;
+ }
+ parent.replaceChild(includeDiv, include);
+ transform(includeDiv);
+ return;
+ }
+ // 4.8. name attribute of element and attribute elements
+ else if ("attribute".equals(elementName) ||
+ "element".equals(elementName))
+ {
+ Element element = (Element) node;
+ String name = element.getAttribute("name");
+ if (name != null)
+ {
+ Document doc = element.getOwnerDocument();
+ Element n =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, "name");
+ n.appendChild(doc.createTextNode(name));
+ Node first = element.getFirstChild();
+ if (first != null)
+ element.insertBefore(n, first);
+ else
+ element.appendChild(n);
+ if ("attribute".equals(elementName))
+ {
+ String ns = element.getAttribute("ns");
+ if (ns != null)
+ {
+ n.setAttribute("ns", ns);
+ element.removeAttribute("ns");
+ }
+ }
+ element.removeAttribute("name");
+ }
+ // 4.12. Number of child elements
+ if ("attribute".equals(elementName))
+ {
+ if (getComponents(node).size() == 1)
+ {
+ Document doc = node.getOwnerDocument();
+ Element text =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "text");
+ node.appendChild(text);
+ }
+ }
+ else // element
+ {
+ if (node.getChildNodes().getLength() > 2)
+ {
+ // transform to 2 child elements
+ Document doc = node.getOwnerDocument();
+ Element child =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "group");
+ Node ctx = getFirstChildElement(node);
+ ctx = getNextSiblingElement(ctx); // skip 1
+ while (ctx != null)
+ {
+ Node next = getNextSiblingElement(ctx);
+ child.appendChild(ctx);
+ ctx = next;
+ }
+ node.appendChild(child);
+ }
+ }
+ }
+ // 4.11. div element
+ else if ("div".equals(elementName))
+ {
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ parent.insertBefore(ctx, node);
+ transform(ctx);
+ ctx = next;
+ }
+ parent.removeChild(node);
+ return;
+ }
+ else if ("mixed".equals(elementName))
+ {
+ // 4.12. Number of child elements
+ transformToOneChildElement(node, "group");
+ // 4.13. mixed element
+ Document doc = node.getOwnerDocument();
+ Node interleave =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "interleave");
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ interleave.appendChild(ctx);
+ ctx = next;
+ }
+ Node text =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "text");
+ interleave.appendChild(text);
+ parent.insertBefore(interleave, node);
+ parent.removeChild(node);
+ node = interleave;
+ }
+ else if ("optional".equals(elementName))
+ {
+ // 4.12. Number of child elements
+ transformToOneChildElement(node, "group");
+ // 4.14. optional element
+ Document doc = node.getOwnerDocument();
+ Node choice =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "choice");
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ choice.appendChild(ctx);
+ ctx = next;
+ }
+ Node empty =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "empty");
+ choice.appendChild(empty);
+ parent.insertBefore(choice, node);
+ parent.removeChild(node);
+ node = choice;
+ }
+ else if ("zeroOrMore".equals(elementName))
+ {
+ // 4.12. Number of child elements
+ transformToOneChildElement(node, "group");
+ // 4.15. zeroOrMore element
+ Document doc = node.getOwnerDocument();
+ Node choice =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "choice");
+ Node oneOrMore =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "oneOrMore");
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ oneOrMore.appendChild(ctx);
+ ctx = next;
+ }
+ Node empty =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "empty");
+ choice.appendChild(oneOrMore);
+ choice.appendChild(empty);
+ parent.insertBefore(choice, node);
+ parent.removeChild(node);
+ node = choice;
+ }
+ else if ("list".equals(elementName) ||
+ "oneOrMore".equals(elementName) ||
+ "define".equals(elementName))
+ {
+ // 4.12. Number of child elements
+ transformToOneChildElement(node, "group");
+ }
+ else if ("except".equals(elementName))
+ {
+ // 4.12. Number of child elements
+ transformToOneChildElement(node, "choice");
+ // 4.16. Constraints
+ String parentName = parent.getLocalName();
+ if ("anyName".equals(parentName))
+ forbidDescendants(node, Collections.singleton("anyName"));
+ else if ("nsName".equals(parentName))
+ {
+ Set names = new HashSet();
+ names.add("nsName");
+ names.add("anyName");
+ forbidDescendants(node, names);
+ }
+ }
+ else if ("choice".equals(elementName) ||
+ "group".equals(elementName) ||
+ "interleave".equals(elementName))
+ {
+ // 4.12. Number of child elements
+ Node ctx = getFirstChildElement(node);
+ Node next = getNextSiblingElement(ctx);
+ if (next == null)
+ {
+ // replace
+ parent.insertBefore(ctx, node);
+ parent.removeChild(node);
+ transform(ctx);
+ return;
+ }
+ else
+ {
+ // transform to 2 child elements
+ Node next2 = getNextSiblingElement(next);
+ if (next2 != null)
+ {
+ Document doc = node.getOwnerDocument();
+ Node child =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ elementName);
+ child.appendChild(ctx);
+ child.appendChild(next);
+ node.insertBefore(next2, child);
+ transform(node); // recurse
+ }
+ }
+ }
+ // 4.17. combine attribute
+ else if ("grammar".equals(elementName))
+ {
+ String combine = null;
+ List nodes = new LinkedList();
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ if ("start".equals(ctx.getLocalName()))
+ {
+ String c = ((Element) ctx).getAttribute("combine");
+ if (combine != null && !combine.equals(c))
+ throw new GrammarException("multiple start elements "+
+ "but no combine attribute");
+ combine = c;
+ nodes.add(ctx);
+ }
+ ctx = next;
+ }
+ if (!nodes.isEmpty())
+ combineNodes(node, combine, "start", nodes);
+ // defines
+ Map defines = new HashMap();
+ Map defineCombines = new HashMap();
+ ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ if ("define".equals(ctx.getLocalName()))
+ {
+ String name = ((Element) ctx).getAttribute("name");
+ combine = (String) defineCombines.get(name);
+ String c = ((Element) ctx).getAttribute("combine");
+ if (combine != null && !combine.equals(c))
+ throw new GrammarException("multiple define " +
+ "elements with name '"+
+ name + "' but no " +
+ "combine attribute");
+ defineCombines.put(name, c);
+ nodes = (List) defines.get(name);
+ if (nodes == null)
+ {
+ nodes = new LinkedList();
+ defines.put(name, nodes);
+ }
+ nodes.add(ctx);
+ }
+ ctx = next;
+ }
+ for (Iterator i = defines.keySet().iterator(); i.hasNext(); )
+ {
+ String name = (String) i.next();
+ combine = (String) defineCombines.get(name);
+ nodes = (List) defines.get(name);
+ if (!nodes.isEmpty())
+ combineNodes(node, combine, "define", nodes);
+ }
+ }
+ // 4.9. ns attribute
+ if ("name".equals(elementName) ||
+ "nsName".equals(elementName) ||
+ "value".equals(elementName))
+ {
+ Element element = (Element) node;
+ String ns = element.getAttribute("ns");
+ if (ns == null)
+ {
+ Node ctx = parent;
+ while (ns == null && ctx != null &&
+ ctx.getNodeType() == Node.ELEMENT_NODE)
+ {
+ ns = ((Element) ctx).getAttribute("ns");
+ ctx = ctx.getParentNode();
+ }
+ element.setAttribute("ns", (ns == null) ? "" : ns);
+ }
+ if ("name".equals(elementName))
+ {
+ // 4.10. QNames
+ String name = element.getTextContent();
+ int ci = name.indexOf(':');
+ if (ci != -1)
+ {
+ String prefix = name.substring(0, ci);
+ element.setTextContent(name.substring(ci + 1));
+ ns = element.lookupNamespaceURI(prefix);
+ element.setAttribute("ns", (ns == null) ? "" : ns);
+ }
+ // 4.16. Constraints
+ if (isDescendantOfFirstChildOfAttribute(element) &&
+ "".equals(element.getAttribute("ns")) &&
+ "xmlns".equals(element.getTextContent()))
+ throw new GrammarException("name cannot be xmlns");
+ }
+ else if ("nsName".equals(elementName))
+ {
+ // 4.16. Constraints
+ if (isDescendantOfFirstChildOfAttribute(element) &&
+ "http://www.w3.org/2000/xmlns"
+ .equals(element.getAttribute("ns")))
+ throw new GrammarException("nsName cannot be XMLNS URI");
+ }
+ }
+ }
+
+ break;
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ // 4.2 Whitespace
+ String parentName = parent.getLocalName();
+ if ("name".equals(parentName))
+ node.setNodeValue(node.getNodeValue().trim());
+ if (!"param".equals(parentName) &&
+ !"value".equals(parentName) &&
+ isWhitespace(node.getNodeValue()))
+ parent.removeChild(node);
+ break;
+ case Node.DOCUMENT_NODE:
+ break;
+ default:
+ parent.removeChild(node);
+ }
+ // Transform children
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ transform(ctx);
+ ctx = next;
+ }
+ }
+
+ /**
+ * Transforms the schema to place all defines under the top-level grammar
+ * element and replace all other grammar elements by their start child.
+ */
+ private void transformGrammar(Node grammar, Node node)
+ throws GrammarException
+ {
+ if (node.getNodeType() == Node.ELEMENT_NODE)
+ {
+ String elementName = node.getLocalName();
+ if ("grammar".equals(elementName))
+ {
+ handleRefs(grammar, node, node);
+ Node start = null;
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ String childName = ctx.getLocalName();
+ if ("define".equals(childName))
+ grammar.appendChild(ctx);
+ else if ("start".equals(childName))
+ start = ctx;
+ ctx = next;
+ }
+ if (start == null)
+ throw new GrammarException("no start element for grammar");
+ Node p = getFirstChildElement(start);
+ Node parent = node.getParentNode();
+ parent.insertBefore(p, node);
+ parent.removeChild(node);
+ node = p;
+ }
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ transformGrammar(grammar, ctx);
+ ctx = next;
+ }
+ }
+ }
+
+ /**
+ * Checks that all references in the specified grammar match a define in
+ * the grammar.
+ */
+ private void handleRefs(Node grammar1, Node grammar2, Node node)
+ throws GrammarException
+ {
+ if (node.getNodeType() == Node.ELEMENT_NODE)
+ {
+ String elementName = node.getLocalName();
+ if ("ref".equals(elementName) || "parentRef".equals(elementName))
+ {
+ Node grammar = grammar2;
+ if ("parentRef".equals(elementName))
+ grammar = grammar1;
+
+ String name = ((Element) node).getAttribute("name");
+ if (name != null)
+ throw new GrammarException("no name attribute on " +
+ elementName);
+ Node define = null;
+ for (Node ctx = grammar.getFirstChild();
+ define == null && ctx != null;
+ ctx = ctx.getNextSibling())
+ {
+ if ("define".equals(ctx.getLocalName()))
+ {
+ String dname = ((Element) ctx).getAttribute("name");
+ if (name.equals(dname))
+ define = ctx;
+ }
+ }
+ if (define == null)
+ throw new GrammarException("no define for '" + name + "'");
+ name = ((Element) define).getAttribute("new-name");
+ if (name == null)
+ {
+ name = createRefName();
+ ((Element) define).setAttribute("new-name", name);
+ }
+ if ("parentRef".equals(elementName))
+ {
+ Document doc = node.getOwnerDocument();
+ Node ref = doc.createElementNS(XMLConstants.RELAXNG_NS_URI,
+ "ref");
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ ref.appendChild(ctx);
+ ctx = next;
+ }
+ Node parent = node.getParentNode();
+ parent.insertBefore(ref, node);
+ parent.removeChild(node);
+ node = ref;
+ }
+ ((Element) node).setAttribute("name", name);
+ }
+ else if ("grammar".equals(elementName))
+ {
+ grammar1 = grammar2;
+ grammar2 = node;
+ }
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ handleRefs(grammar1, grammar2, ctx);
+ ctx = next;
+ }
+ }
+ }
+
+ private String createRefName()
+ {
+ return "ref" + Integer.toString(refCount++);
+ }
+
+ private void transform2(Node node)
+ throws GrammarException
+ {
+ Node parent = node.getParentNode();
+ if (node.getNodeType() == Node.ELEMENT_NODE)
+ {
+ String elementName = node.getLocalName();
+ // 4.20. notAllowed element
+ if ("notAllowed".equals(elementName))
+ {
+ String parentName = parent.getLocalName();
+ if ("attribute".equals(parentName) ||
+ "list".equals(parentName) ||
+ "group".equals(parentName) ||
+ "interleave".equals(parentName) ||
+ "oneOrMore".equals(parentName))
+ {
+ Node pp = parent.getParentNode();
+ pp.insertBefore(node, parent);
+ pp.removeChild(parent);
+ transform2(node); // apply recursively
+ return;
+ }
+ else if ("choice".equals(parentName))
+ {
+ Node p1 = getFirstChildElement(parent);
+ Node p2 = getNextSiblingElement(p1);
+ if (p1 == null || p2 == null)
+ throw new GrammarException("choice does not have two " +
+ "children");
+ String p1Name = p1.getLocalName();
+ String p2Name = p2.getLocalName();
+ Node pp = parent.getParentNode();
+ if ("notAllowed".equals(p1Name) &&
+ "notAllowed".equals(p2Name))
+ {
+ pp.insertBefore(p1, parent);
+ pp.removeChild(parent);
+ transform2(p1); //apply recursively
+ return;
+ }
+ else if ("notAllowed".equals(p1Name))
+ {
+ pp.insertBefore(p2, parent);
+ pp.removeChild(parent);
+ transform2(p2);
+ return;
+ }
+ else
+ {
+ pp.insertBefore(p1, parent);
+ pp.removeChild(parent);
+ transform2(p1);
+ return;
+ }
+ }
+ else if ("except".equals(parentName))
+ {
+ Node pp = parent.getParentNode();
+ pp.removeChild(parent);
+ return;
+ }
+ }
+ // 4.21. empty element
+ else if ("empty".equals(elementName))
+ {
+ String parentName = parent.getLocalName();
+ if ("group".equals(parentName) ||
+ "interleave".equals(parentName))
+ {
+ Node p1 = getFirstChildElement(parent);
+ Node p2 = getNextSiblingElement(p1);
+ if (p1 == null || p2 == null)
+ throw new GrammarException(parentName + " does not have " +
+ "two children");
+ String p1Name = p1.getLocalName();
+ String p2Name = p2.getLocalName();
+ Node pp = parent.getParentNode();
+ if ("empty".equals(p1Name) &&
+ "empty".equals(p2Name))
+ {
+ pp.insertBefore(p1, parent);
+ pp.removeChild(parent);
+ transform2(p1);
+ return;
+ }
+ else if ("empty".equals(p1Name))
+ {
+ pp.insertBefore(p2, parent);
+ pp.removeChild(parent);
+ transform2(p2);
+ return;
+ }
+ else
+ {
+ pp.insertBefore(p1, parent);
+ pp.removeChild(parent);
+ transform2(p1);
+ return;
+ }
+ }
+ else if ("choice".equals(parentName))
+ {
+ Node p1 = getFirstChildElement(parent);
+ Node p2 = getNextSiblingElement(p1);
+ if (p1 == null || p2 == null)
+ throw new GrammarException(parentName + " does not have " +
+ "two children");
+ String p1Name = p1.getLocalName();
+ String p2Name = p2.getLocalName();
+ Node pp = parent.getParentNode();
+ if ("empty".equals(p1Name) &&
+ "empty".equals(p2Name))
+ {
+ pp.insertBefore(p1, parent);
+ pp.removeChild(parent);
+ transform2(p1);
+ return;
+ }
+ }
+ else if ("oneOrMore".equals(parentName))
+ {
+ Node pp = parent.getParentNode();
+ pp.insertBefore(node, parent);
+ pp.removeChild(parent);
+ transform2(node);
+ return;
+ }
+ }
+ Node ctx = node.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ transform2(ctx);
+ ctx = next;
+ }
+ }
+ }
+
+ private static boolean isWhitespace(String text)
+ {
+ int len = text.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = text.charAt(i);
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
+ return false;
+ }
+ return true;
+ }
+
+ private static String escapeURL(String url)
+ {
+ try
+ {
+ return URLEncoder.encode(url, "UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ RuntimeException e2 = new RuntimeException("UTF-8 is unsupported");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ /**
+ * Resolve a URL to an element, as described in section 4.5.
+ */
+ private static Element resolve(String url)
+ throws IOException
+ {
+ try
+ {
+ URL u = new URL(url);
+ InputStream in = u.openStream();
+ DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
+ f.setNamespaceAware(true);
+ f.setCoalescing(true);
+ f.setExpandEntityReferences(true);
+ f.setIgnoringComments(true);
+ f.setIgnoringElementContentWhitespace(true);
+ DocumentBuilder b = f.newDocumentBuilder();
+ Document doc = b.parse(in, url);
+ in.close();
+ String fragment = u.getRef();
+ if (fragment != null)
+ return doc.getElementById(fragment);
+ return doc.getDocumentElement();
+ }
+ catch (SAXException e)
+ {
+ IOException e2 = new IOException("error parsing included element");
+ e2.initCause(e);
+ throw e2;
+ }
+ catch (ParserConfigurationException e)
+ {
+ IOException e2 = new IOException("error parsing included element");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ /**
+ * Returns the "components" of an element, as described in section 4.7.
+ */
+ private List getComponents(Node node)
+ {
+ List ret = new LinkedList();
+ for (Node ctx = node.getFirstChild(); ctx != null;
+ ctx = ctx.getNextSibling())
+ {
+ if (ctx.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+ String ns = ctx.getNamespaceURI();
+ if (ns != null && !ns.equals(XMLConstants.RELAXNG_NS_URI))
+ continue;
+ String name = ctx.getLocalName();
+ if ("div".equals(name))
+ ret.addAll(getComponents(ctx));
+ else if (VOCABULARY.containsKey(name))
+ ret.add(ctx);
+ }
+ return ret;
+ }
+
+ private static void transformToOneChildElement(Node node, String name)
+ {
+ if (node.getChildNodes().getLength() < 2)
+ return;
+ Document doc = node.getOwnerDocument();
+ Element child = doc.createElementNS(XMLConstants.RELAXNG_NS_URI, name);
+ Node ctx = getFirstChildElement(node);
+ while (ctx != null)
+ {
+ Node next = getNextSiblingElement(ctx);
+ child.appendChild(ctx);
+ ctx = next;
+ }
+ node.appendChild(child);
+ }
+
+ private static Element getFirstChildElement(Node node)
+ {
+ Node ctx = node.getFirstChild();
+ while (ctx != null && ctx.getNodeType() != Node.ELEMENT_NODE)
+ ctx = ctx.getNextSibling();
+ return (Element) ctx;
+ }
+
+ private static Element getNextSiblingElement(Node node)
+ {
+ Node ctx = node.getNextSibling();
+ while (ctx != null && ctx.getNodeType() != Node.ELEMENT_NODE)
+ ctx = ctx.getNextSibling();
+ return (Element) ctx;
+ }
+
+ private static void forbidDescendants(Node node, Set names)
+ throws GrammarException
+ {
+ for (Node ctx = node.getFirstChild(); ctx != null;
+ ctx = ctx.getNextSibling())
+ {
+ String ns = ctx.getNamespaceURI();
+ if (!XMLConstants.RELAXNG_NS_URI.equals(ns))
+ continue;
+ String name = ctx.getLocalName();
+ if (names.contains(name))
+ throw new GrammarException("name not allowed: " + name);
+ forbidDescendants(ctx, names);
+ }
+ }
+
+ private static boolean isDescendantOfFirstChildOfAttribute(Node node)
+ {
+ Node child = node;
+ Node parent = node.getParentNode();
+ while (parent != null && !"attribute".equals(parent.getLocalName()))
+ {
+ child = parent;
+ parent = child.getParentNode();
+ }
+ if (parent == null)
+ return false;
+ Node firstChild = getFirstChildElement(parent);
+ return firstChild == child;
+ }
+
+ private static void combineNodes(Node node, String combine, String name,
+ List nodes)
+ {
+ Document doc = node.getOwnerDocument();
+ Node child =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, name);
+ Node combineNode =
+ doc.createElementNS(XMLConstants.RELAXNG_NS_URI, combine);
+ child.appendChild(combineNode);
+ boolean inserted = false;
+ for (Iterator i = nodes.iterator(); i.hasNext(); )
+ {
+ Node startNode = (Node) i.next();
+ if (!inserted)
+ {
+ node.insertBefore(child, startNode);
+ inserted = true;
+ }
+ Node ctx = startNode.getFirstChild();
+ while (ctx != null)
+ {
+ Node next = ctx.getNextSibling();
+ combineNode.appendChild(ctx);
+ ctx = next;
+ }
+ node.removeChild(startNode);
+ }
+ }
+
+ Grammar parseGrammar(Element node)
+ throws GrammarException
+ {
+ checkName(node, "grammar");
+ Grammar grammar = new Grammar();
+ Element start = getFirstChildElement(node);
+ grammar.start = parsePattern(getFirstChildElement(start));
+ for (Element define = getNextSiblingElement(start); define != null;
+ define = getNextSiblingElement(define))
+ grammar.defines.add(parseDefine(define));
+ return grammar;
+ }
+
+ Define parseDefine(Element node)
+ throws GrammarException
+ {
+ checkName(node, "define");
+ Define define = new Define();
+ define.name = node.getAttribute("name");
+ define.element = parseElement(getFirstChildElement(node));
+ return define;
+ }
+
+ Pattern parseTop(Element node)
+ throws GrammarException
+ {
+ String name = node.getLocalName();
+ if ("notAllowed".equals(name))
+ return parseNotAllowed(node);
+ return parsePattern(node);
+ }
+
+ Pattern parsePattern(Element node)
+ throws GrammarException
+ {
+ String name = node.getLocalName();
+ if ("empty".equals(name))
+ return parseEmpty(node);
+ return parseNonEmptyPattern(node);
+ }
+
+ Pattern parseNonEmptyPattern(Element node)
+ throws GrammarException
+ {
+ String name = node.getLocalName();
+ if ("text".equals(name))
+ return parseText(node);
+ else if ("data".equals(name))
+ return parseData(node);
+ else if ("value".equals(name))
+ return parseValue(node);
+ else if ("list".equals(name))
+ return parseList(node);
+ else if ("attribute".equals(name))
+ return parseAttribute(node);
+ else if ("ref".equals(name))
+ return parseRef(node);
+ else if ("oneOrMore".equals(name))
+ return parseOneOrMore(node);
+ else if ("choice".equals(name))
+ return parseChoice(node);
+ else if ("group".equals(name))
+ return parseGroup(node);
+ else if ("interleave".equals(name))
+ return parseInterleave(node);
+ throw new GrammarException("invalid pattern: " + name);
+ }
+
+ ElementPattern parseElement(Element node)
+ throws GrammarException
+ {
+ checkName(node, "element");
+ ElementPattern element = new ElementPattern();
+ Element nameClass = getFirstChildElement(node);
+ element.nameClass = parseNameClass(nameClass);
+ element.pattern = parseTop(getNextSiblingElement(nameClass));
+ return element;
+ }
+
+ NotAllowedPattern parseNotAllowed(Element node)
+ throws GrammarException
+ {
+ checkName(node, "notAllowed");
+ return NotAllowedPattern.INSTANCE;
+ }
+
+ EmptyPattern parseEmpty(Element node)
+ throws GrammarException
+ {
+ checkName(node, "empty");
+ return EmptyPattern.INSTANCE;
+ }
+
+ TextPattern parseText(Element node)
+ throws GrammarException
+ {
+ checkName(node, "text");
+ return TextPattern.INSTANCE;
+ }
+
+ DataPattern parseData(Element node)
+ throws GrammarException
+ {
+ checkName(node, "data");
+ DataPattern data = new DataPattern();
+ DatatypeLibrary dl =
+ getDatatypeLibrary(node.getAttribute("datatypeLibrary"));
+ String type = node.getAttribute("type");
+ try
+ {
+ data.type = dl.createDatatype(type);
+ data.datatypeLibrary = dl;
+ }
+ catch (DatatypeException e)
+ {
+ GrammarException e2 = new GrammarException(type);
+ e2.initCause(e);
+ throw e2;
+ }
+ Element ctx = getFirstChildElement(node);
+ while (ctx != null)
+ {
+ Element next = getNextSiblingElement(ctx);
+ String name = ctx.getLocalName();
+ if ("param".equals(name))
+ data.params.add(parseParam(ctx));
+ else if ("except".equals(name) && next == null)
+ data.exceptPattern = parsePattern(getFirstChildElement(ctx));
+ else
+ throw new GrammarException("invalid element: " + name);
+ ctx = next;
+ }
+ return data;
+ }
+
+ Param parseParam(Element node)
+ throws GrammarException
+ {
+ checkName(node, "param");
+ Param param = new Param();
+ param.name = node.getAttribute("name");
+ param.value = node.getTextContent();
+ return param;
+ }
+
+ ValuePattern parseValue(Element node)
+ throws GrammarException
+ {
+ checkName(node, "value");
+ ValuePattern value = new ValuePattern();
+ DatatypeLibrary dl =
+ getDatatypeLibrary(node.getAttribute("datatypeLibrary"));
+ String type = node.getAttribute("type");
+ try
+ {
+ value.type = dl.createDatatype(type);
+ value.datatypeLibrary = dl;
+ }
+ catch (DatatypeException e)
+ {
+ GrammarException e2 = new GrammarException(type);
+ e2.initCause(e);
+ throw e2;
+ }
+ value.ns = node.getAttribute("ns");
+ value.value = node.getTextContent();
+ return value;
+ }
+
+ ListPattern parseList(Element node)
+ throws GrammarException
+ {
+ checkName(node, "list");
+ ListPattern list = new ListPattern();
+ list.pattern = parsePattern(getFirstChildElement(node));
+ return list;
+ }
+
+ AttributePattern parseAttribute(Element node)
+ throws GrammarException
+ {
+ checkName(node, "attribute");
+ AttributePattern attribute = new AttributePattern();
+ Element nameClass = getFirstChildElement(node);
+ attribute.nameClass = parseNameClass(nameClass);
+ attribute.pattern = parsePattern(getNextSiblingElement(nameClass));
+ return attribute;
+ }
+
+ RefPattern parseRef(Element node)
+ throws GrammarException
+ {
+ checkName(node, "ref");
+ RefPattern ref = new RefPattern();
+ ref.name = node.getAttribute("name");
+ return ref;
+ }
+
+ OneOrMorePattern parseOneOrMore(Element node)
+ throws GrammarException
+ {
+ checkName(node, "oneOrMore");
+ OneOrMorePattern oneOrMore = new OneOrMorePattern();
+ oneOrMore.pattern = parseNonEmptyPattern(getFirstChildElement(node));
+ return oneOrMore;
+ }
+
+ ChoicePattern parseChoice(Element node)
+ throws GrammarException
+ {
+ checkName(node, "choice");
+ ChoicePattern choice = new ChoicePattern();
+ Element p1 = getFirstChildElement(node);
+ Element p2 = getNextSiblingElement(p1);
+ choice.pattern1 = parsePattern(p1);
+ choice.pattern2 = parseNonEmptyPattern(p2);
+ return choice;
+ }
+
+ GroupPattern parseGroup(Element node)
+ throws GrammarException
+ {
+ checkName(node, "group");
+ GroupPattern group = new GroupPattern();
+ Element p1 = getFirstChildElement(node);
+ Element p2 = getNextSiblingElement(p1);
+ group.pattern1 = parseNonEmptyPattern(p1);
+ group.pattern2 = parseNonEmptyPattern(p2);
+ return group;
+ }
+
+ InterleavePattern parseInterleave(Element node)
+ throws GrammarException
+ {
+ checkName(node, "interleave");
+ InterleavePattern interleave = new InterleavePattern();
+ Element p1 = getFirstChildElement(node);
+ Element p2 = getNextSiblingElement(p1);
+ interleave.pattern1 = parseNonEmptyPattern(p1);
+ interleave.pattern2 = parseNonEmptyPattern(p2);
+ return interleave;
+ }
+
+ NameClass parseNameClass(Element node)
+ throws GrammarException
+ {
+ String name = node.getLocalName();
+ if ("anyName".equals(name))
+ return parseAnyName(node);
+ else if ("name".equals(name))
+ return parseName(node);
+ else if ("nsName".equals(name))
+ return parseNsName(node);
+ else if ("choice".equals(name))
+ return parseChoiceNameClass(node);
+ throw new GrammarException("invalid name class: " + name);
+ }
+
+ AnyNameNameClass parseAnyName(Element node)
+ throws GrammarException
+ {
+ checkName(node, "anyName");
+ AnyNameNameClass anyName = new AnyNameNameClass();
+ Element except = getFirstChildElement(node);
+ if (except != null) {
+ checkName(except, "except");
+ anyName.exceptNameClass = parseNameClass(getFirstChildElement(except));
+ }
+ return anyName;
+ }
+
+ NameNameClass parseName(Element node)
+ throws GrammarException
+ {
+ checkName(node, "name");
+ NameNameClass name = new NameNameClass();
+ name.ns = node.getAttribute("ns");
+ name.name = node.getTextContent();
+ return name;
+ }
+
+ NSNameNameClass parseNsName(Element node)
+ throws GrammarException
+ {
+ checkName(node, "nsName");
+ NSNameNameClass nsName = new NSNameNameClass();
+ nsName.ns = node.getAttribute("ns");
+ Element except = getFirstChildElement(node);
+ if (except != null) {
+ checkName(except, "except");
+ nsName.exceptNameClass = parseNameClass(getFirstChildElement(except));
+ }
+ return nsName;
+ }
+
+ ChoiceNameClass parseChoiceNameClass(Element node)
+ throws GrammarException
+ {
+ checkName(node, "choice");
+ ChoiceNameClass choice = new ChoiceNameClass();
+ Element c1 = getFirstChildElement(node);
+ Element c2 = getNextSiblingElement(c1);
+ choice.name1 = parseNameClass(c1);
+ choice.name2 = parseNameClass(c2);
+ return choice;
+ }
+
+ void checkName(Element node, String name)
+ throws GrammarException
+ {
+ if (!name.equals(node.getLocalName()))
+ throw new GrammarException("expecting " + name);
+ }
+
+ DatatypeLibrary getDatatypeLibrary(String uri)
+ throws GrammarException
+ {
+ if (datatypeLibraries == null)
+ datatypeLibraries = new HashMap();
+ DatatypeLibrary library = (DatatypeLibrary) datatypeLibraries.get(uri);
+ if (library == null)
+ {
+ library = new DatatypeLibraryLoader().createDatatypeLibrary(uri);
+ if (library == null)
+ throw new GrammarException("Datatype library not supported: " + uri);
+ datatypeLibraries.put(uri, library);
+ }
+ return library;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/Grammar.java b/libjava/classpath/gnu/xml/validation/relaxng/Grammar.java
new file mode 100644
index 00000000000..76eff4f3a10
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/Grammar.java
@@ -0,0 +1,70 @@
+/* Grammar.java --
+ 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.xml.validation.relaxng;
+
+import java.util.LinkedList;
+import java.util.List;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+import javax.xml.validation.ValidatorHandler;
+
+/**
+ * A RELAX NG grammar.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class Grammar
+ extends Schema
+{
+
+ Pattern start;
+ List defines = new LinkedList();
+
+ public Validator newValidator()
+ {
+ return new GrammarValidator(this);
+ }
+
+ public ValidatorHandler newValidatorHandler()
+ {
+ // TODO
+ return null;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/stream/EndEntityImpl.java b/libjava/classpath/gnu/xml/validation/relaxng/GrammarException.java
index fd36ee267d3..71d03de97c6 100644
--- a/libjava/classpath/gnu/xml/stream/EndEntityImpl.java
+++ b/libjava/classpath/gnu/xml/validation/relaxng/GrammarException.java
@@ -1,5 +1,5 @@
-/* EndEntityImpl.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+/* GrammarException.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,46 +35,22 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.xml.stream;
+package gnu.xml.validation.relaxng;
import java.io.IOException;
-import java.io.Writer;
-import javax.xml.stream.Location;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.EndEntity;
/**
- * An end-entity event.
+ * Exception parsing a grammar.
*
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
*/
-public class EndEntityImpl
- extends XMLEventImpl
- implements EndEntity
+class GrammarException
+ extends IOException
{
- protected final String name;
-
- protected EndEntityImpl(Location location, String name)
- {
- super(location);
- this.name = name;
- }
-
- public int getEventType()
- {
- return END_ENTITY;
- }
-
- public String getName()
- {
- return name;
- }
-
- public void writeAsEncodedUnicode(Writer writer)
- throws XMLStreamException
+ GrammarException(String message)
{
+ super(message);
}
}
-
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/GrammarValidator.java b/libjava/classpath/gnu/xml/validation/relaxng/GrammarValidator.java
new file mode 100644
index 00000000000..d811aeec94e
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/GrammarValidator.java
@@ -0,0 +1,97 @@
+/* GrammarValidator.java --
+ 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.xml.validation.relaxng;
+
+import java.io.IOException;
+import javax.xml.transform.Source;
+import javax.xml.transform.Result;
+import javax.xml.validation.Validator;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * RELAX NG validator.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class GrammarValidator
+ extends Validator
+{
+
+ final Grammar grammar;
+ ErrorHandler errorHandler;
+ LSResourceResolver resourceResolver;
+
+ GrammarValidator(Grammar grammar)
+ {
+ this.grammar = grammar;
+ }
+
+ public ErrorHandler getErrorHandler()
+ {
+ return errorHandler;
+ }
+
+ public void setErrorHandler(ErrorHandler errorHandler)
+ {
+ this.errorHandler = errorHandler;
+ }
+
+ public LSResourceResolver getResourceResolver()
+ {
+ return resourceResolver;
+ }
+
+ public void setResourceResolver(LSResourceResolver resourceResolver)
+ {
+ this.resourceResolver = resourceResolver;
+ }
+
+ public void reset()
+ {
+ // TODO
+ }
+
+ public void validate(Source source, Result result)
+ throws SAXException, IOException
+ {
+ // TODO
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/GroupPattern.java b/libjava/classpath/gnu/xml/validation/relaxng/GroupPattern.java
new file mode 100644
index 00000000000..b01090efa4b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/GroupPattern.java
@@ -0,0 +1,53 @@
+/* GroupPattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG group element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class GroupPattern
+ extends Pattern
+{
+
+ Pattern pattern1;
+ Pattern pattern2;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/InterleavePattern.java b/libjava/classpath/gnu/xml/validation/relaxng/InterleavePattern.java
new file mode 100644
index 00000000000..aa7c28e5e8a
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/InterleavePattern.java
@@ -0,0 +1,53 @@
+/* InterleavePattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG interleave element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class InterleavePattern
+ extends Pattern
+{
+
+ Pattern pattern1;
+ Pattern pattern2;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/ListPattern.java b/libjava/classpath/gnu/xml/validation/relaxng/ListPattern.java
new file mode 100644
index 00000000000..4c0393ae572
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/ListPattern.java
@@ -0,0 +1,52 @@
+/* ListPattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG list element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class ListPattern
+ extends Pattern
+{
+
+ Pattern pattern;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/NSNameNameClass.java b/libjava/classpath/gnu/xml/validation/relaxng/NSNameNameClass.java
new file mode 100644
index 00000000000..f485e997016
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/NSNameNameClass.java
@@ -0,0 +1,61 @@
+/* NSNameNameClass.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG nsName element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class NSNameNameClass
+ extends NameClass
+{
+
+ String ns;
+ NameClass exceptNameClass;
+
+ boolean matchesName(String uri, String localName)
+ {
+ if (!ns.equals(uri))
+ return false;
+ return (exceptNameClass == null) ? true :
+ !exceptNameClass.matchesName(uri, localName);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/NameClass.java b/libjava/classpath/gnu/xml/validation/relaxng/NameClass.java
new file mode 100644
index 00000000000..2a3dc83e510
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/NameClass.java
@@ -0,0 +1,50 @@
+/* NameClass.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG name class.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+abstract class NameClass
+{
+
+ abstract boolean matchesName(String uri, String localName);
+
+}
diff --git a/libjava/classpath/gnu/java/security/provider/MD2withRSA.java b/libjava/classpath/gnu/xml/validation/relaxng/NameNameClass.java
index a72ae5588dc..d5a0c5f0403 100644
--- a/libjava/classpath/gnu/java/security/provider/MD2withRSA.java
+++ b/libjava/classpath/gnu/xml/validation/relaxng/NameNameClass.java
@@ -1,5 +1,5 @@
-/* MD2withRSA.java -- MD2 with RSA encryption signatures.
- Copyright (C) 2004 Free Software Foundation, Inc.
+/* NameNameClass.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,20 +35,26 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
+package gnu.xml.validation.relaxng;
-package gnu.java.security.provider;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-public class MD2withRSA extends RSA
+/**
+ * A RELAX NG name element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class NameNameClass
+ extends NameClass
{
- // Constructor.
- // -------------------------------------------------------------------------
+ String ns;
+ String name;
- public MD2withRSA() throws NoSuchAlgorithmException
+ boolean matchesName(String uri, String localName)
{
- super(MessageDigest.getInstance("MD2"), DIGEST_ALGORITHM.getChild(2));
+ if (!ns.equals(uri))
+ return false;
+ return name.equals(localName);
}
+
}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/NotAllowedPattern.java b/libjava/classpath/gnu/xml/validation/relaxng/NotAllowedPattern.java
new file mode 100644
index 00000000000..8263a4573fa
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/NotAllowedPattern.java
@@ -0,0 +1,53 @@
+/* NotAllowedPattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG notAllowed element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class NotAllowedPattern
+ extends Pattern
+{
+
+ static final NotAllowedPattern INSTANCE = new NotAllowedPattern();
+
+}
+
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/OneOrMorePattern.java b/libjava/classpath/gnu/xml/validation/relaxng/OneOrMorePattern.java
new file mode 100644
index 00000000000..99864d72a59
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/OneOrMorePattern.java
@@ -0,0 +1,52 @@
+/* OneOrMorePattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG oneOrMore element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class OneOrMorePattern
+ extends Pattern
+{
+
+ Pattern pattern;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/Param.java b/libjava/classpath/gnu/xml/validation/relaxng/Param.java
new file mode 100644
index 00000000000..246ad20b7c5
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/Param.java
@@ -0,0 +1,52 @@
+/* Param.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG param element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class Param
+{
+
+ String name;
+ String value;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/Pattern.java b/libjava/classpath/gnu/xml/validation/relaxng/Pattern.java
new file mode 100644
index 00000000000..3bf9a9919b9
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/Pattern.java
@@ -0,0 +1,48 @@
+/* Pattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG pattern.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+abstract class Pattern
+{
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/RELAXNGSchemaFactory.java b/libjava/classpath/gnu/xml/validation/relaxng/RELAXNGSchemaFactory.java
new file mode 100644
index 00000000000..e1eb758ea68
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/RELAXNGSchemaFactory.java
@@ -0,0 +1,151 @@
+/* RelaxNGSchemaFactory.java --
+ 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.xml.validation.relaxng;
+
+import java.io.IOException;
+import java.net.URL;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Schema factory for RELAX NG grammars.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class RELAXNGSchemaFactory
+ extends SchemaFactory
+{
+
+ LSResourceResolver resourceResolver;
+
+ public LSResourceResolver getResourceResolver()
+ {
+ return resourceResolver;
+ }
+
+ public void setResourceResolver(LSResourceResolver resourceResolver)
+ {
+ this.resourceResolver = resourceResolver;
+ }
+
+ public boolean isSchemaLanguageSupported(String schemaLanguage)
+ {
+ return XMLConstants.RELAXNG_NS_URI.equals(schemaLanguage);
+ }
+
+ public Schema newSchema()
+ throws SAXException
+ {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+
+ public Schema newSchema(Source[] schemata)
+ throws SAXException
+ {
+ if (schemata == null || schemata.length != 1)
+ throw new IllegalArgumentException("must specify one source");
+ // TODO multiple schemata
+ // TODO compact syntax
+ try
+ {
+ Document doc = getDocument(schemata[0]);
+ FullSyntaxBuilder builder = new FullSyntaxBuilder();
+ return builder.parse(doc);
+ }
+ catch (IOException e)
+ {
+ SAXException e2 = new SAXException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ private static Document getDocument(Source source)
+ throws SAXException, IOException
+ {
+ if (source instanceof DOMSource)
+ {
+ Node node = ((DOMSource) source).getNode();
+ if (node != null && node instanceof Document)
+ return (Document) node;
+ }
+ String url = source.getSystemId();
+ try
+ {
+ InputSource input = new InputSource(url);
+ if (source instanceof StreamSource)
+ {
+ StreamSource streamSource = (StreamSource) source;
+ input.setByteStream(streamSource.getInputStream());
+ input.setCharacterStream(streamSource.getReader());
+ }
+ if (input.getByteStream() == null &&
+ input.getCharacterStream() == null &&
+ url != null)
+ input.setByteStream(new URL(url).openStream());
+ DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
+ f.setNamespaceAware(true);
+ f.setCoalescing(true);
+ f.setExpandEntityReferences(true);
+ f.setIgnoringComments(true);
+ f.setIgnoringElementContentWhitespace(true);
+ DocumentBuilder b = f.newDocumentBuilder();
+ return b.parse(input);
+ }
+ catch (ParserConfigurationException e)
+ {
+ SAXException e2 = new SAXException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/RefPattern.java b/libjava/classpath/gnu/xml/validation/relaxng/RefPattern.java
new file mode 100644
index 00000000000..d7de09542da
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/RefPattern.java
@@ -0,0 +1,52 @@
+/* RefPattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG ref element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class RefPattern
+ extends Pattern
+{
+
+ String name;
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/TextPattern.java b/libjava/classpath/gnu/xml/validation/relaxng/TextPattern.java
new file mode 100644
index 00000000000..06af3c34ad9
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/TextPattern.java
@@ -0,0 +1,52 @@
+/* TextPattern.java --
+ 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.xml.validation.relaxng;
+
+/**
+ * A RELAX NG text element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class TextPattern
+ extends Pattern
+{
+
+ static final TextPattern INSTANCE = new TextPattern();
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/relaxng/ValuePattern.java b/libjava/classpath/gnu/xml/validation/relaxng/ValuePattern.java
new file mode 100644
index 00000000000..81260b0caf1
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/relaxng/ValuePattern.java
@@ -0,0 +1,58 @@
+/* ValuePattern.java --
+ 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.xml.validation.relaxng;
+
+import org.relaxng.datatype.Datatype;
+import org.relaxng.datatype.DatatypeLibrary;
+
+/**
+ * A RELAX NG value element.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class ValuePattern
+ extends Pattern
+{
+
+ DatatypeLibrary datatypeLibrary;
+ Datatype type;
+ String ns;
+ String value;
+
+}
+
diff --git a/libjava/classpath/gnu/java/security/provider/SHA1withRSA.java b/libjava/classpath/gnu/xml/validation/xmlschema/AnyAttribute.java
index 0e63fdeeb52..df90dc626ab 100644
--- a/libjava/classpath/gnu/java/security/provider/SHA1withRSA.java
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/AnyAttribute.java
@@ -1,5 +1,5 @@
-/* SHA1withRSA.java -- SHA-1 with RSA encryption signatures.
- Copyright (C) 2004 Free Software Foundation, Inc.
+/* AnyAttribute.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,27 +35,33 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
+package gnu.xml.validation.xmlschema;
-package gnu.java.security.provider;
+import gnu.xml.validation.datatype.Annotation;
-import gnu.java.security.OID;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-public class SHA1withRSA extends RSA
+/**
+ * An attribute wildcard.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class AnyAttribute
{
- // Constant.
- // -------------------------------------------------------------------------
+ static final int STRICT = 0;
+ static final int LAX = 1;
+ static final int SKIP = 2;
- private static final OID SHA1 = new OID("1.3.14.3.2.26");
+ final String namespace;
- // Constructor.
- // -------------------------------------------------------------------------
+ final int processContents;
- public SHA1withRSA() throws NoSuchAlgorithmException
+ Annotation annotation;
+
+ AnyAttribute(String namespace, int processContents)
{
- super(MessageDigest.getInstance("SHA-160"), SHA1);
+ this.namespace = namespace;
+ this.processContents = processContents;
}
+
}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/AttributeDeclaration.java b/libjava/classpath/gnu/xml/validation/xmlschema/AttributeDeclaration.java
new file mode 100644
index 00000000000..98b322bee58
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/AttributeDeclaration.java
@@ -0,0 +1,99 @@
+/* AttributeDeclaration.java --
+ 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.xml.validation.xmlschema;
+
+import gnu.xml.validation.datatype.Annotation;
+import gnu.xml.validation.datatype.SimpleType;
+import javax.xml.namespace.QName;
+
+/**
+ * An XML Schema attribute declaration schema component.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class AttributeDeclaration
+{
+
+ static final int NONE = 0;
+ static final int DEFAULT = 1;
+ static final int FIXED = 2;
+
+ /**
+ * The scope of this attribute declaration (global or local).
+ */
+ final boolean scope;
+
+ /**
+ * The constraint type.
+ * One of NONE, DEFAULT, FIXED.
+ */
+ final int type;
+
+ /**
+ * The value constraint.
+ */
+ final String value;
+
+ /**
+ * The name of the attribute to which this declaration refers.
+ */
+ final QName name;
+
+ /**
+ * The type definition corresponding to this attribute.
+ */
+ final SimpleType datatype;
+
+ /**
+ * The annotation associated with this attribute declaration, if any.
+ */
+ final Annotation annotation;
+
+ AttributeDeclaration(boolean scope, int type, String value, QName name,
+ SimpleType datatype, Annotation annotation)
+ {
+ this.scope = scope;
+ this.type = type;
+ this.value = value;
+ this.name = name;
+ this.datatype = datatype;
+ this.annotation = annotation;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/AttributeUse.java b/libjava/classpath/gnu/xml/validation/xmlschema/AttributeUse.java
new file mode 100644
index 00000000000..f8bb11b911c
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/AttributeUse.java
@@ -0,0 +1,79 @@
+/* AttributeUse.java --
+ 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.xml.validation.xmlschema;
+
+/**
+ * An XML Schema attribute use schema component.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class AttributeUse
+{
+
+ /**
+ * Whether the attribute is required.
+ */
+ final boolean required;
+
+ /**
+ * The constraint type.
+ * One of NONE, DEFAULT, FIXED.
+ */
+ final int type;
+
+ /**
+ * The value constraint.
+ */
+ final String value;
+
+ /**
+ * The name of the attribute to which this declaration refers.
+ */
+ final AttributeDeclaration declaration;
+
+ AttributeUse(boolean required, int type, String value,
+ AttributeDeclaration declaration)
+ {
+ this.required = required;
+ this.type = type;
+ this.value = value;
+ this.declaration = declaration;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/ComplexType.java b/libjava/classpath/gnu/xml/validation/xmlschema/ComplexType.java
new file mode 100644
index 00000000000..2c7acb10a18
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/ComplexType.java
@@ -0,0 +1,102 @@
+/* ComplexType.java --
+ 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.xml.validation.xmlschema;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+import javax.xml.namespace.QName;
+import gnu.xml.validation.datatype.Type;
+
+/**
+ * A complex type definition.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class ComplexType
+ extends Type
+{
+
+ /**
+ * Either a simple type definition or a complex type definition.
+ */
+ QName baseType;
+
+ /**
+ * Either EXTENSION or RESTRICTION.
+ */
+ int derivationMethod;
+
+ /**
+ * A subset of {EXTENSION, RESTRICTION}.
+ */
+ final int finality;
+
+ final boolean isAbstract;
+
+ Set attributeUses;
+
+ AnyAttribute attributeWildcard;
+
+ /**
+ * One of EMPTY, SIMPLE, MIXED, or ELEMENT_ONLY.
+ */
+ int contentType;
+
+ /**
+ * A simple type definition or a Particle.
+ */
+ Object contentModel;
+
+ final int prohibitedSubstitutions;
+
+ Set annotations;
+
+ ComplexType(QName name,
+ boolean isAbstract,
+ int prohibitedSubstitutions,
+ int finality)
+ {
+ super(name);
+ this.isAbstract = isAbstract;
+ this.prohibitedSubstitutions = prohibitedSubstitutions;
+ this.finality = finality;
+ attributeUses = new LinkedHashSet();
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/ElementDeclaration.java b/libjava/classpath/gnu/xml/validation/xmlschema/ElementDeclaration.java
new file mode 100644
index 00000000000..d41f5e536e1
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/ElementDeclaration.java
@@ -0,0 +1,125 @@
+/* ElementDeclaration.java --
+ 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.xml.validation.xmlschema;
+
+import gnu.xml.validation.datatype.Annotation;
+import gnu.xml.validation.datatype.Type;
+import javax.xml.namespace.QName;
+
+/**
+ * An XML Schema element declaration schema component.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class ElementDeclaration
+{
+
+ /**
+ * The name of the element to which this declaration refers.
+ */
+ final QName name;
+
+ /**
+ * The type definition corresponding to this element.
+ */
+ Type datatype;
+
+ /**
+ * The scope of this schema component.
+ * One of GLOBAL, LOCAL, or ABSENT.
+ */
+ final int scope;
+
+ /**
+ * If scope is LOCAL, the parent element definition.
+ */
+ final ElementDeclaration parent;
+
+ /**
+ * The constraint type.
+ * One of NONE, DEFAULT, FIXED.
+ */
+ final int type;
+
+ /**
+ * The value constraint.
+ */
+ final String value;
+
+ final boolean nillable;
+
+ // TODO identity-constraint definitions
+
+ final QName substitutionGroup;
+
+ final int substitutionGroupExclusions;
+
+ final int disallowedSubstitutions;
+
+ final boolean isAbstract;
+
+ /**
+ * The annotation associated with this attribute declaration, if any.
+ */
+ Annotation annotation;
+
+ ElementDeclaration(QName name,
+ Type datatype,
+ int scope, ElementDeclaration parent,
+ int type, String value,
+ boolean nillable,
+ QName substitutionGroup,
+ int substitutionGroupExclusions,
+ int disallowedSubstitutions,
+ boolean isAbstract)
+ {
+ this.name = name;
+ this.datatype = datatype;
+ this.scope = scope;
+ this.parent = parent;
+ this.type = type;
+ this.value = value;
+ this.nillable = nillable;
+ this.substitutionGroup = substitutionGroup;
+ this.substitutionGroupExclusions = substitutionGroupExclusions;
+ this.disallowedSubstitutions = disallowedSubstitutions;
+ this.isAbstract = isAbstract;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/java/security/provider/MD4withRSA.java b/libjava/classpath/gnu/xml/validation/xmlschema/Particle.java
index 76a6a1ad033..995c4ff09cf 100644
--- a/libjava/classpath/gnu/java/security/provider/MD4withRSA.java
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/Particle.java
@@ -1,5 +1,5 @@
-/* MD4withRSA.java -- MD4 with RSA encryption signatures.
- Copyright (C) 2004 Free Software Foundation, Inc.
+/* Particle.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,20 +35,27 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
+package gnu.xml.validation.xmlschema;
-package gnu.java.security.provider;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-public class MD4withRSA extends RSA
+/**
+ * Container for element content.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class Particle
{
- // Constructor.
- // -------------------------------------------------------------------------
+ final Integer minOccurs;
+ final Integer maxOccurs;
- public MD4withRSA() throws NoSuchAlgorithmException
+ final Object term;
+
+ Particle(Integer minOccurs, Integer maxOccurs, Object term)
{
- super(MessageDigest.getInstance("MD4"), DIGEST_ALGORITHM.getChild(4));
+ this.minOccurs = minOccurs;
+ this.maxOccurs = maxOccurs;
+ this.term = term;
}
+
}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/ValidationException.java b/libjava/classpath/gnu/xml/validation/xmlschema/ValidationException.java
new file mode 100644
index 00000000000..f2d68430982
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/ValidationException.java
@@ -0,0 +1,58 @@
+/* ValidationException.java --
+ 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.xml.validation.xmlschema;
+
+import org.xml.sax.Locator;
+import org.xml.sax.SAXParseException;
+
+/**
+ * An XML Schema validation rule violation.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class ValidationException
+ extends SAXParseException
+{
+
+ ValidationException(String message, Locator locator)
+ {
+ super(message, locator);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchema.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchema.java
new file mode 100644
index 00000000000..647cbdeffd0
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchema.java
@@ -0,0 +1,134 @@
+/* XMLSchema.java --
+ 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.xml.validation.xmlschema;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+import javax.xml.validation.ValidatorHandler;
+
+/**
+ * An XML Schema schema.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class XMLSchema
+ extends Schema
+{
+
+ static final int FINAL_NONE = 0x00;
+ static final int FINAL_EXTENSION = 0x01;
+ static final int FINAL_RESTRICTION = 0x02;
+ static final int FINAL_LIST = 0x04;
+ static final int FINAL_UNION = 0x08;
+ static final int FINAL_ALL = 0x0f;
+
+ static final int BLOCK_NONE = 0x00;
+ static final int BLOCK_EXTENSION = 0x01;
+ static final int BLOCK_RESTRICTION = 0x02;
+ static final int BLOCK_SUBSTITUTION = 0x04;
+ static final int BLOCK_ALL = 0x07;
+
+ static final int GLOBAL = 0x00;
+ static final int LOCAL = 0x01;
+ static final int ABSENT = 0x02;
+
+ static final int CONSTRAINT_NONE = 0x00;
+ static final int CONSTRAINT_DEFAULT = 0x01;
+ static final int CONSTRAINT_FIXED = 0x02;
+
+ static final int CONTENT_EMPTY = 0x00;
+ static final int CONTENT_SIMPLE = 0x01;
+ static final int CONTENT_MIXED = 0x02;
+ static final int CONTENT_ELEMENT_ONLY = 0x03;
+
+ final String targetNamespace;
+ final String version;
+ final int finalDefault;
+ final int blockDefault;
+ final boolean attributeFormQualified;
+ final boolean elementFormQualified;
+
+ /**
+ * The element declarations in this schema.
+ */
+ final Map elementDeclarations;
+
+ /**
+ * The attribute declarations in this schema.
+ */
+ final Map attributeDeclarations;
+
+ /**
+ * The type declarations in this schema.
+ */
+ final Map types;
+
+ XMLSchema(String targetNamespace, String version,
+ int finalDefault, int blockDefault,
+ boolean attributeFormQualified,
+ boolean elementFormQualified)
+ {
+ this.targetNamespace = targetNamespace;
+ this.version = version;
+ this.finalDefault = finalDefault;
+ this.blockDefault = blockDefault;
+ this.attributeFormQualified = attributeFormQualified;
+ this.elementFormQualified = elementFormQualified;
+ elementDeclarations = new LinkedHashMap();
+ attributeDeclarations = new LinkedHashMap();
+ types = new LinkedHashMap();
+ }
+
+ public Validator newValidator()
+ {
+ // TODO
+ //return new XMLSchemaValidator(this);
+ return null;
+ }
+
+ public ValidatorHandler newValidatorHandler()
+ {
+ // TODO
+ //return new XMLSchemaValidatorHandler(this);
+ return null;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaAttributeTypeInfo.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaAttributeTypeInfo.java
new file mode 100644
index 00000000000..758bc94cd95
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaAttributeTypeInfo.java
@@ -0,0 +1,100 @@
+/* XMLSchemaAttributeTypeInfo.java --
+ 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.xml.validation.xmlschema;
+
+import org.w3c.dom.TypeInfo;
+import gnu.xml.validation.datatype.SimpleType;
+
+/**
+ * Attribute type information provided by validation against an XML Schema.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class XMLSchemaAttributeTypeInfo
+ extends XMLSchemaTypeInfo
+{
+
+ final XMLSchema schema;
+ final AttributeDeclaration decl;
+ final SimpleType type;
+ boolean id;
+ final boolean specified;
+
+ XMLSchemaAttributeTypeInfo(XMLSchema schema, AttributeDeclaration decl,
+ boolean specified)
+ {
+ this.schema = schema;
+ this.decl = decl;
+ this.specified = specified;
+ type = (decl == null) ? null : decl.datatype;
+ }
+
+ public String getTypeName()
+ {
+ if (type == null)
+ {
+ return "CDATA";
+ }
+ return type.name.getLocalPart();
+ }
+
+ public String getTypeNamespace()
+ {
+ if (type == null)
+ {
+ return "";
+ }
+ return type.name.getNamespaceURI();
+ }
+
+ public boolean isDerivedFrom(String typeNamespace, String typeName,
+ int derivationMethod)
+ {
+ if (type == null)
+ {
+ return false;
+ }
+ else
+ {
+ return simpleTypeIsDerivedFrom(type, typeNamespace, typeName,
+ derivationMethod);
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaBuilder.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaBuilder.java
new file mode 100644
index 00000000000..ddf91409d2b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaBuilder.java
@@ -0,0 +1,844 @@
+/* XMLSchemaBuilder.java --
+ 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.xml.validation.xmlschema;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.DatatypeLibrary;
+import org.relaxng.datatype.helpers.DatatypeLibraryLoader;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import gnu.xml.validation.datatype.Annotation;
+import gnu.xml.validation.datatype.AtomicSimpleType;
+import gnu.xml.validation.datatype.ListSimpleType;
+import gnu.xml.validation.datatype.SimpleType;
+import gnu.xml.validation.datatype.Type;
+import gnu.xml.validation.datatype.UnionSimpleType;
+
+/**
+ * Parses an XML Schema DOM tree, constructing a compiled internal
+ * representation.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class XMLSchemaBuilder
+{
+
+ XMLSchema schema;
+ final DatatypeLibrary typeLibrary;
+
+ XMLSchemaBuilder()
+ {
+ final String ns = XMLConstants.W3C_XML_SCHEMA_NS_URI;
+ typeLibrary = new DatatypeLibraryLoader().createDatatypeLibrary(ns);
+ }
+
+ void parseSchema(Node node)
+ throws DatatypeException
+ {
+ String uri = node.getNamespaceURI();
+ String name = node.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ node.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("schema".equals(name))
+ {
+ NamedNodeMap attrs = node.getAttributes();
+ String targetNamespace = getAttribute(attrs, "targetNamespace");
+ String version = getAttribute(attrs, "version");
+ String fd = getAttribute(attrs, "finalDefault");
+ int finalDefault = parseFullDerivationSet(fd);
+ String bd = getAttribute(attrs, "blockDefault");
+ int blockDefault = parseBlockSet(bd);
+ String afd = getAttribute(attrs, "attributeFormDefault");
+ boolean attributeFormQualified = "qualified".equals(afd);
+ String efd = getAttribute(attrs, "elementFormDefault");
+ boolean elementFormQualified = "qualified".equals(efd);
+ schema = new XMLSchema(targetNamespace, version,
+ finalDefault, blockDefault,
+ attributeFormQualified,
+ elementFormQualified);
+ for (Node child = node.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ parseTopLevelElement(child);
+ }
+ return;
+ }
+ }
+ // TODO throw schema exception
+ }
+
+ void parseTopLevelElement(Node node)
+ throws DatatypeException
+ {
+ String uri = node.getNamespaceURI();
+ String name = node.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ node.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("element".equals(name))
+ {
+ ElementDeclaration ed =
+ (ElementDeclaration) parseElement(node, null);
+ schema.elementDeclarations.put(ed.name, ed);
+ // TODO
+ }
+ else if ("attribute".equals(name))
+ {
+ AttributeDeclaration ad =
+ (AttributeDeclaration) parseAttribute(node, true);
+ schema.attributeDeclarations.put(ad.name, ad);
+ // TODO
+ }
+ else if ("type".equals(name))
+ {
+ // TODO
+ }
+ else if ("group".equals(name))
+ {
+ // TODO
+ }
+ else if ("attributeGroup".equals(name))
+ {
+ // TODO
+ }
+ else if ("notation".equals(name))
+ {
+ // TODO
+ }
+ else if ("identityConstraint".equals(name))
+ {
+ // TODO
+ }
+ }
+ // TODO throw schema exception
+ }
+
+ Object parseAttribute(Node node, boolean scope)
+ throws DatatypeException
+ {
+ NamedNodeMap attrs = node.getAttributes();
+ String def = getAttribute(attrs, "default");
+ String fixed = getAttribute(attrs, "fixed");
+ int constraintType = AttributeDeclaration.NONE;
+ String constraintValue = null;
+ if (def != null)
+ {
+ constraintType = AttributeDeclaration.DEFAULT;
+ constraintValue = def;
+ }
+ else if (fixed != null)
+ {
+ constraintType = AttributeDeclaration.FIXED;
+ constraintValue = fixed;
+ }
+ // TODO form = (qualified | unqualified)
+ String attrName = getAttribute(attrs, "name");
+ String attrNamespace = getAttribute(attrs, "targetNamespace");
+ String ref = getAttribute(attrs, "ref");
+ String use = getAttribute(attrs, "use");
+ String type = getAttribute(attrs, "type");
+ SimpleType datatype = (type == null) ? null :
+ parseSimpleType(asQName(type, node));
+ Annotation annotation = null;
+ for (Node child = node.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ String uri = child.getNamespaceURI();
+ String name = child.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ child.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("annotation".equals(name))
+ {
+ annotation = parseAnnotation(child);
+ }
+ else if ("simpleType".equals(name))
+ {
+ datatype = parseSimpleType(child);
+ }
+ else
+ {
+ // TODO throw schema exception
+ }
+ }
+ }
+ if (scope)
+ {
+ return new AttributeDeclaration(scope,
+ constraintType,
+ constraintValue,
+ new QName(attrNamespace, attrName),
+ datatype,
+ annotation);
+ }
+ else
+ {
+ boolean required = "required".equals(use);
+ // TODO ref
+ AttributeDeclaration decl = (ref == null) ?
+ new AttributeDeclaration(scope,
+ AttributeDeclaration.NONE,
+ null,
+ new QName(attrNamespace, attrName),
+ datatype,
+ annotation) :
+ /*schema.getAttributeDeclaration(ref)*/ null;
+ return new AttributeUse(required,
+ constraintType,
+ constraintValue,
+ decl);
+ }
+ }
+
+ int parseFullDerivationSet(String value)
+ {
+ int ret = XMLSchema.FINAL_NONE;
+ if ("#all".equals(value))
+ {
+ ret = XMLSchema.FINAL_ALL;
+ }
+ else
+ {
+ StringTokenizer st = new StringTokenizer(value, " ");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if ("extension".equals(token))
+ {
+ ret |= XMLSchema.FINAL_EXTENSION;
+ }
+ else if ("restriction".equals(token))
+ {
+ ret |= XMLSchema.FINAL_RESTRICTION;
+ }
+ else if ("list".equals(token))
+ {
+ ret |= XMLSchema.FINAL_LIST;
+ }
+ else if ("union".equals(token))
+ {
+ ret |= XMLSchema.FINAL_UNION;
+ }
+ }
+ }
+ return ret;
+ }
+
+ int parseSimpleTypeDerivationSet(String value)
+ {
+ int ret = XMLSchema.FINAL_NONE;
+ if ("#all".equals(value))
+ {
+ ret = XMLSchema.FINAL_LIST |
+ XMLSchema.FINAL_UNION |
+ XMLSchema.FINAL_RESTRICTION;
+ }
+ else
+ {
+ StringTokenizer st = new StringTokenizer(value, " ");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if ("list".equals(token))
+ {
+ ret |= XMLSchema.FINAL_LIST;
+ }
+ else if ("union".equals(token))
+ {
+ ret |= XMLSchema.FINAL_UNION;
+ }
+ else if ("restriction".equals(token))
+ {
+ ret |= XMLSchema.FINAL_RESTRICTION;
+ }
+ }
+ }
+ return ret;
+ }
+
+ int parseComplexTypeDerivationSet(String value)
+ {
+ int ret = XMLSchema.FINAL_NONE;
+ if ("#all".equals(value))
+ {
+ ret = XMLSchema.FINAL_EXTENSION | XMLSchema.FINAL_RESTRICTION;
+ }
+ else
+ {
+ StringTokenizer st = new StringTokenizer(value, " ");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if ("extension".equals(token))
+ {
+ ret |= XMLSchema.FINAL_EXTENSION;
+ }
+ else if ("restriction".equals(token))
+ {
+ ret |= XMLSchema.FINAL_RESTRICTION;
+ }
+ }
+ }
+ return ret;
+ }
+
+ int parseBlockSet(String value)
+ {
+ int ret = XMLSchema.BLOCK_NONE;
+ if ("#all".equals(value))
+ {
+ ret = XMLSchema.BLOCK_ALL;
+ }
+ else
+ {
+ StringTokenizer st = new StringTokenizer(value, " ");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if ("extension".equals(token))
+ {
+ ret |= XMLSchema.BLOCK_EXTENSION;
+ }
+ else if ("restriction".equals(token))
+ {
+ ret |= XMLSchema.BLOCK_RESTRICTION;
+ }
+ else if ("substitution".equals(token))
+ {
+ ret |= XMLSchema.BLOCK_SUBSTITUTION;
+ }
+ }
+ }
+ return ret;
+ }
+
+ int parseComplexTypeBlockSet(String value)
+ {
+ int ret = XMLSchema.BLOCK_NONE;
+ if ("#all".equals(value))
+ {
+ ret = XMLSchema.BLOCK_EXTENSION | XMLSchema.BLOCK_RESTRICTION;
+ }
+ else
+ {
+ StringTokenizer st = new StringTokenizer(value, " ");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if ("extension".equals(token))
+ {
+ ret |= XMLSchema.BLOCK_EXTENSION;
+ }
+ else if ("restriction".equals(token))
+ {
+ ret |= XMLSchema.BLOCK_RESTRICTION;
+ }
+ }
+ }
+ return ret;
+ }
+
+ Object parseElement(Node node, ElementDeclaration parent)
+ throws DatatypeException
+ {
+ NamedNodeMap attrs = node.getAttributes();
+ Integer minOccurs = null;
+ Integer maxOccurs = null;
+ Node parentNode = node.getParentNode();
+ boolean notTopLevel = !"schema".equals(parentNode.getLocalName());
+ if (notTopLevel)
+ {
+ String ref = getAttribute(attrs, "ref");
+ if (ref != null)
+ {
+ minOccurs = getOccurrence(getAttribute(attrs, "minOccurs"));
+ maxOccurs = getOccurrence(getAttribute(attrs, "maxOccurs"));
+ // TODO resolve top-level element declaration
+ ElementDeclaration ad = null;
+ return new Particle(minOccurs, maxOccurs, ad);
+ }
+ }
+ String elementName = getAttribute(attrs, "name");
+ String elementNamespace = getAttribute(attrs, "targetNamespace");
+ String type = getAttribute(attrs, "type");
+ Type datatype = (type != null) ?
+ parseSimpleType(asQName(type, node)) : null;
+ int scope = (parent == null) ?
+ XMLSchema.GLOBAL :
+ XMLSchema.LOCAL;
+ String def = getAttribute(attrs, "default");
+ String fixed = getAttribute(attrs, "fixed");
+ int constraintType = AttributeDeclaration.NONE;
+ String constraintValue = null;
+ if (def != null)
+ {
+ constraintType = AttributeDeclaration.DEFAULT;
+ constraintValue = def;
+ }
+ else if (fixed != null)
+ {
+ constraintType = AttributeDeclaration.FIXED;
+ constraintValue = fixed;
+ }
+ String sg = getAttribute(attrs, "substitutionGroup");
+ QName substitutionGroup = QName.valueOf(sg);
+ String sgPrefix = substitutionGroup.getPrefix();
+ if (sgPrefix != null && !"".equals(sgPrefix))
+ {
+ String sgName = substitutionGroup.getLocalPart();
+ String sgNamespace = node.lookupNamespaceURI(sgPrefix);
+ substitutionGroup = new QName(sgNamespace, sgName);
+ }
+
+ String block = getAttribute(attrs, "block");
+ int substitutionGroupExclusions = (block == null) ?
+ schema.blockDefault :
+ parseBlockSet(block);
+ String final_ = getAttribute(attrs, "final");
+ int disallowedSubstitutions = (final_ == null) ?
+ schema.finalDefault :
+ parseFullDerivationSet(final_);
+
+ boolean nillable = "true".equals(getAttribute(attrs, "nillable"));
+ boolean isAbstract = "true".equals(getAttribute(attrs, "abstract"));
+
+ if (notTopLevel)
+ {
+ minOccurs = getOccurrence(getAttribute(attrs, "minOccurs"));
+ maxOccurs = getOccurrence(getAttribute(attrs, "maxOccurs"));
+ String form = getAttribute(attrs, "form");
+ if (form != null)
+ {
+ if ("qualified".equals(form))
+ {
+ elementNamespace = schema.targetNamespace;
+ }
+ }
+ else if (schema.elementFormQualified)
+ {
+ elementNamespace = schema.targetNamespace;
+ }
+ }
+ ElementDeclaration ed =
+ new ElementDeclaration(new QName(elementNamespace, elementName),
+ datatype,
+ scope, parent,
+ constraintType, constraintValue,
+ nillable,
+ substitutionGroup,
+ substitutionGroupExclusions,
+ disallowedSubstitutions,
+ isAbstract);
+
+ for (Node child = node.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ String uri = child.getNamespaceURI();
+ String name = child.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ child.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("annotation".equals(name))
+ {
+ ed.annotation = parseAnnotation(child);
+ }
+ else if ("simpleType".equals(name) && datatype == null)
+ {
+ ed.datatype = parseSimpleType(child);
+ }
+ else if ("complexType".equals(name) && datatype == null)
+ {
+ ed.datatype = parseComplexType(child, ed);
+ }
+ else
+ {
+ // throw schema exception
+ }
+ }
+ }
+
+ if (notTopLevel)
+ {
+ return new Particle(minOccurs, maxOccurs, ed);
+ }
+ else
+ {
+ return ed;
+ }
+ }
+
+ Integer getOccurrence(String value)
+ {
+ if (value == null)
+ {
+ return new Integer(1);
+ }
+ else if ("unbounded".equals(value))
+ {
+ return null;
+ }
+ else
+ {
+ return new Integer(value);
+ }
+ }
+
+ SimpleType parseSimpleType(QName typeName)
+ throws DatatypeException
+ {
+ SimpleType type = (SimpleType) schema.types.get(typeName);
+ if (!XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(typeName.getNamespaceURI()))
+ return null;
+ String localName = typeName.getLocalPart();
+ return (SimpleType) typeLibrary.createDatatype(localName);
+ }
+
+ SimpleType parseSimpleType(Node simpleType)
+ throws DatatypeException
+ {
+ NamedNodeMap attrs = simpleType.getAttributes();
+ String typeFinal = getAttribute(attrs, "final");
+ if (typeFinal == null)
+ {
+ Node schema = simpleType.getParentNode();
+ while (schema != null && !"schema".equals(schema.getLocalName()))
+ {
+ schema = schema.getParentNode();
+ }
+ if (schema != null)
+ {
+ NamedNodeMap schemaAttrs = schema.getAttributes();
+ typeFinal = getAttribute(schemaAttrs, "finalDefault");
+ }
+ }
+ int typeFinality = parseSimpleTypeDerivationSet(typeFinal);
+ QName typeName = asQName(getAttribute(attrs, "name"), simpleType);
+ int variety = 0;
+ Set facets = new LinkedHashSet();
+ int fundamentalFacets = 0; // TODO
+ SimpleType baseType = null; // TODO
+ Annotation annotation = null;
+ // TODO use DatatypeBuilder
+ for (Node child = simpleType.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ String uri = child.getNamespaceURI();
+ String name = child.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ child.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("annotation".equals(name))
+ {
+ annotation = parseAnnotation(child);
+ }
+ else if ("restriction".equals(name))
+ {
+ // TODO
+ }
+ else if ("list".equals(name))
+ {
+ variety = SimpleType.LIST;
+ // TODO
+ }
+ else if ("union".equals(name))
+ {
+ variety = SimpleType.UNION;
+ // TODO
+ }
+ }
+ }
+ return new SimpleType(typeName, variety, facets, fundamentalFacets,
+ baseType, annotation);
+ }
+
+ Type parseComplexType(Node complexType, ElementDeclaration parent)
+ throws DatatypeException
+ {
+ NamedNodeMap attrs = complexType.getAttributes();
+ QName typeName = asQName(getAttribute(attrs, "name"), complexType);
+ boolean isAbstract = "true".equals(getAttribute(attrs, "abstract"));
+ String block = getAttribute(attrs, "block");
+ int prohibitedSubstitutions = (block == null) ?
+ schema.blockDefault :
+ parseComplexTypeBlockSet(block);
+ String final_ = getAttribute(attrs, "final");
+ int finality = (final_ == null) ?
+ schema.finalDefault :
+ parseComplexTypeDerivationSet(final_);
+ ComplexType type = new ComplexType(typeName, isAbstract,
+ prohibitedSubstitutions, finality);
+ boolean mixed = "true".equals(getAttribute(attrs, "mixed"));
+ for (Node child = complexType.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ String uri = child.getNamespaceURI();
+ String name = child.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ child.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("simpleContent".equals(name))
+ {
+ parseSimpleContent(child, type);
+ }
+ }
+ }
+ if (mixed)
+ {
+ type.contentType = XMLSchema.CONTENT_MIXED;
+ }
+ return type;
+ }
+
+ void parseSimpleContent(Node simpleContent, ComplexType type)
+ throws DatatypeException
+ {
+ for (Node child = simpleContent.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ String uri = child.getNamespaceURI();
+ String name = child.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ child.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("annotation".equals(name))
+ {
+ type.annotations.add(parseAnnotation(child));
+ }
+ else if ("restriction".equals(name))
+ {
+ type.derivationMethod = XMLSchema.FINAL_RESTRICTION;
+ parseRestriction(child, type);
+ }
+ else if ("extension".equals(name))
+ {
+ type.derivationMethod = XMLSchema.FINAL_EXTENSION;
+ parseExtension(child, type);
+ }
+ }
+ }
+ }
+
+ void parseRestriction(Node restriction, ComplexType type)
+ throws DatatypeException
+ {
+ NamedNodeMap attrs = restriction.getAttributes();
+ String base = getAttribute(attrs, "base");
+ QName baseType = asQName(base, restriction);
+ SimpleType simpleType = null;
+ for (Node child = restriction.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ String uri = child.getNamespaceURI();
+ String name = child.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ child.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("annotation".equals(name))
+ {
+ type.annotations.add(parseAnnotation(child));
+ }
+ else if ("simpleType".equals(name))
+ {
+ type.contentType = XMLSchema.CONTENT_SIMPLE;
+ simpleType = parseSimpleType(child);
+ }
+ else if ("minExclusive".equals(name))
+ {
+ }
+ else if ("minInclusive".equals(name))
+ {
+ }
+ else if ("maxExclusive".equals(name))
+ {
+ }
+ else if ("maxInclusive".equals(name))
+ {
+ }
+ else if ("totalDigits".equals(name))
+ {
+ }
+ else if ("fractionDigits".equals(name))
+ {
+ }
+ else if ("length".equals(name))
+ {
+ }
+ else if ("minLength".equals(name))
+ {
+ }
+ else if ("maxLength".equals(name))
+ {
+ }
+ else if ("enumeration".equals(name))
+ {
+ }
+ else if ("whiteSpace".equals(name))
+ {
+ }
+ else if ("pattern".equals(name))
+ {
+ }
+ else if ("attribute".equals(name))
+ {
+ AttributeUse use =
+ (AttributeUse) parseAttribute(child, false);
+ schema.attributeDeclarations.put(use.declaration.name,
+ use.declaration);
+ type.attributeUses.add(use);
+ }
+ else if ("attributeGroup".equals(name))
+ {
+ NamedNodeMap agAttrs = child.getAttributes();
+ String ref = getAttribute(agAttrs, "ref");
+ QName ag = asQName(ref, child);
+ type.attributeUses.add(ag);
+ }
+ else if ("anyAttribute".equals(name))
+ {
+ type.attributeWildcard = parseAnyAttribute(child);
+ }
+ }
+ }
+ }
+
+ void parseExtension(Node extension, ComplexType type)
+ throws DatatypeException
+ {
+ NamedNodeMap attrs = extension.getAttributes();
+ String base = getAttribute(attrs, "base");
+ QName baseType = asQName(base, extension);
+ for (Node child = extension.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ String uri = child.getNamespaceURI();
+ String name = child.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ child.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("annotation".equals(name))
+ {
+ type.annotations.add(parseAnnotation(child));
+ }
+ else if ("attribute".equals(name))
+ {
+ AttributeUse use =
+ (AttributeUse) parseAttribute(child, false);
+ schema.attributeDeclarations.put(use.declaration.name,
+ use.declaration);
+ type.attributeUses.add(use);
+ }
+ else if ("attributeGroup".equals(name))
+ {
+ NamedNodeMap agAttrs = child.getAttributes();
+ String ref = getAttribute(agAttrs, "ref");
+ QName ag = asQName(ref, child);
+ type.attributeUses.add(ag);
+ }
+ else if ("anyAttribute".equals(name))
+ {
+ type.attributeWildcard = parseAnyAttribute(child);
+ }
+ }
+ }
+ }
+
+ AnyAttribute parseAnyAttribute(Node node)
+ {
+ NamedNodeMap attrs = node.getAttributes();
+ String namespace = getAttribute(attrs, "namespace");
+ String pc = getAttribute(attrs, "processContents");
+ int processContents = AnyAttribute.STRICT;
+ if ("lax".equals(pc))
+ {
+ processContents = AnyAttribute.LAX;
+ }
+ else if ("skip".equals(pc))
+ {
+ processContents = AnyAttribute.SKIP;
+ }
+ AnyAttribute ret = new AnyAttribute(namespace, processContents);
+ for (Node child = node.getFirstChild(); child != null;
+ child = child.getNextSibling())
+ {
+ String uri = child.getNamespaceURI();
+ String name = child.getLocalName();
+ if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri) &&
+ child.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if ("annotation".equals(name))
+ {
+ ret.annotation = parseAnnotation(child);
+ }
+ }
+ }
+ return ret;
+ }
+
+ Annotation parseAnnotation(Node node)
+ {
+ // TODO
+ return null;
+ }
+
+ private static String getAttribute(NamedNodeMap attrs, String name)
+ {
+ Node attr = attrs.getNamedItem(name);
+ return (attr == null) ? null : attr.getNodeValue();
+ }
+
+ private static QName asQName(String text, Node resolver)
+ {
+ QName name = QName.valueOf(text);
+ String prefix = name.getPrefix();
+ if (prefix != null && prefix.length() > 0)
+ {
+ String uri = resolver.lookupNamespaceURI(prefix);
+ name = new QName(uri, name.getLocalPart());
+ }
+ return name;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaElementTypeInfo.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaElementTypeInfo.java
new file mode 100644
index 00000000000..98a5fb75983
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaElementTypeInfo.java
@@ -0,0 +1,93 @@
+/* XMLSchemaElementTypeInfo.java --
+ 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.xml.validation.xmlschema;
+
+import org.w3c.dom.TypeInfo;
+import gnu.xml.validation.datatype.SimpleType;
+import gnu.xml.validation.datatype.Type;
+
+/**
+ * Element type information provided by validation against an XML Schema.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class XMLSchemaElementTypeInfo
+ extends XMLSchemaTypeInfo
+{
+
+ final XMLSchema schema;
+ final ElementDeclaration decl;
+ final Type type;
+ boolean nil;
+
+ XMLSchemaElementTypeInfo(XMLSchema schema, ElementDeclaration decl,
+ Type type)
+ {
+ this.schema = schema;
+ this.decl = decl;
+ this.type = type;
+ }
+
+ public String getTypeName()
+ {
+ return type.name.getLocalPart();
+ }
+
+ public String getTypeNamespace()
+ {
+ return type.name.getNamespaceURI();
+ }
+
+ public boolean isDerivedFrom(String typeNamespace, String typeName,
+ int derivationMethod)
+ {
+ if (type instanceof SimpleType)
+ {
+ SimpleType simpleType = (SimpleType) type;
+ return simpleTypeIsDerivedFrom(simpleType, typeNamespace, typeName,
+ derivationMethod);
+ }
+ else
+ {
+ // TODO
+ return false;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaSchemaFactory.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaSchemaFactory.java
new file mode 100644
index 00000000000..b37ae543154
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaSchemaFactory.java
@@ -0,0 +1,159 @@
+/* XMLSchemaSchemaFactory.java --
+ 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.xml.validation.xmlschema;
+
+import java.io.IOException;
+import java.net.URL;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import org.relaxng.datatype.DatatypeException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Schema factory for W3C XML Schema schemata.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLSchemaSchemaFactory
+ extends SchemaFactory
+{
+
+ LSResourceResolver resourceResolver;
+
+ public LSResourceResolver getResourceResolver()
+ {
+ return resourceResolver;
+ }
+
+ public void setResourceResolver(LSResourceResolver resourceResolver)
+ {
+ this.resourceResolver = resourceResolver;
+ }
+
+ public boolean isSchemaLanguageSupported(String schemaLanguage)
+ {
+ return XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(schemaLanguage);
+ }
+
+ public Schema newSchema()
+ throws SAXException
+ {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+
+ public Schema newSchema(Source[] schemata)
+ throws SAXException
+ {
+ if (schemata == null || schemata.length != 1)
+ throw new IllegalArgumentException("must specify one source");
+ // TODO multiple sources
+ try
+ {
+ Document doc = getDocument(schemata[0]);
+ XMLSchemaBuilder builder = new XMLSchemaBuilder();
+ builder.parseSchema(doc);
+ return builder.schema;
+ }
+ catch (IOException e)
+ {
+ SAXException e2 = new SAXException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ catch (DatatypeException e)
+ {
+ SAXException e2 = new SAXException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ private static Document getDocument(Source source)
+ throws SAXException, IOException
+ {
+ if (source instanceof DOMSource)
+ {
+ Node node = ((DOMSource) source).getNode();
+ if (node != null && node instanceof Document)
+ return (Document) node;
+ }
+ String url = source.getSystemId();
+ try
+ {
+ InputSource input = new InputSource(url);
+ if (source instanceof StreamSource)
+ {
+ StreamSource streamSource = (StreamSource) source;
+ input.setByteStream(streamSource.getInputStream());
+ input.setCharacterStream(streamSource.getReader());
+ }
+ if (input.getByteStream() == null &&
+ input.getCharacterStream() == null &&
+ url != null)
+ input.setByteStream(new URL(url).openStream());
+ DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
+ f.setNamespaceAware(true);
+ f.setCoalescing(true);
+ f.setExpandEntityReferences(true);
+ f.setIgnoringComments(true);
+ f.setIgnoringElementContentWhitespace(true);
+ DocumentBuilder b = f.newDocumentBuilder();
+ return b.parse(input);
+ }
+ catch (ParserConfigurationException e)
+ {
+ SAXException e2 = new SAXException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaTypeInfo.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaTypeInfo.java
new file mode 100644
index 00000000000..60cc25fc42b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaTypeInfo.java
@@ -0,0 +1,77 @@
+/* XMLSchemaTypeInfo.java --
+ 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.xml.validation.xmlschema;
+
+import org.w3c.dom.TypeInfo;
+import gnu.xml.validation.datatype.SimpleType;
+
+/**
+ * Abstract superclass providing simple type derivation.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+abstract class XMLSchemaTypeInfo
+ implements TypeInfo
+{
+
+ protected boolean simpleTypeIsDerivedFrom(SimpleType simpleType,
+ String typeNamespace,
+ String typeName,
+ int derivationMethod)
+ {
+ switch (derivationMethod)
+ {
+ case TypeInfo.DERIVATION_RESTRICTION:
+ SimpleType baseType = simpleType.baseType;
+ while (baseType != null)
+ {
+ if (baseType.name.getNamespaceURI().equals(typeNamespace) &&
+ baseType.name.getLocalPart().equals(typeName))
+ {
+ return true;
+ }
+ baseType = baseType.baseType;
+ }
+ break;
+ // TODO other methods
+ }
+ return false;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaTypeInfoProvider.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaTypeInfoProvider.java
new file mode 100644
index 00000000000..9b20c0c8db9
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaTypeInfoProvider.java
@@ -0,0 +1,82 @@
+/* XMLSchemaTypeInfoProvider.java --
+ 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.xml.validation.xmlschema;
+
+import javax.xml.validation.TypeInfoProvider;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * TypeInfo provider for XML Schema validator handler.
+ * This simply delegates to the handler. It wouldn't be required if
+ * TypeInfoProvider were an interface instead of an abstract class.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class XMLSchemaTypeInfoProvider
+ extends TypeInfoProvider
+{
+
+ final XMLSchemaValidatorHandler handler;
+
+ XMLSchemaTypeInfoProvider(XMLSchemaValidatorHandler handler)
+ {
+ this.handler = handler;
+ }
+
+ public TypeInfo getElementTypeInfo()
+ {
+ return handler.getElementTypeInfo();
+ }
+
+ public TypeInfo getAttributeTypeInfo(int index)
+ {
+ return handler.getAttributeTypeInfo(index);
+ }
+
+ public boolean isIdAttribute(int index)
+ {
+ return handler.isIdAttribute(index);
+ }
+
+ public boolean isSpecified(int index)
+ {
+ return handler.isSpecified(index);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaValidator.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaValidator.java
new file mode 100644
index 00000000000..056babf64b5
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaValidator.java
@@ -0,0 +1,98 @@
+/* XMLSchemaValidator.java --
+ 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.xml.validation.xmlschema;
+
+import java.io.IOException;
+import javax.xml.validation.Validator;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * JAXP validator for an XML Schema.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class XMLSchemaValidator
+ extends Validator
+{
+
+ final XMLSchema schema;
+
+ ErrorHandler errorHandler;
+ LSResourceResolver resourceResolver;
+
+ XMLSchemaValidator(XMLSchema schema)
+ {
+ this.schema = schema;
+ }
+
+ public void reset()
+ {
+ }
+
+ public void validate(Source source, Result result)
+ throws SAXException, IOException
+ {
+ // TODO
+ }
+
+ public ErrorHandler getErrorHandler()
+ {
+ return errorHandler;
+ }
+
+ public void setErrorHandler(ErrorHandler errorHandler)
+ {
+ this.errorHandler = errorHandler;
+ }
+
+ public LSResourceResolver getResourceResolver()
+ {
+ return resourceResolver;
+ }
+
+ public void setResourceResolver(LSResourceResolver resourceResolver)
+ {
+ this.resourceResolver = resourceResolver;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaValidatorHandler.java b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaValidatorHandler.java
new file mode 100644
index 00000000000..9e6d8e9a9cb
--- /dev/null
+++ b/libjava/classpath/gnu/xml/validation/xmlschema/XMLSchemaValidatorHandler.java
@@ -0,0 +1,394 @@
+/* XMLSchemaValidatorHandler.java --
+ 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.xml.validation.xmlschema;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.validation.TypeInfoProvider;
+import javax.xml.validation.ValidatorHandler;
+import org.relaxng.datatype.DatatypeException;
+import org.relaxng.datatype.DatatypeLibrary;
+import org.relaxng.datatype.helpers.DatatypeLibraryLoader;
+import org.w3c.dom.TypeInfo;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.Attributes2Impl;
+import org.xml.sax.helpers.NamespaceSupport;
+import gnu.xml.validation.datatype.SimpleType;
+import gnu.xml.validation.datatype.Type;
+
+/**
+ * Streaming validator.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+final class XMLSchemaValidatorHandler
+ extends ValidatorHandler
+{
+
+ final XMLSchema schema;
+ final TypeInfoProvider typeInfoProvider;
+ final NamespaceSupport namespaceSupport;
+ final DatatypeLibrary typeLibrary;
+ Locator loc;
+ ContentHandler contentHandler;
+ ErrorHandler errorHandler;
+ LSResourceResolver resourceResolver;
+ final LinkedList context; // element context
+ final ArrayList attributes; // attribute context;
+
+ XMLSchemaValidatorHandler(XMLSchema schema)
+ {
+ this.schema = schema;
+ typeInfoProvider = new XMLSchemaTypeInfoProvider(this);
+ namespaceSupport = new NamespaceSupport();
+ context = new LinkedList();
+ attributes = new ArrayList();
+ final String ns = XMLConstants.W3C_XML_SCHEMA_NS_URI;
+ typeLibrary = new DatatypeLibraryLoader().createDatatypeLibrary(ns);
+ }
+
+ public ContentHandler getContentHandler()
+ {
+ return contentHandler;
+ }
+
+ public void setContentHandler(ContentHandler contentHandler)
+ {
+ this.contentHandler = contentHandler;
+ }
+
+ public ErrorHandler getErrorHandler()
+ {
+ return errorHandler;
+ }
+
+ public void setErrorHandler(ErrorHandler errorHandler)
+ {
+ this.errorHandler = errorHandler;
+ }
+
+ public LSResourceResolver getResourceResolver()
+ {
+ return resourceResolver;
+ }
+
+ public void setResourceResolver(LSResourceResolver resourceResolver)
+ {
+ this.resourceResolver = resourceResolver;
+ }
+
+ public TypeInfoProvider getTypeInfoProvider()
+ {
+ return typeInfoProvider;
+ }
+
+ TypeInfo getElementTypeInfo()
+ {
+ return (XMLSchemaElementTypeInfo) context.getFirst();
+ }
+
+ TypeInfo getAttributeTypeInfo(int index)
+ {
+ return (XMLSchemaAttributeTypeInfo) attributes.get(index);
+ }
+
+ boolean isIdAttribute(int index)
+ {
+ XMLSchemaAttributeTypeInfo typeInfo =
+ (XMLSchemaAttributeTypeInfo) attributes.get(index);
+ return typeInfo.id;
+ }
+
+ boolean isSpecified(int index)
+ {
+ XMLSchemaAttributeTypeInfo typeInfo =
+ (XMLSchemaAttributeTypeInfo) attributes.get(index);
+ return typeInfo.specified;
+ }
+
+ public void setDocumentLocator(Locator locator)
+ {
+ loc = locator;
+ if (contentHandler != null)
+ {
+ contentHandler.setDocumentLocator(locator);
+ }
+ }
+
+ public void startDocument()
+ throws SAXException
+ {
+ namespaceSupport.reset();
+ context.clear();
+ attributes.clear();
+ if (contentHandler != null)
+ {
+ contentHandler.startDocument();
+ }
+ }
+
+ public void endDocument()
+ throws SAXException
+ {
+ if (contentHandler != null)
+ {
+ contentHandler.endDocument();
+ }
+ }
+
+ public void startPrefixMapping(String prefix, String uri)
+ throws SAXException
+ {
+ namespaceSupport.declarePrefix(prefix, uri);
+ if (contentHandler != null)
+ {
+ contentHandler.startPrefixMapping(prefix, uri);
+ }
+ }
+
+ public void endPrefixMapping(String prefix)
+ throws SAXException
+ {
+ if (contentHandler != null)
+ {
+ contentHandler.endPrefixMapping(prefix);
+ }
+ }
+
+ public void startElement(String uri, String localName, String qName,
+ Attributes atts)
+ throws SAXException
+ {
+ namespaceSupport.pushContext();
+ QName name = new QName(uri, localName);
+ ElementDeclaration decl =
+ (ElementDeclaration) schema.elementDeclarations.get(name);
+ // Validation Rule: Element Locally Valid (Element)
+ String xsiType =
+ atts.getValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
+ xsiType = xsiType.trim(); // normalise
+ String xsiNil =
+ atts.getValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil");
+ Type type = decl.datatype;
+ if (xsiType.length() > 0)
+ {
+ try
+ {
+ Type specifiedType = resolveType(xsiType);
+ // TODO 4.3
+ type = specifiedType;
+ }
+ catch (DatatypeException e) // 4.1, 4.2
+ {
+ ValidationException e2 =
+ new ValidationException("Can't resolve type " + xsiType,
+ loc);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ XMLSchemaElementTypeInfo typeInfo =
+ new XMLSchemaElementTypeInfo(schema, decl, type);
+ if (decl == null) // 1
+ {
+ throw new ValidationException("No declaration for " + name, loc);
+ }
+ if (decl.isAbstract) // 2
+ {
+ throw new ValidationException("Declaration for " + name +
+ " is abstract", loc);
+ }
+ if (xsiNil.length() > 0)
+ {
+ if (!decl.nillable) // 3.1
+ {
+ throw new ValidationException("Declaration for " + name +
+ " is nillable but xsi:nil present",
+ loc);
+ }
+ else if ("true".equals(xsiNil)) // 3.2
+ {
+ typeInfo.nil = true;
+ if (decl.type == XMLSchema.CONSTRAINT_FIXED) // 3.2.2
+ {
+ throw new ValidationException("Declaration for " + name +
+ " is fixed but xsi:nil is true",
+ loc);
+ }
+ }
+ }
+ // TODO 5, 6, 7
+
+ // parent
+ if (!context.isEmpty())
+ {
+ XMLSchemaElementTypeInfo parent =
+ (XMLSchemaElementTypeInfo) context.getFirst();
+ if (parent.nil) // Element Locally Valid (Element) 3.2.1
+ {
+ throw new ValidationException("Parent of " + qName +
+ " is declared xsi:nil", loc);
+ }
+ // TODO
+ }
+ context.addFirst(typeInfo);
+ // attributes
+ int len = atts.getLength();
+ Attributes2Impl atts2 = new Attributes2Impl();
+ int count = 0;
+ for (int i = 0; i < len; i++)
+ {
+ String attUri = atts.getURI(i);
+ String attLocalName = atts.getLocalName(i);
+ String attQName = atts.getQName(i);
+ String attValue = atts.getValue(i);
+
+ if (XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(attUri))
+ {
+ continue; // ?
+ }
+
+ QName attName = new QName(attUri, attLocalName);
+ AttributeDeclaration attDecl =
+ (AttributeDeclaration) schema.attributeDeclarations.get(attName);
+ boolean declared = (attDecl != null);
+
+ String attType = (attDecl != null) ?
+ attDecl.datatype.toString() : "CDATA";
+ XMLSchemaAttributeTypeInfo attTypeInfo =
+ new XMLSchemaAttributeTypeInfo(schema, attDecl, true);
+ attributes.add(attTypeInfo);
+
+ atts2.addAttribute(attUri, attLocalName, attQName, attType, attValue);
+ atts2.setDeclared(count, declared);
+ atts2.setSpecified(count, true);
+ count++;
+ }
+ // add defaulted attributes to atts2
+ // TODO
+ // atts2.setSpecified(count, false);
+ if (contentHandler != null)
+ {
+ contentHandler.startElement(uri, localName, qName, atts2);
+ }
+ }
+
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException
+ {
+ // TODO check all required have been seen
+ context.removeFirst();
+ attributes.clear();
+ namespaceSupport.popContext();
+ if (contentHandler != null)
+ {
+ contentHandler.endElement(uri, localName, qName);
+ }
+ }
+
+ public void characters(char[] ch, int start, int length)
+ throws SAXException
+ {
+ XMLSchemaElementTypeInfo parent =
+ (XMLSchemaElementTypeInfo) context.getFirst();
+ if (parent.nil) // Element Locally Valid (Element) 3.2.1
+ {
+ throw new ValidationException(parent.decl.name.toString() +
+ " is declared xsi:nil",
+ loc);
+ }
+ // TODO
+ if (contentHandler != null)
+ {
+ contentHandler.characters(ch, start, length);
+ }
+ }
+
+ public void ignorableWhitespace(char[] ch, int start, int length)
+ throws SAXException
+ {
+ if (contentHandler != null)
+ {
+ contentHandler.ignorableWhitespace(ch, start, length);
+ }
+ }
+
+ public void processingInstruction(String target, String data)
+ throws SAXException
+ {
+ if (contentHandler != null)
+ {
+ contentHandler.processingInstruction(target, data);
+ }
+ }
+
+ public void skippedEntity(String name)
+ throws SAXException
+ {
+ if (contentHandler != null)
+ {
+ contentHandler.skippedEntity(name);
+ }
+ }
+
+ Type resolveType(String value)
+ throws DatatypeException
+ {
+ QName name = QName.valueOf(value);
+ String prefix = name.getPrefix();
+ String localName = name.getLocalPart();
+ if (prefix != null && prefix.length() > 0)
+ {
+ String uri = namespaceSupport.getURI(prefix);
+ if (!XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(uri))
+ return null;
+ }
+ if ("anyType".equals(localName))
+ return Type.ANY_TYPE;
+ return (SimpleType) typeLibrary.createDatatype(localName);
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/xpath/LangFunction.java b/libjava/classpath/gnu/xml/xpath/LangFunction.java
index 2c2506d1b97..584787efbf7 100644
--- a/libjava/classpath/gnu/xml/xpath/LangFunction.java
+++ b/libjava/classpath/gnu/xml/xpath/LangFunction.java
@@ -1,5 +1,5 @@
/* LangFunction.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -91,9 +91,15 @@ final class LangFunction
String getLang(Node node)
{
- if (node.getNodeType() == Node.ELEMENT_NODE)
+ while (node != null)
{
- return ((Element) node).getAttribute("xml:lang");
+ if (node.getNodeType() == Node.ELEMENT_NODE)
+ {
+ String lang = ((Element) node).getAttribute("xml:lang");
+ if (lang != null)
+ return lang;
+ }
+ node = node.getParentNode();
}
return null;
}
diff --git a/libjava/classpath/gnu/xml/xpath/NodeTypeTest.java b/libjava/classpath/gnu/xml/xpath/NodeTypeTest.java
index 09e92d0d9a2..4fe164625bb 100644
--- a/libjava/classpath/gnu/xml/xpath/NodeTypeTest.java
+++ b/libjava/classpath/gnu/xml/xpath/NodeTypeTest.java
@@ -84,6 +84,7 @@ public final class NodeTypeTest
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
case Node.COMMENT_NODE:
+ case Node.DOCUMENT_NODE:
if (type > 0)
{
if (nodeType != type)
diff --git a/libjava/classpath/gnu/xml/xpath/Selector.java b/libjava/classpath/gnu/xml/xpath/Selector.java
index 93408e48b23..c7abb33e2ff 100644
--- a/libjava/classpath/gnu/xml/xpath/Selector.java
+++ b/libjava/classpath/gnu/xml/xpath/Selector.java
@@ -90,7 +90,7 @@ public final class Selector
if (len > 0)
tests.toArray(this.tests);
else
- this.tests[0] = new NameTest(null, true, true);
+ this.tests[0] = new NodeTypeTest((short) 0);
if (axis == NAMESPACE && this.tests[0] instanceof NameTest)
{
NameTest nt = (NameTest) this.tests[0];
@@ -108,6 +108,14 @@ public final class Selector
public boolean matches(Node context)
{
+ // If called directly, selector is the top level of the path
+ return matches(context,
+ getContextPosition(context),
+ getContextSize(context));
+ }
+
+ boolean matches(Node context, int pos, int len)
+ {
short nodeType = context.getNodeType();
switch (axis)
{
@@ -125,19 +133,11 @@ public final class Selector
default:
return false;
}
- int tlen = tests.length;
- if (tlen > 0)
+ for (int j = 0; j < tests.length && len > 0; j++)
{
- int pos = getContextPosition(context);
- int len = getContextSize(context);
- if (len == 0)
- System.err.println("WARNING: context size is 0");
- for (int j = 0; j < tlen && len > 0; j++)
- {
- Test test = tests[j];
- if (!test.matches(context, pos, len))
- return false;
- }
+ Test test = tests[j];
+ if (!test.matches(context, pos, len))
+ return false;
}
return true;
}
@@ -147,7 +147,10 @@ public final class Selector
int pos = 1;
for (ctx = ctx.getPreviousSibling(); ctx != null;
ctx = ctx.getPreviousSibling())
- pos++;
+ {
+ if (tests[0].matches(ctx, 1, 1))
+ pos++;
+ }
return pos;
}
@@ -161,10 +164,16 @@ public final class Selector
int count = 1;
Node sib = ctx.getPreviousSibling();
for (; sib != null; sib = sib.getPreviousSibling())
- count++;
+ {
+ if (tests[0].matches(ctx, 1, 1))
+ count++;
+ }
sib = ctx.getNextSibling();
for (; sib != null; sib = sib.getNextSibling())
- count++;
+ {
+ if (tests[0].matches(ctx, 1, 1))
+ count++;
+ }
return count;
}