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 */ 020package org.apache.directory.server.kerberos.shared.crypto.encryption; 021 022 023import java.security.SecureRandom; 024 025import org.apache.directory.shared.kerberos.codec.types.EncryptionType; 026import org.apache.directory.shared.kerberos.components.EncryptedData; 027import org.apache.directory.shared.kerberos.components.EncryptionKey; 028import org.apache.directory.shared.kerberos.exceptions.KerberosException; 029 030 031/** 032 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 033 */ 034public 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 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}