1 /* 2 * 3 * Copyright (C) 1998-2019, OFFIS e.V. 4 * All rights reserved. See COPYRIGHT file for details. 5 * 6 * This software and supporting documentation were developed by 7 * 8 * OFFIS e.V. 9 * R&D Division Health 10 * Escherweg 2 11 * D-26121 Oldenburg, Germany 12 * 13 * 14 * Module: dcmsign 15 * 16 * Author: Marco Eichelberg 17 * 18 * Purpose: 19 * classes: SiTimeStamp 20 * 21 */ 22 23 #ifndef SITSTAMP_H 24 #define SITSTAMP_H 25 26 #include "dcmtk/config/osconfig.h" 27 28 #ifdef WITH_OPENSSL 29 30 #include "dcmtk/dcmsign/sitypes.h" 31 #include "dcmtk/ofstd/ofstring.h" 32 33 // forward declarations 34 class DcmItem; 35 class SiCertificateVerifier; 36 class SiCertificate; 37 struct TS_req_st; 38 struct TS_resp_st; 39 struct TS_tst_info_st; 40 typedef struct TS_req_st TS_REQ; 41 typedef struct TS_resp_st TS_RESP; 42 typedef struct TS_tst_info_st TS_TST_INFO; 43 typedef struct pkcs7_st PKCS7; 44 45 /** Base class for a timestamp client. 46 * Instances of derived classes are able to request timestamps from a timestamp service. 47 * This class implements the code needed to create a timestamp request and to insert 48 * a timestamp reply into a DICOM dataset, but not the protocol for actually 49 * interacting with a timestamp authority. 50 * @remark this class is only available if DCMTK is compiled with OpenSSL support enabled. 51 */ 52 class DCMTK_DCMSIGN_EXPORT SiTimeStamp 53 { 54 public: 55 56 /// default constructor 57 SiTimeStamp(); 58 59 /// destructor 60 virtual ~SiTimeStamp(); 61 62 /** takes a block of raw data and requests a time stamp for this raw data. 63 * @param inputData pointer to raw data 64 * @param inputDataSize length of raw data block in bytes 65 * @return status code 66 */ 67 virtual OFCondition stamp( 68 const unsigned char *inputData, 69 unsigned long inputDataSize) = 0; 70 71 /** reads the current timestamp from an item of the Digital Signatures Sequence 72 * and creates a timestamp ticket object. 73 * @param item item of the DigitalSignatureSQ from which the timestamp is read 74 * @return status code 75 */ 76 virtual OFCondition read(DcmItem& item); 77 78 /** writes the current timestamp into an item of the Digital Signatures Sequence 79 * and creates the timestamp type information in the item. 80 * @param item item of the DigitalSignatureSQ to which the timestamp is written 81 * @return status code 82 */ 83 virtual OFCondition write(DcmItem& item) = 0; 84 85 /** set the requested policy OID to be included into the time stamp query 86 * @param oid policy OID, NULL for no policy (which is the default). 87 */ 88 virtual void setPolicyOID(const char *oid); 89 90 /** sets the flag controlling whether or not a nonce is included 91 * into the timestamp query. Since a nonce is a protection against replay 92 * attack, normally it should be included, and this is also the default. 93 * @param nonce OFTrue if nonce should be included, OFFalse otherwise 94 */ 95 virtual void setNonce(OFBool nonce); 96 97 /** sets the flag controlling whether the timestamp authority will be 98 * requested to include its certificate into the timestamp reply. 99 * A timestamp reply with certificate is easier to verify, as less 100 * external key material is required, but somewhat larger. 101 * Default is OFTrue; 102 * @param creq OFTrue if certificate should be requested, OFFalse otherwise 103 */ 104 virtual void setCertificateRequested(OFBool creq); 105 106 /** sets the message authentication code to be used for creating 107 * the hash value in the timestamp query. Default is SHA256. 108 * @param creq OFTrue if certificate should be requested, OFFalse otherwise 109 */ 110 virtual void setMAC(E_MACType mac); 111 112 // methods that return the various attributes of a timestamp ticket 113 114 /** checks if this object contains a timestamp ticket info object 115 * @return OFTrue if timestamp ticket info available, OFFalse otherwise 116 */ 117 virtual OFBool have_tsinfo() const; 118 119 /** returns the timestamp ticket info version number 120 * @return tsinfo version number if available, -1 otherwise 121 */ 122 virtual long get_tsinfo_version() const; 123 124 /** returns the timestamp ticket info policy OID 125 * @param oid upon return, contains the policy OID if available, an empty string otherwise 126 */ 127 virtual void get_tsinfo_policy_oid(OFString& oid) const; 128 129 /** returns the timestamp ticket info MAC algorithm name 130 * @param mac upon return, contains the MAC algorithm name if available, an empty string otherwise 131 */ 132 virtual void get_tsinfo_imprint_algorithm_name(OFString& mac) const; 133 134 /** returns the timestamp ticket info serial number 135 * @param serial upon return, contains the serial number if available, an empty string otherwise 136 */ 137 virtual void get_tsinfo_serial_number(OFString& serial) const; 138 139 /** returns the timestamp ticket info nonce, if present 140 * @param nonce upon return, contains the nonce if available, an empty string otherwise 141 */ 142 virtual void get_tsinfo_nonce(OFString& nonce) const; 143 144 /** returns the timestamp ticket info timestamp authority (TSA) name, if present 145 * @param tsa upon return, contains the TSA name if available, an empty string otherwise 146 */ 147 virtual void get_tsinfo_tsa_name(OFString& tsa) const; 148 149 /** returns the timestamp ticket info ordering flag 150 * @return OFTrue if timestamp ticket is present and contains an ordering flag with value "true", OFFalse otherwise 151 */ 152 virtual OFBool get_tsinfo_ordering() const; 153 154 /** returns the timestamp ticket info accuracy, if present 155 * @param accuracy upon return, contains the accuracy if available, an empty string otherwise 156 */ 157 virtual void get_tsinfo_accuracy(OFString& accuracy) const; 158 159 /** returns the timestamp date/time information, if present 160 * @param ts upon return, contains the timestamp date/time information, an empty string otherwise 161 */ 162 virtual void get_tsinfo_timestamp(OFString& ts) const; 163 164 /** returns the number of extensions in the timestamp ticket 165 * @return number of extensions in the timestamp ticket 166 */ 167 virtual int get_tsinfo_numextensions() const; 168 169 /** returns one timestamp extension, if present 170 * @param ext upon return, contains the timestamp extension if present, an empty string otherwise 171 * @param idx number of the extension, 0 <= idx < get_tsinfo_numextensions(). 172 */ 173 virtual void get_tsinfo_extension(OFString& ext, int idx) const; 174 175 /** this method performs the following functions: 176 * - it checks if there is one and only one signer. 177 * - it identifies the signer certificate (which may be embedded in the timestamp, or loaded in the SiCertificateVerifier store) 178 * - it checks the extended key usage and key usage fields of the signer certificate 179 * - it verifies the certificate path 180 * - it checks if the certificate path meets the requirements of the 181 * SigningCertificate ESS signed attribute. 182 * - it verifies the signature value (against the imprint in the timestamp token 183 * - it prints the contents of the signer certificate to the logger 184 * @param cv container for the certificates used during verification 185 * @return EC_Normal upon success, an error code otherwise. 186 */ 187 virtual OFCondition verifyTSSignature(SiCertificateVerifier& cv); 188 189 /** Verify the timestamp token by checking that its imprint is 190 * indeed a hash of the DICOM signature, that the version number 191 * is as expected and that the TSA name, if provided in the timestamp 192 * ticket structure, matches the name of the TSA given in the TSA 193 * certificate. 194 * @param cv container for the certificates used during verification 195 * @param ditem item of the Digital Signatures Sequence containing the timestamp 196 * @param cert certificate of the signer of the DICOM signature, used to check 197 * the date/time of the timestamp against the validity period of the certificate 198 * @return EC_Normal upon success, an error code otherwise. 199 */ 200 virtual OFCondition verifyTSToken( 201 SiCertificateVerifier& cv, 202 DcmItem& ditem, 203 SiCertificate& cert); 204 205 /** returns an error string containing a textual description of the result 206 * of the last call to verifyTSSignature() or verifyTSToken() 207 * if that call returned SI_EC_TimestampSignatureVerificationFailed. 208 * @param err text string returned in this parameter 209 */ 210 void lastError(OFString& err) const; 211 212 protected: 213 214 /** takes a block of raw data, computes a message digest and creates 215 * a time stamp query object. 216 * @param inputData pointer to raw data 217 * @param inputDataSize length of raw data block in bytes 218 * @return status code 219 */ 220 virtual OFCondition create_ts_query( 221 const unsigned char *inputData, 222 unsigned long inputDataSize); 223 224 /** return pointer to timestamp query object, may be NULL. 225 * @return pointer to timestamp query object, may be NULL. 226 */ getTSQ()227 virtual TS_REQ *getTSQ() { return tsq_; } 228 229 /** return pointer to timestamp response object, may be NULL. 230 * @return pointer to timestamp response object, may be NULL. 231 */ getTSR()232 virtual TS_RESP *getTSR() { return tsr_; } 233 234 /** return pointer to timestamp ticket object, may be NULL. 235 * @return pointer to timestamp ticket object, may be NULL. 236 */ getTS()237 virtual PKCS7 *getTS() { return ts_; } 238 239 /** return pointer to timestamp ticket info object, may be NULL. 240 * @return pointer to timestamp ticket info object, may be NULL. 241 */ getTSInfo()242 virtual TS_TST_INFO *getTSInfo() { return tsinfo_; } 243 244 /** load timestamp query from file 245 * @param fname filename, must not be NULL 246 * @return status code 247 */ 248 virtual OFCondition load_ts_query(const char *fname); 249 250 /** load timestamp response from file 251 * @param fname filename, must not be NULL 252 * @return status code 253 */ 254 virtual OFCondition load_ts_response(const char *fname); 255 256 /** check consistency between timestamp query (if available), timestamp 257 * response and DICOM digital signature. 258 * @param tsq pointer to timestamp query, may be NULL 259 * @param tsr pointer to timestamp response, must not be NULL 260 * @param ditem item of the DigitalSignaturesSequence to which this timestamp belongs 261 * @return status code 262 */ 263 static OFCondition check_ts_response( 264 TS_REQ *tsq, 265 TS_RESP *tsr, 266 DcmItem& ditem); 267 268 /** insert timestamp token into DICOM dataset 269 * The timestamp response must have been checked prior to this method call. 270 * @param tsr pointer to timestamp response, must not be NULL 271 * @param ditem item of the DigitalSignaturesSequence to which this timestamp is written 272 * @return status code 273 */ 274 static OFCondition write_ts_token( 275 TS_RESP *tsr, 276 DcmItem& ditem); 277 278 private: 279 280 /// time stamping policy OID to be included in the time stamp query. Default is empty. 281 OFString tsq_policy_; 282 283 /// MAC algorithm for creating the hash key to be timestamped. Default is SHA-256. 284 E_MACType tsq_mac_; 285 286 /// Use a pseudo-random nonce in the time stamp query. Default is OFTrue. 287 OFBool tsq_use_nonce_; 288 289 /// Request the TSA certificate to be embedded into the time stamp reply. Default is OFTrue. 290 OFBool tsq_certificate_requested_; 291 292 /// pointer to time stamp request object, may be NULL 293 TS_REQ *tsq_; 294 295 /// pointer to time stamp response object, may be NULL 296 TS_RESP *tsr_; 297 298 /// pointer to time stamp ticket object, may be NULL 299 PKCS7 *ts_; 300 301 /// pointer to time stamp ticket info object (extracted from the timestamp ticket), may be NULL 302 TS_TST_INFO *tsinfo_; 303 304 /// OpenSSL X.509 certificate verification error code for the last operation 305 long errorCode_; 306 307 /// error string for the last operation, valid if errorCode_ < 0 308 const char *errorString_; 309 310 }; 311 312 #endif 313 #endif 314