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 021package org.apache.directory.server.kerberos.shared.crypto.encryption; 022 023 024import java.nio.ByteBuffer; 025import java.util.Collections; 026import java.util.EnumMap; 027import java.util.Map; 028 029import org.apache.directory.api.asn1.Asn1Object; 030import org.apache.directory.api.asn1.EncoderException; 031import org.apache.directory.api.ldap.model.constants.Loggers; 032import org.apache.directory.shared.kerberos.codec.types.EncryptionType; 033import org.apache.directory.shared.kerberos.components.EncryptedData; 034import org.apache.directory.shared.kerberos.components.EncryptionKey; 035import org.apache.directory.shared.kerberos.exceptions.ErrorType; 036import org.apache.directory.shared.kerberos.exceptions.KerberosException; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040 041/** 042 * A Hashed Adapter encapsulating ASN.1 cipher text engines to 043 * perform encrypt() and decrypt() operations. 044 * 045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 046 */ 047public class CipherTextHandler 048{ 049 /** The loggers for this class */ 050 private static final Logger LOG_KRB = LoggerFactory.getLogger( Loggers.KERBEROS_LOG.getName() ); 051 052 /** a map of the default encryption types to the encryption engine class names */ 053 private static final Map<EncryptionType, Class<? extends EncryptionEngine>> DEFAULT_CIPHERS; 054 055 // Initialize the list of encyption mechanisms 056 static 057 { 058 EnumMap<EncryptionType, Class<? extends EncryptionEngine>> map = new EnumMap<>( EncryptionType.class ); 059 060 map.put( EncryptionType.DES_CBC_MD5, DesCbcMd5Encryption.class ); 061 map.put( EncryptionType.DES3_CBC_SHA1_KD, Des3CbcSha1KdEncryption.class ); 062 map.put( EncryptionType.AES128_CTS_HMAC_SHA1_96, Aes128CtsSha1Encryption.class ); 063 map.put( EncryptionType.AES256_CTS_HMAC_SHA1_96, Aes256CtsSha1Encryption.class ); 064 map.put( EncryptionType.RC4_HMAC, ArcFourHmacMd5Encryption.class ); 065 066 DEFAULT_CIPHERS = Collections.unmodifiableMap( map ); 067 } 068 069 070 /** 071 * Performs an encode and an encrypt. 072 * 073 * @param key The key to use for encrypting. 074 * @param message The Kerberos object to encode. 075 * @param usage The key usage. 076 * @return The Kerberos EncryptedData. 077 * @throws KerberosException if the seal failed 078 */ 079 public EncryptedData seal( EncryptionKey key, Asn1Object message, KeyUsage usage ) throws KerberosException 080 { 081 try 082 { 083 int bufferSize = message.computeLength(); 084 ByteBuffer buffer = ByteBuffer.allocate( bufferSize ); 085 byte[] encoded = message.encode( buffer ).array(); 086 return encrypt( key, encoded, usage ); 087 } 088 catch ( EncoderException ioe ) 089 { 090 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, ioe ); 091 } 092 catch ( ClassCastException cce ) 093 { 094 throw new KerberosException( ErrorType.KRB_AP_ERR_BAD_INTEGRITY, cce ); 095 } 096 } 097 098 099 public EncryptedData encrypt( EncryptionKey key, byte[] plainText, KeyUsage usage ) throws KerberosException 100 { 101 EncryptionEngine engine = getEngine( key ); 102 103 return engine.getEncryptedData( key, plainText, usage ); 104 } 105 106 107 /** 108 * Decrypt a block of data. 109 * 110 * @param key The key used to decrypt the data 111 * @param data The data to decrypt 112 * @param usage The key usage number 113 * @return The decrypted data as a byte[] 114 * @throws KerberosException If the decoding failed 115 */ 116 public byte[] decrypt( EncryptionKey key, EncryptedData data, KeyUsage usage ) throws KerberosException 117 { 118 LOG_KRB.debug( "Decrypting data using key {} and usage {}", key.getKeyType(), usage ); 119 EncryptionEngine engine = getEngine( key ); 120 121 return engine.getDecryptedData( key, data, usage ); 122 } 123 124 125 private EncryptionEngine getEngine( EncryptionKey key ) throws KerberosException 126 { 127 EncryptionType encryptionType = key.getKeyType(); 128 129 Class<?> clazz = DEFAULT_CIPHERS.get( encryptionType ); 130 131 if ( clazz == null ) 132 { 133 throw new KerberosException( ErrorType.KDC_ERR_ETYPE_NOSUPP ); 134 } 135 136 try 137 { 138 return ( EncryptionEngine ) clazz.newInstance(); 139 } 140 catch ( IllegalAccessException iae ) 141 { 142 throw new KerberosException( ErrorType.KDC_ERR_ETYPE_NOSUPP, iae ); 143 } 144 catch ( InstantiationException ie ) 145 { 146 throw new KerberosException( ErrorType.KDC_ERR_ETYPE_NOSUPP, ie ); 147 } 148 } 149}