View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.kerberos.shared.crypto.encryption;
21  
22  
23  import java.security.SecureRandom;
24  
25  import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
26  import org.apache.directory.shared.kerberos.components.EncryptedData;
27  import org.apache.directory.shared.kerberos.components.EncryptionKey;
28  import org.apache.directory.shared.kerberos.exceptions.KerberosException;
29  
30  
31  /**
32   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
33   */
34  public abstract class EncryptionEngine
35  {
36      private static final SecureRandom random = new SecureRandom();
37  
38  
39      protected abstract byte[] getDecryptedData( EncryptionKey key, EncryptedData data, KeyUsage usage )
40          throws KerberosException;
41  
42  
43      protected abstract EncryptedData getEncryptedData( EncryptionKey key, byte[] plainText, KeyUsage usage );
44  
45  
46      protected abstract EncryptionType getEncryptionType();
47  
48  
49      protected abstract int getConfounderLength();
50  
51  
52      protected abstract int getChecksumLength();
53  
54  
55      protected abstract byte[] encrypt( byte[] plainText, byte[] key );
56  
57  
58      protected abstract byte[] decrypt( byte[] cipherText, byte[] key );
59  
60  
61      protected abstract byte[] calculateIntegrity( byte[] plainText, byte[] key, KeyUsage usage );
62  
63  
64      protected byte[] deriveRandom( byte[] key, byte[] usage, int n, int k )
65      {
66          byte[] nFoldedUsage = NFold.nFold( n, usage );
67  
68          int kBytes = k / 8;
69          byte[] result = new byte[kBytes];
70  
71          byte[] fillingKey = encrypt( nFoldedUsage, key );
72  
73          int pos = 0;
74  
75          for ( int i = 0; i < kBytes; i++ )
76          {
77              if ( pos < fillingKey.length )
78              {
79                  result[i] = fillingKey[pos];
80                  pos++;
81              }
82              else
83              {
84                  fillingKey = encrypt( fillingKey, key );
85                  pos = 0;
86                  result[i] = fillingKey[pos];
87                  pos++;
88              }
89          }
90  
91          return result;
92      }
93  
94  
95      // Encryption
96      protected byte[] getRandomBytes( int size )
97      {
98          byte[] bytes = new byte[size];
99  
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         int l1 = array1.length;
142         int l2 = array2.length;
143         byte concatenatedBytes[] = new byte[l1 + l2];
144 
145         System.arraycopy( array1, 0, concatenatedBytes, 0, l1 );
146         System.arraycopy( array2, 0, concatenatedBytes, l1, l2 );
147 
148         return concatenatedBytes;
149     }
150 
151 
152     // Decryption
153     protected byte[] removeLeadingBytes( byte[] array, int confounder, int checksum )
154     {
155         byte lessBytes[] = new byte[array.length - confounder - checksum];
156 
157         int j = 0;
158         for ( int i = confounder + checksum; i < array.length; i++ )
159         {
160             lessBytes[j] = array[i];
161             j++;
162         }
163 
164         return lessBytes;
165     }
166 
167 
168     protected byte[] removeTrailingBytes( byte[] array, int confounder, int checksum )
169     {
170         byte lessBytes[] = new byte[array.length - confounder - checksum];
171 
172         int j = 0;
173         for ( int i = 0; i < array.length - confounder - checksum; i++ )
174         {
175             lessBytes[j] = array[i];
176             j++;
177         }
178 
179         return lessBytes;
180     }
181 
182 
183     protected int getBit( byte[] data, int pos )
184     {
185         int posByte = pos / 8;
186         int posBit = pos % 8;
187 
188         byte valByte = data[posByte];
189         
190         return valByte >> ( 8 - ( posBit + 1 ) ) & 0x0001;
191     }
192 
193 
194     protected void setBit( byte[] data, int pos, int val )
195     {
196         int posByte = pos / 8;
197         int posBit = pos % 8;
198         byte oldByte = data[posByte];
199         oldByte = ( byte ) ( ( ( 0xFF7F >> posBit ) & oldByte ) & 0x00FF );
200         byte newByte = ( byte ) ( ( val << ( 8 - ( posBit + 1 ) ) ) | oldByte );
201         data[posByte] = newByte;
202     }
203 
204 
205     /**
206      * The "well-known constant" used for the DK function is the key
207      * usage number, expressed as four octets in big-endian order,
208      * followed by one octet indicated below.
209      * 
210      *  Kc = DK(base-key, usage | 0x99);
211      *  
212      *  @param usage The key usage
213      *  @return the computed usage Kc
214      */
215     protected byte[] getUsageKc( KeyUsage usage )
216     {
217         return getUsage( usage.getOrdinal(), ( byte ) 0x99 );
218     }
219 
220 
221     /**
222      * The "well-known constant" used for the DK function is the key
223      * usage number, expressed as four octets in big-endian order,
224      * followed by one octet indicated below.
225      * 
226      *  Ke = DK(base-key, usage | 0xAA);
227      *  
228      *  @param usage The key usage
229      *  @return the computed usage Ke
230      */
231     protected byte[] getUsageKe( KeyUsage usage )
232     {
233         return getUsage( usage.getOrdinal(), ( byte ) 0xAA );
234     }
235 
236 
237     /**
238      * The "well-known constant" used for the DK function is the key
239      * usage number, expressed as four octets in big-endian order,
240      * followed by one octet indicated below.
241      * 
242      *  Ki = DK(base-key, usage | 0x55);
243      *  
244      *  @param usage The key usage
245      *  @return the computed usage Ki
246      */
247     protected byte[] getUsageKi( KeyUsage usage )
248     {
249         return getUsage( usage.getOrdinal(), ( byte ) 0x55 );
250     }
251 
252 
253     private byte[] getUsage( int usage, byte constant )
254     {
255         byte[] bytes = new byte[5];
256         bytes[0] = ( byte ) ( ( usage >>> 24 ) & 0x000000FF );
257         bytes[1] = ( byte ) ( ( usage >> 16 ) & 0x000000FF );
258         bytes[2] = ( byte ) ( ( usage >> 8 ) & 0x000000FF );
259         bytes[3] = ( byte ) ( usage & 0x00FF );
260         bytes[4] = constant;
261 
262         return bytes;
263     }
264 }