1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /**
   6  * Licensed to the Apache Software Foundation (ASF) under one
   7  * or more contributor license agreements. See the NOTICE file
   8  * distributed with this work for additional information
   9  * regarding copyright ownership. The ASF licenses this file
  10  * to you under the Apache License, Version 2.0 (the
  11  * "License"); you may not use this file except in compliance
  12  * with the License. You may obtain a copy of the License at
  13  *
  14  * http://www.apache.org/licenses/LICENSE-2.0
  15  *
  16  * Unless required by applicable law or agreed to in writing,
  17  * software distributed under the License is distributed on an
  18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  19  * KIND, either express or implied. See the License for the
  20  * specific language governing permissions and limitations
  21  * under the License.
  22  */
  23 package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations;
  24 
  25 import java.security.Key;
  26 import java.security.PublicKey;
  27 import java.security.cert.X509Certificate;
  28 import java.util.ArrayList;
  29 import java.util.List;
  30 
  31 import javax.crypto.SecretKey;
  32 
  33 import com.sun.org.apache.xml.internal.security.encryption.EncryptedKey;
  34 import com.sun.org.apache.xml.internal.security.encryption.XMLCipher;
  35 import com.sun.org.apache.xml.internal.security.encryption.XMLEncryptionException;
  36 import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi;
  37 import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver;
  38 import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants;
  39 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
  40 import org.w3c.dom.Element;
  41 
  42 /**
  43  * The <code>EncryptedKeyResolver</code> is not a generic resolver.  It can 
  44  * only be for specific instantiations, as the key being unwrapped will 
  45  * always be of a particular type and will always have been wrapped by 
  46  * another key which needs to be recursively resolved.
  47  *
  48  * The <code>EncryptedKeyResolver</code> can therefore only be instantiated
  49  * with an algorithm.  It can also be instantiated with a key (the KEK) or 
  50  * will search the static KeyResolvers to find the appropriate key.
  51  *
  52  * @author Berin Lautenbach
  53  */
  54 public class EncryptedKeyResolver extends KeyResolverSpi {
  55 
  56     /** {@link org.apache.commons.logging} logging facility */
  57     private static java.util.logging.Logger log = 
  58         java.util.logging.Logger.getLogger(EncryptedKeyResolver.class.getName());
  59 
  60     private Key kek;
  61     private String algorithm;
  62     private List<KeyResolverSpi> internalKeyResolvers;
  63 
  64     /**
  65      * Constructor for use when a KEK needs to be derived from a KeyInfo
  66      * list
  67      * @param algorithm
  68      */
  69     public EncryptedKeyResolver(String algorithm) {             
  70         kek = null;
  71         this.algorithm = algorithm;
  72     }
  73 
  74     /**
  75      * Constructor used for when a KEK has been set
  76      * @param algorithm
  77      * @param kek
  78      */
  79     public EncryptedKeyResolver(String algorithm, Key kek) {            
  80         this.algorithm = algorithm;
  81         this.kek = kek;
  82     }
  83 
  84     /**
  85      * This method is used to add a custom {@link KeyResolverSpi} to help
  86      * resolve the KEK.
  87      *
  88      * @param realKeyResolver
  89      */
  90     public void registerInternalKeyResolver(KeyResolverSpi realKeyResolver) {
  91         if (internalKeyResolvers == null) {
  92             internalKeyResolvers = new ArrayList<KeyResolverSpi>();
  93         }
  94         internalKeyResolvers.add(realKeyResolver);
  95     }
  96 
  97     /** @inheritDoc */
  98     public PublicKey engineLookupAndResolvePublicKey(
  99         Element element, String BaseURI, StorageResolver storage
 100     ) {
 101         return null;
 102     }
 103 
 104     /** @inheritDoc */
 105     public X509Certificate engineLookupResolveX509Certificate(
 106         Element element, String BaseURI, StorageResolver storage
 107     ) {
 108         return null;
 109     }
 110 
 111     /** @inheritDoc */
 112     public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
 113         Element element, String BaseURI, StorageResolver storage
 114     ) {
 115         if (log.isLoggable(java.util.logging.Level.FINE)) {
 116             log.log(java.util.logging.Level.FINE, "EncryptedKeyResolver - Can I resolve " + element.getTagName());
 117         }
 118 
 119         if (element == null) {
 120             return null;
 121         }
 122 
 123         SecretKey key = null;
 124         boolean isEncryptedKey = 
 125             XMLUtils.elementIsInEncryptionSpace(element, EncryptionConstants._TAG_ENCRYPTEDKEY);
 126         if (isEncryptedKey) {
 127             if (log.isLoggable(java.util.logging.Level.FINE)) {
 128                 log.log(java.util.logging.Level.FINE, "Passed an Encrypted Key");
 129             }
 130             try {
 131                 XMLCipher cipher = XMLCipher.getInstance();
 132                 cipher.init(XMLCipher.UNWRAP_MODE, kek);
 133                 if (internalKeyResolvers != null) {
 134                     int size = internalKeyResolvers.size();
 135                     for (int i = 0; i < size; i++) {
 136                         cipher.registerInternalKeyResolver(internalKeyResolvers.get(i));
 137                     }
 138                 }
 139                 EncryptedKey ek = cipher.loadEncryptedKey(element);
 140                 key = (SecretKey) cipher.decryptKey(ek, algorithm);
 141             } catch (XMLEncryptionException e) {
 142                 if (log.isLoggable(java.util.logging.Level.FINE)) {
 143                     log.log(java.util.logging.Level.FINE, e.getMessage(), e);
 144                 }
 145             }
 146         }
 147 
 148         return key;
 149     }
 150 }