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 /*
  24  * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  25  */
  26 /*
  27  * $Id: DOMKeyInfoFactory.java 1854026 2019-02-21 09:30:01Z coheigea $
  28  */
  29 package org.jcp.xml.dsig.internal.dom;
  30 
  31 import java.math.BigInteger;
  32 import java.security.KeyException;
  33 import java.security.PublicKey;
  34 import java.security.interfaces.ECPublicKey;
  35 import java.security.interfaces.DSAPublicKey;
  36 import java.security.interfaces.RSAPublicKey;
  37 import java.util.List;
  38 
  39 import javax.xml.crypto.MarshalException;
  40 import javax.xml.crypto.URIDereferencer;
  41 import javax.xml.crypto.XMLStructure;
  42 import javax.xml.crypto.dom.DOMCryptoContext;
  43 import javax.xml.crypto.dsig.XMLSignature;
  44 import javax.xml.crypto.dsig.keyinfo.KeyInfo;
  45 import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
  46 import javax.xml.crypto.dsig.keyinfo.KeyName;
  47 import javax.xml.crypto.dsig.keyinfo.KeyValue;
  48 import javax.xml.crypto.dsig.keyinfo.PGPData;
  49 import javax.xml.crypto.dsig.keyinfo.RetrievalMethod;
  50 import javax.xml.crypto.dsig.keyinfo.X509Data;
  51 import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial;
  52 
  53 import org.w3c.dom.Document;
  54 import org.w3c.dom.Element;
  55 import org.w3c.dom.Node;
  56 
  57 /**
  58  * DOM-based implementation of KeyInfoFactory.
  59  *
  60  */
  61 public final class DOMKeyInfoFactory extends KeyInfoFactory {
  62 
  63     public DOMKeyInfoFactory() { }
  64 
  65     @SuppressWarnings("rawtypes")
  66     public KeyInfo newKeyInfo(List content) {
  67         return newKeyInfo(content, null);
  68     }
  69 
  70     @SuppressWarnings({ "unchecked", "rawtypes" })
  71     public KeyInfo newKeyInfo(List content, String id) {
  72         return new DOMKeyInfo(content, id);
  73     }
  74 
  75     public KeyName newKeyName(String name) {
  76         return new DOMKeyName(name);
  77     }
  78 
  79     public KeyValue newKeyValue(PublicKey key)  throws KeyException {
  80         String algorithm = key.getAlgorithm();
  81         if ("DSA".equals(algorithm)) {
  82             return new DOMKeyValue.DSA((DSAPublicKey) key);
  83         } else if ("RSA".equals(algorithm)) {
  84             return new DOMKeyValue.RSA((RSAPublicKey) key);
  85         } else if ("EC".equals(algorithm)) {
  86             return new DOMKeyValue.EC((ECPublicKey) key);
  87         } else {
  88             throw new KeyException("unsupported key algorithm: " + algorithm);
  89         }
  90     }
  91 
  92     public PGPData newPGPData(byte[] keyId) {
  93         return newPGPData(keyId, null, null);
  94     }
  95 
  96     @SuppressWarnings({ "rawtypes", "unchecked" })
  97     public PGPData newPGPData(byte[] keyId, byte[] keyPacket, List other) {
  98         return new DOMPGPData(keyId, keyPacket, other);
  99     }
 100 
 101     @SuppressWarnings({ "rawtypes", "unchecked" })
 102     public PGPData newPGPData(byte[] keyPacket, List other) {
 103         return new DOMPGPData(keyPacket, other);
 104     }
 105 
 106     public RetrievalMethod newRetrievalMethod(String uri) {
 107         return newRetrievalMethod(uri, null, null);
 108     }
 109 
 110     @SuppressWarnings({ "rawtypes", "unchecked" })
 111     public RetrievalMethod newRetrievalMethod(String uri, String type,
 112         List transforms) {
 113         if (uri == null) {
 114             throw new NullPointerException("uri must not be null");
 115         }
 116         return new DOMRetrievalMethod(uri, type, transforms);
 117     }
 118 
 119     @SuppressWarnings({ "rawtypes" })
 120     public X509Data newX509Data(List content) {
 121         return new DOMX509Data(content);
 122     }
 123 
 124     @Override
 125     public X509IssuerSerial newX509IssuerSerial(String issuerName,
 126         BigInteger serialNumber) {
 127         return new DOMX509IssuerSerial(issuerName, serialNumber);
 128     }
 129 
 130     public boolean isFeatureSupported(String feature) {
 131         if (feature == null) {
 132             throw new NullPointerException();
 133         } else {
 134             return false;
 135         }
 136     }
 137 
 138     public URIDereferencer getURIDereferencer() {
 139         return DOMURIDereferencer.INSTANCE;
 140     }
 141 
 142     @Override
 143     public KeyInfo unmarshalKeyInfo(XMLStructure xmlStructure)
 144         throws MarshalException {
 145         if (xmlStructure == null) {
 146             throw new NullPointerException("xmlStructure cannot be null");
 147         }
 148         if (!(xmlStructure instanceof javax.xml.crypto.dom.DOMStructure)) {
 149             throw new ClassCastException("xmlStructure must be of type DOMStructure");
 150         }
 151         Node node =
 152             ((javax.xml.crypto.dom.DOMStructure) xmlStructure).getNode();
 153         node.normalize();
 154 
 155         Element element = null;
 156         if (node.getNodeType() == Node.DOCUMENT_NODE) {
 157             element = ((Document) node).getDocumentElement();
 158         } else if (node.getNodeType() == Node.ELEMENT_NODE) {
 159             element = (Element) node;
 160         } else {
 161             throw new MarshalException
 162                 ("xmlStructure does not contain a proper Node");
 163         }
 164 
 165         // check tag
 166         String tag = element.getLocalName();
 167         String namespace = element.getNamespaceURI();
 168         if (tag == null || namespace == null) {
 169             throw new MarshalException("Document implementation must " +
 170                 "support DOM Level 2 and be namespace aware");
 171         }
 172         if ("KeyInfo".equals(tag) && XMLSignature.XMLNS.equals(namespace)) {
 173             try {
 174                 return new DOMKeyInfo(element, new UnmarshalContext(), getProvider());
 175             } catch (MarshalException me) {
 176                 throw me;
 177             } catch (Exception e) {
 178                 throw new MarshalException(e);
 179             }
 180         } else {
 181             throw new MarshalException("Invalid KeyInfo tag: " + namespace + ":" + tag);
 182         }
 183     }
 184 
 185     private static class UnmarshalContext extends DOMCryptoContext {
 186         UnmarshalContext() {}
 187     }
 188 
 189 }