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 03:00:43 +0300 (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 }