001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.server.kerberos.shared.crypto.encryption;
021    
022    
023    import java.security.SecureRandom;
024    
025    import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
026    import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
027    import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;
028    
029    
030    /**
031     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
032     * @version $Rev: 540371 $, $Date: 2007-05-22 02:00:43 +0200 (Tue, 22 May 2007) $
033     */
034    public abstract class EncryptionEngine
035    {
036        private static final SecureRandom random = new SecureRandom();
037    
038    
039        protected abstract byte[] getDecryptedData( EncryptionKey key, EncryptedData data, KeyUsage usage )
040            throws KerberosException;
041    
042    
043        protected abstract EncryptedData getEncryptedData( EncryptionKey key, byte[] plainText, KeyUsage usage );
044    
045    
046        protected abstract EncryptionType getEncryptionType();
047    
048    
049        protected abstract int getConfounderLength();
050    
051    
052        protected abstract int getChecksumLength();
053    
054    
055        protected abstract byte[] encrypt( byte[] plainText, byte[] key );
056    
057    
058        protected abstract byte[] decrypt( byte[] cipherText, byte[] key );
059    
060    
061        protected abstract byte[] calculateIntegrity( byte[] plainText, byte[] key, KeyUsage usage );
062    
063    
064        protected byte[] deriveRandom( byte[] key, byte[] usage, int n, int k )
065        {
066            byte[] nFoldedUsage = NFold.nFold( n, usage );
067    
068            int kBytes = k / 8;
069            byte[] result = new byte[kBytes];
070    
071            byte[] fillingKey = encrypt( nFoldedUsage, key );
072    
073            int pos = 0;
074    
075            for ( int i = 0; i < kBytes; i++ )
076            {
077                if ( pos < fillingKey.length )
078                {
079                    result[i] = fillingKey[pos];
080                    pos++;
081                }
082                else
083                {
084                    fillingKey = encrypt( fillingKey, key );
085                    pos = 0;
086                    result[i] = fillingKey[pos];
087                    pos++;
088                }
089            }
090    
091            return result;
092        }
093    
094    
095        // Encryption
096        protected byte[] getRandomBytes( int size )
097        {
098            byte[] bytes = new byte[size];
099    
100            // SecureRandom.nextBytes is already synchronized
101            random.nextBytes( bytes );
102    
103            return bytes;
104        }
105    
106    
107        // Encryption
108        protected byte[] padString( byte encodedString[] )
109        {
110            int x;
111            if ( encodedString.length < 8 )
112            {
113                x = encodedString.length;
114            }
115            else
116            {
117                x = encodedString.length % 8;
118            }
119    
120            if ( x == 0 )
121            {
122                return encodedString;
123            }
124    
125            byte paddedByteArray[] = new byte[( 8 - x ) + encodedString.length];
126    
127            for ( int y = paddedByteArray.length - 1; y > encodedString.length - 1; y-- )
128            {
129                paddedByteArray[y] = 0;
130            }
131    
132            System.arraycopy( encodedString, 0, paddedByteArray, 0, encodedString.length );
133    
134            return paddedByteArray;
135        }
136    
137    
138        // Encryption
139        protected byte[] concatenateBytes( byte[] array1, byte[] array2 )
140        {
141            byte concatenatedBytes[] = new byte[array1.length + array2.length];
142    
143            for ( int i = 0; i < array1.length; i++ )
144            {
145                concatenatedBytes[i] = array1[i];
146            }
147    
148            for ( int j = array1.length; j < concatenatedBytes.length; j++ )
149            {
150                concatenatedBytes[j] = array2[j - array1.length];
151            }
152    
153            return concatenatedBytes;
154        }
155    
156    
157        // Decryption
158        protected byte[] removeLeadingBytes( byte[] array, int confounder, int checksum )
159        {
160            byte lessBytes[] = new byte[array.length - confounder - checksum];
161    
162            int j = 0;
163            for ( int i = confounder + checksum; i < array.length; i++ )
164            {
165                lessBytes[j] = array[i];
166                j++;
167            }
168    
169            return lessBytes;
170        }
171    
172    
173        protected byte[] removeTrailingBytes( byte[] array, int confounder, int checksum )
174        {
175            byte lessBytes[] = new byte[array.length - confounder - checksum];
176    
177            int j = 0;
178            for ( int i = 0; i < array.length - confounder - checksum; i++ )
179            {
180                lessBytes[j] = array[i];
181                j++;
182            }
183    
184            return lessBytes;
185        }
186    
187    
188        protected int getBit( byte[] data, int pos )
189        {
190            int posByte = pos / 8;
191            int posBit = pos % 8;
192    
193            byte valByte = data[posByte];
194            int valInt = valByte >> ( 8 - ( posBit + 1 ) ) & 0x0001;
195            return valInt;
196        }
197    
198    
199        protected void setBit( byte[] data, int pos, int val )
200        {
201            int posByte = pos / 8;
202            int posBit = pos % 8;
203            byte oldByte = data[posByte];
204            oldByte = ( byte ) ( ( ( 0xFF7F >> posBit ) & oldByte ) & 0x00FF );
205            byte newByte = ( byte ) ( ( val << ( 8 - ( posBit + 1 ) ) ) | oldByte );
206            data[posByte] = newByte;
207        }
208    
209    
210        /**
211         * The "well-known constant" used for the DK function is the key
212         * usage number, expressed as four octets in big-endian order,
213         * followed by one octet indicated below.
214         * 
215         *  Kc = DK(base-key, usage | 0x99);
216         */
217        protected byte[] getUsageKc( KeyUsage usage )
218        {
219            return getUsage( usage.getOrdinal(), ( byte ) 0x99 );
220        }
221    
222    
223        /**
224         * The "well-known constant" used for the DK function is the key
225         * usage number, expressed as four octets in big-endian order,
226         * followed by one octet indicated below.
227         * 
228         *  Ke = DK(base-key, usage | 0xAA);
229         */
230        protected byte[] getUsageKe( KeyUsage usage )
231        {
232            return getUsage( usage.getOrdinal(), ( byte ) 0xAA );
233        }
234    
235    
236        /**
237         * The "well-known constant" used for the DK function is the key
238         * usage number, expressed as four octets in big-endian order,
239         * followed by one octet indicated below.
240         * 
241         *  Ki = DK(base-key, usage | 0x55);
242         */
243        protected byte[] getUsageKi( KeyUsage usage )
244        {
245            return getUsage( usage.getOrdinal(), ( byte ) 0x55 );
246        }
247    
248    
249        private byte[] getUsage( int usage, byte constant )
250        {
251            byte[] bytes = new byte[5];
252            bytes[0] = ( byte ) ( ( usage >>> 24 ) & 0x000000FF );
253            bytes[1] = ( byte ) ( ( usage >> 16 ) & 0x000000FF );
254            bytes[2] = ( byte ) ( ( usage >> 8 ) & 0x000000FF );
255            bytes[3] = ( byte ) ( usage & 0x00FF );
256            bytes[4] = constant;
257    
258            return bytes;
259        }
260    }