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.messages.value; 021 022 023 import java.nio.BufferOverflowException; 024 import java.nio.ByteBuffer; 025 import java.util.Arrays; 026 027 import org.apache.directory.server.i18n.I18n; 028 import org.apache.directory.server.kerberos.shared.crypto.encryption.EncryptionType; 029 import org.apache.directory.shared.asn1.AbstractAsn1Object; 030 import org.apache.directory.shared.asn1.ber.tlv.TLV; 031 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag; 032 import org.apache.directory.shared.asn1.ber.tlv.Value; 033 import org.apache.directory.shared.asn1.codec.EncoderException; 034 import org.apache.directory.shared.ldap.util.StringTools; 035 import org.slf4j.Logger; 036 import org.slf4j.LoggerFactory; 037 038 039 /** 040 * A Kerberos symmetric encryption key, which includes metadata support for 041 * the associated key type and key version number. 042 * 043 * The ASN.1 description for this structure is : 044 * EncryptionKey ::= SEQUENCE { 045 * keytype [0] Int32 -- actually encryption type --, 046 * keyvalue [1] OCTET STRING 047 * } 048 * 049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 050 * @version $Rev: 902575 $, $Date: 2010-01-24 15:38:06 +0100 (Sun, 24 Jan 2010) $ 051 */ 052 public class EncryptionKey extends AbstractAsn1Object 053 { 054 /** The logger */ 055 private static final Logger log = LoggerFactory.getLogger( EncryptionKey.class ); 056 057 /** Speedup for logs */ 058 private static final boolean IS_DEBUG = log.isDebugEnabled(); 059 060 // The encryption type 061 private EncryptionType keyType; 062 063 // The encrypted value 064 private byte[] keyValue; 065 066 // The key version 067 private int keyVersion; 068 069 // Storage for computed lengths 070 private transient int keyTypeLength; 071 private transient int keyValueLength; 072 private transient int encryptionKeyLength; 073 074 075 /** 076 * Creates a new instance of EncryptionKey. 077 */ 078 public EncryptionKey() 079 { 080 } 081 082 083 /** 084 * Creates a new instance of EncryptionKey. 085 * 086 * @param keyType The encryptionType 087 * @param keyValue The value 088 */ 089 public EncryptionKey( EncryptionType keyType, byte[] keyValue ) 090 { 091 this.keyType = keyType; 092 this.keyValue = keyValue; 093 } 094 095 096 /** 097 * Creates a new instance of EncryptionKey. 098 * 099 * @param keyType The encryptionType 100 * @param keyValue The value 101 * @param keyVersion ??? 102 */ 103 public EncryptionKey( EncryptionType keyType, byte[] keyValue, int keyVersion ) 104 { 105 this.keyType = keyType; 106 this.keyValue = keyValue; 107 this.keyVersion = keyVersion; 108 } 109 110 111 /** 112 * Destroys this key by overwriting the symmetric key material with zeros. 113 */ 114 public synchronized void destroy() 115 { 116 if ( keyValue != null ) 117 { 118 Arrays.fill( keyValue, ( byte ) 0x00 ); 119 } 120 } 121 122 123 /** 124 * Returns the key type. 125 * 126 * @return The key type. 127 */ 128 public EncryptionType getKeyType() 129 { 130 return keyType; 131 } 132 133 134 /** 135 * Set the encryption type 136 * @param keyType The encryption type 137 */ 138 public void setKeyType( EncryptionType keyType ) 139 { 140 this.keyType = keyType; 141 } 142 143 144 /** 145 * Returns the key value. 146 * 147 * @return The key value. 148 */ 149 public byte[] getKeyValue() 150 { 151 return keyValue; 152 } 153 154 155 /** 156 * Returns the key version. 157 * 158 * @return The key version. 159 */ 160 public int getKeyVersion() 161 { 162 return keyVersion; 163 } 164 165 166 /** 167 * Set the key value 168 * @param keyVersion The key version 169 */ 170 public void setKeyVersion( int keyVersion) 171 { 172 this.keyVersion = keyVersion; 173 } 174 175 176 /** 177 * Set the key value 178 * @param keyValue The key value 179 */ 180 public void setKeyValue( byte[] keyValue ) 181 { 182 this.keyValue = keyValue; 183 } 184 185 186 /** 187 * @see Object#equals(Object) 188 */ 189 public boolean equals( Object o ) 190 { 191 if ( this == o ) 192 { 193 return true; 194 } 195 196 if ( ( o == null ) || !( o instanceof EncryptionKey ) ) 197 { 198 return false; 199 } 200 201 EncryptionKey that = ( EncryptionKey ) o; 202 return ( this.keyType == that.keyType ) && ( Arrays.equals( this.keyValue, that.keyValue ) ); 203 } 204 205 206 /** 207 * Compute the EncryptionKey length 208 * 209 * EncryptionKey : 210 * 211 * 0x30 L1 EncryptionKey 212 * | 213 * +--> 0xA0 L2 keyType tag 214 * | | 215 * | +--> 0x02 L2-1 keyType (int) 216 * | 217 * +--> 0xA1 L3 keyValue tag 218 * | 219 * +--> 0x04 L3-1 keyValue (OCTET STRING) 220 * 221 * where L1 = L2 + lenght(0xA0) + length(L2) + 222 * L3 + lenght(0xA1) + length(L3) 223 * and 224 * L2 = L2-1 + length(0x02) + length( L2-1) 225 * L3 = L3-1 + length(0x04) + length( L3-1) 226 */ 227 public int computeLength() 228 { 229 // Compute the keyType. The Length will always be cobntained in 1 byte 230 keyTypeLength = 1 + 1 + Value.getNbBytes( keyType.getOrdinal() ); 231 encryptionKeyLength = 1 + TLV.getNbBytes( keyTypeLength ) + keyTypeLength; 232 233 // Compute the keyValue 234 if ( keyValue == null ) 235 { 236 keyValueLength = 1 + 1; 237 } 238 else 239 { 240 keyValueLength = 1 + TLV.getNbBytes( keyValue.length ) + keyValue.length; 241 } 242 243 encryptionKeyLength += 1 + TLV.getNbBytes( keyValueLength ) + keyValueLength; 244 245 // Compute the whole sequence length 246 int encryptionKeySeqLength = 1 + Value.getNbBytes( encryptionKeyLength ) + encryptionKeyLength; 247 248 return encryptionKeySeqLength; 249 250 } 251 252 253 /** 254 * Encode the EncryptionKey message to a PDU. 255 * 256 * EncryptionKey : 257 * 258 * 0x30 LL 259 * 0xA0 LL 260 * 0x02 0x01 keyType 261 * 0xA1 LL 262 * 0x04 LL keyValue 263 * 264 * @param buffer The buffer where to put the PDU. It should have been allocated 265 * before, with the right size. 266 * @return The constructed PDU. 267 */ 268 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 269 { 270 if ( buffer == null ) 271 { 272 throw new EncoderException( I18n.err( I18n.ERR_148 ) ); 273 } 274 275 try 276 { 277 // The EncryptionKey SEQ Tag 278 buffer.put( UniversalTag.SEQUENCE_TAG ); 279 buffer.put( TLV.getBytes( encryptionKeyLength ) ); 280 281 // The keyType, first the tag, then the value 282 buffer.put( ( byte ) 0xA0 ); 283 buffer.put( TLV.getBytes( keyTypeLength ) ); 284 Value.encode( buffer, keyType.getOrdinal() ); 285 286 // The keyValue, first the tag, then the value 287 buffer.put( ( byte ) 0xA1 ); 288 buffer.put( TLV.getBytes( keyValueLength ) ); 289 Value.encode( buffer, keyValue ); 290 } 291 catch ( BufferOverflowException boe ) 292 { 293 log.error( I18n.err( I18n.ERR_142, 1 + TLV.getNbBytes( encryptionKeyLength ) 294 + encryptionKeyLength, buffer.capacity() ) ); 295 throw new EncoderException( I18n.err( I18n.ERR_138 ) ); 296 } 297 298 if ( IS_DEBUG ) 299 { 300 log.debug( "EncryptionKey encoding : {}", StringTools.dumpBytes( buffer.array() ) ); 301 log.debug( "EncryptionKey initial value : {}", toString() ); 302 } 303 304 return buffer; 305 } 306 307 308 /** 309 * @see Object#toString() 310 */ 311 public String toString() 312 { 313 return keyType.toString() + " (" + keyType.getOrdinal() + ")"; 314 } 315 }