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.signature; 24 25 import java.io.ByteArrayInputStream; 26 import java.io.IOException; 27 import java.io.InputStream; 28 import java.io.OutputStream; 29 30 import javax.crypto.SecretKey; 31 import javax.crypto.spec.SecretKeySpec; 32 import javax.xml.parsers.ParserConfigurationException; 33 34 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm; 35 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; 36 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; 37 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; 38 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; 39 import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces; 40 import com.sun.org.apache.xml.internal.security.utils.Constants; 41 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; 42 import org.w3c.dom.Document; 43 import org.w3c.dom.Element; 44 import org.w3c.dom.Node; 45 import org.xml.sax.SAXException; 46 47 /** 48 * Handles {@code <ds:SignedInfo>} elements 49 * This {@code SignedInfo} element includes the canonicalization algorithm, 50 * a signature algorithm, and one or more references. 51 * 52 */ 53 public class SignedInfo extends Manifest { 54 55 /** Field signatureAlgorithm */ 56 private SignatureAlgorithm signatureAlgorithm; 57 58 /** Field c14nizedBytes */ 59 private byte[] c14nizedBytes; 60 61 private Element c14nMethod; 62 private Element signatureMethod; 63 64 /** 65 * Overwrites {@link Manifest#addDocument} because it creates another 66 * Element. 67 * 68 * @param doc the {@link Document} in which {@code XMLsignature} will 69 * be placed 70 * @throws XMLSecurityException 71 */ SignedInfo(Document doc)72 public SignedInfo(Document doc) throws XMLSecurityException { 73 this(doc, XMLSignature.ALGO_ID_SIGNATURE_DSA, 74 Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS); 75 } 76 77 /** 78 * Constructs {@link SignedInfo} using given Canonicalization algorithm and 79 * Signature algorithm. 80 * 81 * @param doc {@code SignedInfo} is placed in this document 82 * @param signatureMethodURI URI representation of the Digest and 83 * Signature algorithm 84 * @param canonicalizationMethodURI URI representation of the 85 * Canonicalization method 86 * @throws XMLSecurityException 87 */ SignedInfo( Document doc, String signatureMethodURI, String canonicalizationMethodURI )88 public SignedInfo( 89 Document doc, String signatureMethodURI, String canonicalizationMethodURI 90 ) throws XMLSecurityException { 91 this(doc, signatureMethodURI, 0, canonicalizationMethodURI); 92 } 93 94 /** 95 * Constructor SignedInfo 96 * 97 * @param doc {@code SignedInfo} is placed in this document 98 * @param signatureMethodURI URI representation of the Digest and 99 * Signature algorithm 100 * @param hMACOutputLength 101 * @param canonicalizationMethodURI URI representation of the 102 * Canonicalization method 103 * @throws XMLSecurityException 104 */ SignedInfo( Document doc, String signatureMethodURI, int hMACOutputLength, String canonicalizationMethodURI )105 public SignedInfo( 106 Document doc, String signatureMethodURI, 107 int hMACOutputLength, String canonicalizationMethodURI 108 ) throws XMLSecurityException { 109 super(doc); 110 111 c14nMethod = 112 XMLUtils.createElementInSignatureSpace(getDocument(), Constants._TAG_CANONICALIZATIONMETHOD); 113 114 c14nMethod.setAttributeNS(null, Constants._ATT_ALGORITHM, canonicalizationMethodURI); 115 appendSelf(c14nMethod); 116 addReturnToSelf(); 117 118 if (hMACOutputLength > 0) { 119 this.signatureAlgorithm = 120 new SignatureAlgorithm(getDocument(), signatureMethodURI, hMACOutputLength); 121 } else { 122 this.signatureAlgorithm = new SignatureAlgorithm(getDocument(), signatureMethodURI); 123 } 124 125 signatureMethod = this.signatureAlgorithm.getElement(); 126 appendSelf(signatureMethod); 127 addReturnToSelf(); 128 } 129 130 /** 131 * @param doc 132 * @param signatureMethodElem 133 * @param canonicalizationMethodElem 134 * @throws XMLSecurityException 135 */ SignedInfo( Document doc, Element signatureMethodElem, Element canonicalizationMethodElem )136 public SignedInfo( 137 Document doc, Element signatureMethodElem, Element canonicalizationMethodElem 138 ) throws XMLSecurityException { 139 super(doc); 140 // Check this? 141 this.c14nMethod = canonicalizationMethodElem; 142 appendSelf(c14nMethod); 143 addReturnToSelf(); 144 145 this.signatureAlgorithm = 146 new SignatureAlgorithm(signatureMethodElem, null); 147 148 signatureMethod = this.signatureAlgorithm.getElement(); 149 appendSelf(signatureMethod); 150 151 addReturnToSelf(); 152 } 153 154 /** 155 * Build a {@link SignedInfo} from an {@link Element} 156 * 157 * @param element {@code SignedInfo} 158 * @param baseURI the URI of the resource where the XML instance was stored 159 * @throws XMLSecurityException 160 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html"> 161 * Question</A> 162 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0054.html"> 163 * Answer</A> 164 */ SignedInfo(Element element, String baseURI)165 public SignedInfo(Element element, String baseURI) throws XMLSecurityException { 166 this(element, baseURI, true); 167 } 168 169 /** 170 * Build a {@link SignedInfo} from an {@link Element} 171 * 172 * @param element {@code SignedInfo} 173 * @param baseURI the URI of the resource where the XML instance was stored 174 * @param secureValidation whether secure validation is enabled or not 175 * @throws XMLSecurityException 176 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html"> 177 * Question</A> 178 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0054.html"> 179 * Answer</A> 180 */ SignedInfo( Element element, String baseURI, boolean secureValidation )181 public SignedInfo( 182 Element element, String baseURI, boolean secureValidation 183 ) throws XMLSecurityException { 184 // Parse the Reference children and Id attribute in the Manifest 185 super(reparseSignedInfoElem(element, secureValidation), baseURI, secureValidation); 186 187 c14nMethod = XMLUtils.getNextElement(element.getFirstChild()); 188 signatureMethod = XMLUtils.getNextElement(c14nMethod.getNextSibling()); 189 this.signatureAlgorithm = 190 new SignatureAlgorithm(signatureMethod, this.getBaseURI(), secureValidation); 191 } 192 reparseSignedInfoElem(Element element, boolean secureValidation)193 private static Element reparseSignedInfoElem(Element element, boolean secureValidation) 194 throws XMLSecurityException { 195 /* 196 * If a custom canonicalizationMethod is used, canonicalize 197 * ds:SignedInfo, reparse it into a new document 198 * and replace the original not-canonicalized ds:SignedInfo by 199 * the re-parsed canonicalized one. 200 */ 201 Element c14nMethod = XMLUtils.getNextElement(element.getFirstChild()); 202 String c14nMethodURI = 203 c14nMethod.getAttributeNS(null, Constants._ATT_ALGORITHM); 204 if (!(c14nMethodURI.equals(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS) || 205 c14nMethodURI.equals(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS) || 206 c14nMethodURI.equals(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS) || 207 c14nMethodURI.equals(Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS) || 208 c14nMethodURI.equals(Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS) || 209 c14nMethodURI.equals(Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS))) { 210 // the c14n is not a secure one and can rewrite the URIs or like 211 // so reparse the SignedInfo to be sure 212 try { 213 Canonicalizer c14nizer = 214 Canonicalizer.getInstance(c14nMethodURI); 215 c14nizer.setSecureValidation(secureValidation); 216 217 byte[] c14nizedBytes = c14nizer.canonicalizeSubtree(element); 218 javax.xml.parsers.DocumentBuilder db = 219 XMLUtils.createDocumentBuilder(false, secureValidation); 220 try (InputStream is = new ByteArrayInputStream(c14nizedBytes)) { 221 Document newdoc = db.parse(is); 222 Node imported = element.getOwnerDocument().importNode( 223 newdoc.getDocumentElement(), true); 224 element.getParentNode().replaceChild(imported, element); 225 return (Element) imported; 226 } 227 } catch (ParserConfigurationException ex) { 228 throw new XMLSecurityException(ex); 229 } catch (IOException ex) { 230 throw new XMLSecurityException(ex); 231 } catch (SAXException ex) { 232 throw new XMLSecurityException(ex); 233 } 234 } 235 return element; 236 } 237 238 /** 239 * Tests core validation process 240 * 241 * @return true if verification was successful 242 * @throws MissingResourceFailureException 243 * @throws XMLSecurityException 244 */ verify()245 public boolean verify() 246 throws MissingResourceFailureException, XMLSecurityException { 247 return super.verifyReferences(false); 248 } 249 250 /** 251 * Tests core validation process 252 * 253 * @param followManifests defines whether the verification process has to verify referenced {@code ds:Manifest}s, too 254 * @return true if verification was successful 255 * @throws MissingResourceFailureException 256 * @throws XMLSecurityException 257 */ verify(boolean followManifests)258 public boolean verify(boolean followManifests) 259 throws MissingResourceFailureException, XMLSecurityException { 260 return super.verifyReferences(followManifests); 261 } 262 263 /** 264 * Returns getCanonicalizedOctetStream 265 * 266 * @return the canonicalization result octet stream of {@code SignedInfo} element 267 * @throws CanonicalizationException 268 * @throws InvalidCanonicalizerException 269 * @throws XMLSecurityException 270 */ getCanonicalizedOctetStream()271 public byte[] getCanonicalizedOctetStream() 272 throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException { 273 if (this.c14nizedBytes == null) { 274 Canonicalizer c14nizer = 275 Canonicalizer.getInstance(this.getCanonicalizationMethodURI()); 276 c14nizer.setSecureValidation(isSecureValidation()); 277 278 String inclusiveNamespaces = this.getInclusiveNamespaces(); 279 if (inclusiveNamespaces == null) { 280 this.c14nizedBytes = c14nizer.canonicalizeSubtree(getElement()); 281 } else { 282 this.c14nizedBytes = c14nizer.canonicalizeSubtree(getElement(), inclusiveNamespaces); 283 } 284 } 285 286 // make defensive copy 287 return this.c14nizedBytes.clone(); 288 } 289 290 /** 291 * Output the C14n stream to the given OutputStream. 292 * @param os 293 * @throws CanonicalizationException 294 * @throws InvalidCanonicalizerException 295 * @throws XMLSecurityException 296 */ signInOctetStream(OutputStream os)297 public void signInOctetStream(OutputStream os) 298 throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException { 299 if (this.c14nizedBytes == null) { 300 Canonicalizer c14nizer = 301 Canonicalizer.getInstance(this.getCanonicalizationMethodURI()); 302 c14nizer.setSecureValidation(isSecureValidation()); 303 c14nizer.setWriter(os); 304 String inclusiveNamespaces = this.getInclusiveNamespaces(); 305 306 if (inclusiveNamespaces == null) { 307 c14nizer.canonicalizeSubtree(getElement()); 308 } else { 309 c14nizer.canonicalizeSubtree(getElement(), inclusiveNamespaces); 310 } 311 } else { 312 try { 313 os.write(this.c14nizedBytes); 314 } catch (IOException e) { 315 throw new RuntimeException(e); 316 } 317 } 318 } 319 320 /** 321 * Returns the Canonicalization method URI 322 * 323 * @return the Canonicalization method URI 324 */ getCanonicalizationMethodURI()325 public String getCanonicalizationMethodURI() { 326 return c14nMethod.getAttributeNS(null, Constants._ATT_ALGORITHM); 327 } 328 329 /** 330 * Returns the Signature method URI 331 * 332 * @return the Signature method URI 333 */ getSignatureMethodURI()334 public String getSignatureMethodURI() { 335 Element signatureElement = this.getSignatureMethodElement(); 336 337 if (signatureElement != null) { 338 return signatureElement.getAttributeNS(null, Constants._ATT_ALGORITHM); 339 } 340 341 return null; 342 } 343 344 /** 345 * Method getSignatureMethodElement 346 * @return returns the SignatureMethod Element 347 * 348 */ getSignatureMethodElement()349 public Element getSignatureMethodElement() { 350 return signatureMethod; 351 } 352 353 /** 354 * Creates a SecretKey for the appropriate Mac algorithm based on a 355 * byte[] array password. 356 * 357 * @param secretKeyBytes 358 * @return the secret key for the SignedInfo element. 359 */ createSecretKey(byte[] secretKeyBytes)360 public SecretKey createSecretKey(byte[] secretKeyBytes) { 361 return new SecretKeySpec(secretKeyBytes, this.signatureAlgorithm.getJCEAlgorithmString()); 362 } 363 getSignatureAlgorithm()364 public SignatureAlgorithm getSignatureAlgorithm() { 365 return signatureAlgorithm; 366 } 367 368 /** 369 * Method getBaseLocalName 370 * {@inheritDoc} 371 * 372 */ getBaseLocalName()373 public String getBaseLocalName() { 374 return Constants._TAG_SIGNEDINFO; 375 } 376 getInclusiveNamespaces()377 public String getInclusiveNamespaces() { 378 String c14nMethodURI = getCanonicalizationMethodURI(); 379 if (!(c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#") || 380 c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#WithComments"))) { 381 return null; 382 } 383 384 Element inclusiveElement = XMLUtils.getNextElement(c14nMethod.getFirstChild()); 385 386 if (inclusiveElement != null) { 387 try { 388 String inclusiveNamespaces = 389 new InclusiveNamespaces( 390 inclusiveElement, 391 InclusiveNamespaces.ExclusiveCanonicalizationNamespace 392 ).getInclusiveNamespaces(); 393 return inclusiveNamespaces; 394 } catch (XMLSecurityException e) { 395 return null; 396 } 397 } 398 return null; 399 } 400 } 401