Index: modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/CryptoProvider.java
===================================================================
--- modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/CryptoProvider.java (revision 0)
+++ modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/CryptoProvider.java (revision 0)
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.harmony.security.provider.crypto;
+
+
+import java.security.Provider;
+import java.security.AccessController;
+
+
+/**
+ * Implementation of Provider for MessageDigest
+ * using a Secure Hash Algorithm, SHA-1;
+ * see SECURE HASH STANDARD, FIPS PUB 180-2
+ * (http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf)
+ *
+ * The implementation supports "SHA-1" algorithms described in
+ * JavaTM Cryptography Architecture, API Specification & Reference
+ */
+
+
+public final class CryptoProvider extends Provider {
+
+
+ /**
+ * Creates a Provider and puts parameters
+ */
+ public CryptoProvider() {
+
+ super("Crypto", 1.0, "HARMONY CryptoProvider");
+
+ // names of classes implementing services
+ final String MD_NAME =
+ "org.apache.harmony.security.provider.crypto.SHA1_MessageDigestImpl";
+
+ AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Object run() {
+
+ put("MessageDigest.SHA-1", MD_NAME);
+ put("MessageDigest.SHA-1 ImplementedIn", "Software");
+ put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
+ put("Alg.Alias.MessageDigest.SHA", "SHA-1");
+
+ return null;
+ }
+ }
+ );
+ }
+}
Index: modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java
===================================================================
--- modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java (revision 0)
+++ modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java (revision 0)
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.harmony.security.provider.crypto;
+
+
+import java.security.MessageDigestSpi;
+import java.security.DigestException;
+
+import java.nio.ByteBuffer;
+import java.nio.BufferUnderflowException;
+
+import java.util.Arrays;
+
+import org.apache.harmony.security.provider.crypto.SHA1_Data;
+import org.apache.harmony.security.provider.crypto.SHA1Impl;
+
+
+/**
+ * This class extends the MessageDigestSpi class implementing all its abstract methods;
+ * it overrides the "Object clone()" and "int engineGetDigestLength()" methods.
+ * The class implements the Cloneable interface.
+ */
+
+
+public class SHA1_MessageDigestImpl extends MessageDigestSpi
+ implements Cloneable, SHA1_Data {
+
+
+ private int buffer[]; // buffer has the following structure:
+ // - 0-16 - frame for accumulating a message
+ // - 17-79 - for SHA1Impl methods
+ // - 80 - unused
+ // - 81 - to store length of the message
+ // - 82-86 - frame for current message digest
+
+ private byte oneByte[]; // one byte buffer needed to use in engineUpdate(byte)
+ // having buffer as private field is just optimization
+
+ private int messageLength; // total length of bytes supplied by user
+
+
+ /**
+ * The constructor creates needed buffers and sets the engine at initial state
+ */
+ public SHA1_MessageDigestImpl() {
+
+ // BYTES_OFFSET +6 is minimal length required by methods in SHA1Impl
+ buffer = new int[BYTES_OFFSET +6];
+
+ oneByte = new byte[1];
+
+ engineReset();
+ }
+
+
+ /**
+ * The method performs final actions and invokes the "computeHash(int[])" method.
+ * In case if there is no enough words in current frame
+ * after processing its data, extra frame is prepared and
+ * the "computeHash(int[])" method is invoked second time.
+ *
+ * After processing, the method resets engine's state
+ *
+ * @param
+ * digest - byte array
+ * @param
+ * offset - offset in digest
+ */
+ private void processDigest(byte[] digest, int offset) {
+
+ int i, j; // implementation variables
+ int lastWord; //
+
+ long nBits = messageLength <<3 ; // length has to be calculated before padding
+
+ engineUpdate( (byte) 0x80 ); // beginning byte in padding
+
+ i = 0; // i contains number of beginning word for following loop
+
+ lastWord = (buffer[BYTES_OFFSET] + 3)>>2 ; // computing of # of full words by shifting
+ // # of bytes
+
+ // possible cases:
+ //
+ // - buffer[BYTES_OFFSET] == 0 - buffer frame is empty,
+ // padding byte was 64th in previous frame
+ // current frame should contain only message's length
+ //
+ // - lastWord < 14 - two last, these are 14 & 15, words in 16 word frame are free;
+ // no extra frame needed
+ // - lastWord = 14 - only one last, namely 15-th, word in frame doesn't contain bytes;
+ // extra frame is needed
+ // - lastWord > 14 - last word in frame is not full;
+ // extra frame is needed
+
+ if ( buffer[BYTES_OFFSET] != 0 ) {
+
+ if ( lastWord < 15 ) {
+ i = lastWord;
+ } else {
+ if ( lastWord == 15 ) {
+ buffer[15] = 0; // last word in frame is set to "0"
+ }
+ SHA1Impl.computeHash(buffer);
+ i = 0;
+ }
+ }
+ Arrays.fill(buffer, i, 14, 0);
+
+ buffer[14] = (int)( nBits >>>32 );
+ buffer[15] = (int)( nBits & 0xFFFFFFFF );
+ SHA1Impl.computeHash(buffer);
+
+ // converting 5-word frame into 20 bytes
+ j = offset;
+ for ( i = HASH_OFFSET; i < HASH_OFFSET +5; i++ ) {
+ int k = buffer[i];
+ digest[j ] = (byte) ( k >>>24 ); // getting first byte from left
+ digest[j+1] = (byte) ( k >>>16 ); // getting second byte from left
+ digest[j+2] = (byte) ( k >>> 8 ); // getting third byte from left
+ digest[j+3] = (byte) ( k ); // getting fourth byte from left
+ j += 4;
+ }
+
+ engineReset();
+ }
+
+ // methods specified in java.security.MessageDigestSpi
+
+ /**
+ * Returns a "deep" copy of this SHA1MDImpl object.
+ *
+ * The method overrides "clone()" in class Object.
+ *
+ * @return
+ * a clone of this object
+ */
+ public Object clone() throws CloneNotSupportedException {
+
+ SHA1_MessageDigestImpl cloneObj = (SHA1_MessageDigestImpl) super.clone();
+
+ cloneObj.buffer = ( int[])buffer.clone();
+ cloneObj.oneByte = (byte[])oneByte.clone();
+
+ return cloneObj;
+ }
+
+
+ /**
+ * Computes a message digest value.
+ *
+ * The method resets the engine.
+ *
+ * The method overrides "engineDigest()" in class MessageDigestSpi.
+ *
+ * @return
+ * byte array containing message digest value
+ */
+ protected byte[] engineDigest() {
+
+ byte[] hash = new byte[DIGEST_LENGTH];
+
+ processDigest(hash, 0);
+ return hash;
+ }
+
+
+ /**
+ * Computes message digest value.
+ * Upon return, the value is stored in "buf" buffer beginning "offset" byte.
+ *
+ * The method resets the engine.
+ *
+ * The method overrides "engineDigest(byte[],int,int) in class MessageDigestSpi.
+ *
+ * @param
+ * buf byte array to store a message digest returned
+ * @param
+ * offset a position in the array for first byte of the message digest
+ * @param
+ * len number of bytes within buffer allotted for the message digest;
+ * as this implementation doesn't provide partial digests,
+ * len should be >= 20, DigestException is thrown otherwise
+ * @return
+ * the length of the message digest stored in the "buf" buffer;
+ * in this implementation the length=20
+ *
+ * @throws IllegalArgumentException
+ * if null is passed to the "buf" argument
+ * if offset + len > buf.length
+ * if offset > buf.length or len > buf.length
+ *
+ * @throws DigestException
+ * if len < 20
+ *
+ * @throws ArrayIndexOutOfBoundsException
+ * if offset < 0
+ */
+ protected int engineDigest(byte[] buf, int offset, int len) throws DigestException {
+
+ if ( buf == null ) {
+ throw new IllegalArgumentException("null is passed to 'buf' parameter");
+ }
+ if ( offset > buf.length || len > buf.length || (len + offset) > buf.length ) {
+ throw new IllegalArgumentException(
+ "buf.lendth doesn't fit supplied offset and len");
+ }
+ if ( len < DIGEST_LENGTH ) {
+ throw new DigestException(" len < digest's length (which is 20 bytes) ");
+ }
+ if ( offset < 0 ) {
+ throw new ArrayIndexOutOfBoundsException("negative offset: " + offset);
+ }
+
+ processDigest(buf, offset);
+
+ return DIGEST_LENGTH;
+ }
+
+
+ /**
+ * Returns a message digest length.
+ *
+ * The method overrides "engineGetDigestLength()" in class MessageDigestSpi.
+ *
+ * @return
+ * total length of current message digest as an int value
+ */
+ protected int engineGetDigestLength() {
+ return DIGEST_LENGTH;
+ }
+
+
+ /**
+ * Resets the engine.
+ *
+ * The method overrides "engineReset()" in class MessageDigestSpi.
+ */
+ protected void engineReset() {
+
+ messageLength = 0;
+
+ buffer[BYTES_OFFSET] = 0;
+ buffer[HASH_OFFSET ] = H0;
+ buffer[HASH_OFFSET +1] = H1;
+ buffer[HASH_OFFSET +2] = H2;
+ buffer[HASH_OFFSET +3] = H3;
+ buffer[HASH_OFFSET +4] = H4;
+ }
+
+
+ /**
+ * Supplements a byte to current message.
+ *
+ * The method overrides "engineUpdate(byte)" in class MessageDigestSpi.
+ *
+ * @param
+ * input byte to add to current message
+ */
+ protected void engineUpdate(byte input) {
+
+ oneByte[0] = input;
+ SHA1Impl.updateHash( buffer, oneByte, 0, 0 );
+ messageLength++;
+ }
+
+
+ /**
+ * Updates current message.
+ *
+ * The method overrides "engineUpdate(byte[],intint)" in class MessageDigestSpi.
+ *
+ * The method silently returns if "len" <= 0.
+ *
+ * @param
+ * input a byte array
+ * @param
+ * offset a number of first byte in the "input" array to use for updating
+ * @param
+ * len a number of bytes to use
+ *
+ * @throws NullPointerException
+ * if null is passed to the "buf" argument
+ *
+ * @throws IllegalArgumentException
+ * if offset > buf.length or len > buf.length or
+ * (len + offset) > buf.length
+ * @throws ArrayIndexOutOfBoundsException
+ * offset < 0
+ */
+ protected void engineUpdate(byte[] input, int offset, int len) {
+
+ if ( input == null ) {
+ throw new IllegalArgumentException("no byte[] passed to 'input' parameter");
+ }
+ if ( len <= 0 ) {
+ return;
+ }
+ if ( offset < 0 ) {
+ throw new ArrayIndexOutOfBoundsException("offset < 0 : " + offset);
+ }
+ if ( offset > input.length || len > input.length || (len + offset) > input.length ) {
+ throw new IllegalArgumentException(
+ "input.lendth doesn't fit supplied offset and len");
+ }
+
+ SHA1Impl.updateHash(buffer, input, offset, offset + len -1 );
+ messageLength += len;
+ }
+
+}