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 }