1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 /* 21 * XSEC 22 * 23 * DSIG_Reference := Class for checking and setting up reference nodes in a DSIG signature 24 * 25 * $Id: DSIGReference.hpp 1894269 2021-10-14 20:25:32Z scantor $ 26 * 27 */ 28 29 #ifndef DSIGREFERENCE_INCLUDE 30 #define DSIGREFERENCE_INCLUDE 31 32 // High level include 33 #include <xsec/framework/XSECDefs.hpp> 34 35 // Xerces INcludes 36 37 #include <xercesc/dom/DOM.hpp> 38 #include <xercesc/dom/DOMNamedNodeMap.hpp> 39 40 // XSEC Includes 41 #include <xsec/utils/XSECSafeBufferFormatter.hpp> 42 #include <xsec/dsig/DSIGTransform.hpp> 43 #include <xsec/dsig/DSIGReferenceList.hpp> 44 #include <xsec/dsig/DSIGConstants.hpp> 45 46 class DSIGTransformList; 47 class DSIGTransformBase64; 48 class DSIGTransformC14n; 49 class DSIGTransformEnvelope; 50 class DSIGTransformXPath; 51 class DSIGTransformXPathFilter; 52 class DSIGTransformXSL; 53 class DSIGSignature; 54 class DSIGSignedInfo; 55 56 class TXFMBase; 57 class TXFMChain; 58 class XSECBinTXFMInputStream; 59 class XSECURIResolver; 60 class XSECEnv; 61 62 /** 63 * @ingroup pubsig 64 */ 65 66 /** 67 * @brief The class used for manipulating Reference Elements within a signature. 68 * 69 * <p>The DSIGReference class creates and manipulates (including hashing and validating) 70 * \<Reference\> elements.</p> 71 * 72 */ 73 74 class XSEC_EXPORT DSIGReference { 75 76 public: 77 78 /** @name Constructors and Destructors */ 79 //@{ 80 81 /** 82 * \brief Contructor for use with existing XML signatures or templates. 83 * 84 * <p>Create a DSIGReference object based on an already existing 85 * DSIG Reference XML node. It is assumed that the underlying 86 * DOM structure is in place and works correctly.</p> 87 * 88 * @note DSIGReference structures should only ever be created via calls to a 89 * DSIGSignature object. 90 * 91 * @param env The operating environment in which the Reference is operating 92 * @param dom The DOM node (within doc) that is to be used as the base of the reference. 93 * @see #load 94 * @see DSIGSignature#createReference 95 */ 96 97 DSIGReference(const XSECEnv * env, XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *dom); 98 99 /** 100 * \brief Contructor for use when creating new Reference structures. 101 * 102 * <p>Create a DSIGReference object that can later be used to create 103 * a new Reference structure in the DOM document.</p> 104 * 105 * @note DSIGReference structures should only ever be created via calls to a 106 * DSIGSignature object. 107 * 108 * @param env The environment object for this reference. 109 * @see #load 110 * @see DSIGSignature#createReference 111 */ 112 113 DSIGReference(const XSECEnv * env); 114 115 /** 116 * \brief Destructor. 117 * 118 * @note Does not impact any created DOM structures when destroyed. 119 * 120 * @note DSIGReferences should <em>never</em> be destroyed/deleted by 121 * applications. They are owned and managed by DSIGSignature structures. 122 */ 123 124 ~DSIGReference(); 125 126 //@} 127 128 /** @name Reference Construction and Manipulation */ 129 //@{ 130 131 /** 132 * \brief Load a DSIGReference from an existing DOM structure. 133 * 134 * <p>This function will load a Reference structure from the owner 135 * document.</p> 136 * 137 */ 138 139 void load(); 140 141 /** 142 * \brief Create a Reference structure in the document. 143 * 144 * <p>This function will create a Reference structure in the owner 145 * document. In some cases, a call to this function will be sufficient 146 * to put the required Reference in place. In other cases, calls will 147 * also need to be made to the various append*Transform methods.</p> 148 * 149 * @note The XSEC Library currently makes very little use of <em>type</em> 150 * attributes in \<Reference\> Elements. However this may of use to calling 151 * applications. 152 * 153 * @param URI The URI (data source) for this reference. Set to NULL for 154 * an anonymous reference. 155 * @param hashAlgorithmURI The type of Digest to be used (generally SHA-1) 156 * @param type A type string (as defined by XML Signature). 157 * @returns The root Reference element of the newly created DOM structure. 158 */ 159 160 XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * 161 createBlankReference(const XMLCh * URI, 162 const XMLCh * hashAlgorithmURI, 163 const XMLCh * type); 164 165 /** 166 * \brief Append an Enveloped Signature Transform to the Reference. 167 * 168 * Appends a simple enveloped-signature transform to the list of transforms 169 * in this element. 170 * 171 * @returns The newly created envelope transform. 172 * 173 */ 174 175 DSIGTransformEnvelope * appendEnvelopedSignatureTransform(); 176 177 /** 178 * \brief Append a Base64 Transform to the Reference. 179 * 180 * @returns The newly created Base64 transform. 181 */ 182 183 DSIGTransformBase64 * appendBase64Transform(); 184 185 /** 186 * \brief Append an XPath Transform to the Reference. 187 * 188 * <p> Append an XPath transform. Namespaces can be added to the 189 * transform directly using the returned <em>DSIGTransformXPath</em> 190 * structure</p> 191 * 192 * @param expr The XPath expression to be placed in the transform. 193 * @returns The newly created XPath transform 194 */ 195 196 DSIGTransformXPath * appendXPathTransform(const char * expr); 197 198 /** 199 * \brief Append an XPath-Filter2 Transform to the Reference. 200 * 201 * The returned DSIGTransformXPathFilter will have no actual filter 202 * expressions loaded, but calls can be made to 203 * DSIGTransformXPathFilter::appendTransform to add them. 204 * 205 * @returns The newly created XPath Filter transform 206 */ 207 208 DSIGTransformXPathFilter * appendXPathFilterTransform(void); 209 210 /** 211 * \brief Append an XSLT Transform to the Reference. 212 * 213 * <p>The caller must have already create the stylesheet and turned it into 214 * a DOM structure that is passed in as the stylesheet parameter.</p> 215 * 216 * @param stylesheet The stylesheet DOM structure to be placed in the reference. 217 * @returns The newly create XSLT transform 218 */ 219 220 DSIGTransformXSL * appendXSLTransform(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *stylesheet); 221 222 /** 223 * \brief Append a Canonicalization Transform to the Reference. 224 * 225 * @param canonicalizationAlgorithmURI The type of canonicalisation to be added. 226 * @returns The newly create canonicalisation transform 227 */ 228 229 DSIGTransformC14n * appendCanonicalizationTransform( 230 const XMLCh * canonicalizationAlgorithmURI 231 ); 232 233 /** 234 * \brief Append a "debug" transformer. 235 * 236 * This method allows applications to provide a TXFM that will be appended 237 * to the transform chain just prior to the application of the hash 238 * algorithm. 239 * 240 * @note This is primarily for debugging. It should not be used to modify the 241 * contents of the byte stream. 242 * 243 * @param t The TXFM element to insert. 244 */ 245 246 void setPreHashTXFM(TXFMBase * t); 247 248 /** 249 * \brief Set the Id attribute of the DSIGReference 250 * 251 * This method allows applications to set the Id attribute of the DSIGReference 252 * as described in http://www.w3.org/TR/xmldsig-core/#sec-Reference. 253 * 254 * 255 * @param id The value for this reference. 256 */ 257 void setId(const XMLCh *id); 258 259 /** 260 * \brief Set the Type attribute of the DSIGReference 261 * 262 * This method allows applications to set the Type attribute of the DSIGReference 263 * as described in http://www.w3.org/TR/xmldsig-core/#sec-Reference. 264 * 265 * 266 * @param type The value for this reference. 267 */ 268 void setType(const XMLCh *type); 269 //@} 270 271 /** @name Getting Information */ 272 //@{ 273 274 /** 275 * \brief Create an input stream based on the digested byte stream. 276 * 277 * This method allows applications to read the fully canonicalised 278 * byte stream that is hashed for a reference. 279 * 280 * All transforms are performed up to the point where they would 281 * normally be fed into the Digest function. 282 * 283 * @returns A BinInputSource of the canonicalised SignedInfo 284 */ 285 286 XSECBinTXFMInputStream * makeBinInputStream(void) const; 287 288 /** 289 * \brief Return the URI string of the Reference. 290 * 291 * @returns A pointer to the buffer (owned by the Reference) containing 292 * the value of the URI stored inthe reference 293 */ 294 295 const XMLCh * getURI() const; 296 297 /** 298 * \brief Get the Digest Algorithm URI 299 * 300 * @returns the URI associated with the Algorithm used to generate 301 * the digest 302 */ 303 getAlgorithmURI() const304 const XMLCh * getAlgorithmURI() const { 305 return mp_algorithmURI; 306 } 307 308 /** 309 * \brief Obtain the transforms for this reference 310 * 311 * Get the DSIGTransformList object for this reference. Can be used to 312 * obtain information about the transforms and also change the the transforms 313 */ 314 getTransforms(void) const315 DSIGTransformList * getTransforms(void) const { 316 return mp_transformList; 317 } 318 319 /** 320 * \brief Determine whether the reference is a manifest 321 * 322 * @returns true iff the Reference element is a Manifest reference 323 */ 324 325 bool isManifest() const; 326 327 /** 328 * \brief Get the Manifest 329 * 330 * @returns The ReferenceList containing the references in the Manifest 331 * list of this reference element. 332 */ 333 334 DSIGReferenceList * getManifestReferenceList() const; // Return list of references for a manifest object 335 336 337 //@} 338 339 /** @name Message Digest/Hash manipulation */ 340 //@{ 341 342 /** 343 * \brief Calculate the Hash value of a reference 344 * 345 * Takes the Reference URI, performs all the transforms and finally 346 * calculates the Hash value of the data using the Digest algorithm 347 * indicated in the reference 348 * 349 * @param toFill A Buffer that the raw hash will be copied into. 350 * @param maxToFill Maximum number of bytes to place in the buffer 351 * @returns The number of bytes copied into the buffer 352 */ 353 354 unsigned int calculateHash(XMLByte * toFill, unsigned int maxToFill) const; 355 356 /** 357 * \brief Read the hash from the Reference element. 358 * 359 * Reads the Base64 encoded element from the Reference element. 360 * The hash is then translated from Base64 back into raw form and 361 * written into the indicated buffer. 362 * 363 * @param toFill Pointer to the buffer where the raw hash will be written 364 * @param maxToFill Maximum bytes to write to the buffer 365 * @returns Number of bytes written 366 */ 367 368 unsigned int readHash(XMLByte *toFill, unsigned int maxToFill) const; 369 370 /** 371 * \brief Validate the Reference element 372 * 373 * Performs a #calculateHash() and a #readHash() and then compares the 374 * results. 375 * 376 * @returns true iff the hash of the data matches the hash stored 377 * in the reference. 378 */ 379 380 bool checkHash() const; 381 382 /** 383 * \brief Set the value of the hash in the Reference 384 * 385 * Hashes the data referenced by the element and then writes 386 * the Base64 encoded hash value into the Reference. 387 * 388 */ 389 390 void setHash(); 391 392 //@} 393 394 /** @name Helper (static) Functions */ 395 //@{ 396 397 /** 398 * \brief Create a Transformer chain 399 * 400 * Given a TransformList create the corresponding TXFM chain to allow 401 * the caller to read the reference byte stream 402 * 403 * @note This method is primarily for use within the XSEC library. 404 * Users wishing to get the byte stream should use the #makeBinInputStream 405 * method instead. 406 * 407 * @param input The input transformer to which the TXFMs will be applied to 408 * This is generally created from the URI attribute of the reference. 409 * @param lst The list of Transform elements from which to build the 410 * transformer list. 411 * @returns The <B>end</B> of the newly build TXFM chain. This can be 412 * read from using TXFMBase::readBytes() to give the end result of the 413 * transforms. 414 */ 415 416 static TXFMChain * createTXFMChainFromList(TXFMBase * input, 417 DSIGTransformList * lst); 418 419 /** 420 * \brief Load a Transforms list from the \<Transforms\> DOMNode. 421 * 422 * Reads the data from the XML data stored in the DOM and create 423 * the associated DSIGTrasnformList. 424 * 425 * @param transformsNode Starting node in the DOM 426 * @param formatter The formatter to be used to move from XMLCh to strings 427 * @param env Environment in which to operate 428 * @returns A pointer to the created list. 429 */ 430 431 static DSIGTransformList * loadTransforms( 432 XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *transformsNode, 433 XSECSafeBufferFormatter * formatter, 434 const XSECEnv * env); 435 436 /** 437 * \brief Create a starting point for a TXFM Chain. 438 * 439 * Uses the provided URI to find the base data that the Transformer chain 440 * will be built upon. 441 * 442 * @param doc The document that the signature is based on (used for local URIs) 443 * @param URI The URI to build the base from 444 * @param env The environment the signature is operating in 445 * @returns A base TXFM element. 446 */ 447 448 static TXFMBase * getURIBaseTXFM(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc, 449 const XMLCh * URI, 450 const XSECEnv * env); 451 452 /** 453 * \brief Load a series of references. 454 * 455 * Takes a series of \<Reference\> elements in a DOM structure 456 * and creates the corresponding ReferenceList object. 457 * 458 * @note Internal function - meant for use by the library 459 * 460 * @param env The environment in which this reference resides 461 * @param firstReference First reference in DOM structure 462 * @returns the created list. 463 */ 464 465 static DSIGReferenceList *loadReferenceListFromXML(const XSECEnv * env, 466 XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *firstReference); 467 468 /** 469 * \brief Validate a list of references. 470 * 471 * Runs through a reference list, calling verify() on each and 472 * setting the ErrroStrings for any errors found 473 * 474 * @param lst The list to verify 475 * @param errorStr The string to append any errors found to 476 * @returns true iff all the references validate successfully. 477 */ 478 479 static bool verifyReferenceList(const DSIGReferenceList * lst, safeBuffer &errorStr); 480 481 /** 482 * \brief Hash a reference list 483 * 484 * Run through a list of references and calculate the hash value of each 485 * element. Finally set the Base64 encoded string according to the newly 486 * calcuated hash. 487 * 488 * @note This is an internal library function and should not be called directly. 489 * 490 * @param list The list of references 491 * @param interlocking If set to false, the library will assume there 492 * are no inter-related references. The algorithm for determining this 493 * internally is very primitive and CPU intensive, so this is a method to 494 * bypass the checks. 495 */ 496 static void hashReferenceList(const DSIGReferenceList * list, bool interlocking = true); 497 498 //@} 499 500 private: 501 502 // Internal functions 503 void createTransformList(void); 504 void addTransform( 505 DSIGTransform * txfm, 506 XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * txfmElt 507 ); 508 509 510 XSECSafeBufferFormatter * mp_formatter; 511 XERCES_CPP_NAMESPACE_QUALIFIER DOMNode 512 * mp_referenceNode; // Points to start of document where reference node is 513 mutable TXFMBase * mp_preHash; // To be used pre-hash 514 DSIGReferenceList * mp_manifestList; // The list of references in a manifest 515 const XMLCh * mp_URI; // The URI String 516 bool m_isManifest; // Does this reference a manifest? 517 XERCES_CPP_NAMESPACE_QUALIFIER DOMNode 518 * mp_transformsNode; 519 XERCES_CPP_NAMESPACE_QUALIFIER DOMNode 520 * mp_hashValueNode; // Node where the Hash value is stored 521 const XSECEnv * mp_env; 522 DSIGTransformList * mp_transformList; // List of transforms 523 const XMLCh * mp_algorithmURI; // Hash algorithm for this reference 524 525 bool m_loaded; 526 527 DSIGReference(); 528 529 /*\@}*/ 530 531 friend class DSIGSignedInfo; 532 }; 533 534 #endif /* #define DSIGREFERENCE_INCLUDE */ 535