1 /*
2  *
3  *  Copyright (C) 2019-2020, 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 #include "dcmtk/config/osconfig.h"
24 
25 #ifdef WITH_OPENSSL
26 
27 #include "dcmtk/dcmsign/sitsfs.h"
28 #include "dcmtk/dcmdata/dcerror.h"   /* for EC_IllegalCall */
29 #include "dcmtk/dcmdata/dcfilefo.h"  /* for class DcmFileFormat */
30 #include "dcmtk/dcmdata/dcdeftag.h"  /* for DCM_DigitalSignatureUID */
31 
32 BEGIN_EXTERN_C
33 #include <openssl/ts.h>
34 #include <openssl/bio.h>
35 END_EXTERN_C
36 
37 
38 
SiTimeStampFS()39 SiTimeStampFS::SiTimeStampFS()
40 : SiTimeStamp()
41 , tsqFilename_()
42 , tsrFilename_()
43 , uidFilename_()
44 {
45 }
46 
47 
~SiTimeStampFS()48 SiTimeStampFS::~SiTimeStampFS()
49 {
50 }
51 
52 
setTSQFilename(const char * fname)53 void SiTimeStampFS::setTSQFilename(const char *fname)
54 {
55   if (fname)
56     tsqFilename_ = fname;
57     else tsqFilename_ = "";
58 }
59 
60 
setTSRFilename(const char * fname)61 void SiTimeStampFS::setTSRFilename(const char *fname)
62 {
63   if (fname)
64     tsrFilename_ = fname;
65     else tsrFilename_ = "";
66 }
67 
68 
setUIDFilename(const char * fname)69 void SiTimeStampFS::setUIDFilename(const char *fname)
70 {
71   if (fname)
72     uidFilename_ = fname;
73     else uidFilename_ = "";
74 }
75 
76 
stamp(const unsigned char * inputData,unsigned long inputDataSize)77 OFCondition SiTimeStampFS::stamp(
78     const unsigned char *inputData,
79     unsigned long inputDataSize)
80 {
81   return create_ts_query(inputData, inputDataSize);
82 }
83 
84 
write(DcmItem & item)85 OFCondition SiTimeStampFS::write(DcmItem& item)
86 {
87 
88   TS_REQ *query = getTSQ();
89   if (query == NULL)
90   {
91     DCMSIGN_ERROR("No timestamp query object available, cannot write to file.");
92     return EC_IllegalCall;
93   }
94 
95   OFCondition result = EC_Normal;
96 
97   // first we write the time stamp query file
98   if (tsqFilename_.length() == 0)
99   {
100     DCMSIGN_WARN("Name of timestamp query file not set, will not write file.");
101   }
102   else
103   {
104     BIO *out_bio = BIO_new_file(tsqFilename_.c_str(), "wb");
105     if (out_bio == NULL)
106     {
107       DCMSIGN_WARN("Unable to create time stamp query file '" << tsqFilename_ << "'");
108       result = SI_EC_CannotWriteTSQ;
109     }
110     else
111     {
112       if (!i2d_TS_REQ_bio(out_bio, query))
113       {
114         DCMSIGN_WARN("Writing time stamp query file '" << tsqFilename_ << "' failed");
115         result = SI_EC_CannotWriteTSQ;
116       }
117       BIO_free_all(out_bio);
118     }
119   }
120 
121   if (result.bad()) return result;
122 
123   // now we write the UID file
124   if (uidFilename_.length() == 0)
125   {
126     DCMSIGN_WARN("Name of UID file for time stamp query not set, will not write file.");
127   }
128   else
129   {
130     OFString uid;
131     DcmFileFormat dfile;
132     if (item.findAndGetOFString(DCM_DigitalSignatureUID, uid).good())
133     {
134       result = dfile.getDataset()->putAndInsertString(DCM_DigitalSignatureUID, uid.c_str());
135       if (result.good()) result = dfile.saveFile(uidFilename_, EXS_LittleEndianImplicit);
136     }
137     else
138     {
139       DCMSIGN_ERROR("Signature UID not found in dataset.");
140       result = EC_IllegalCall;
141     }
142   }
143 
144   return result;
145 }
146 
147 
getUIDFromFile(OFString & uid)148 OFCondition SiTimeStampFS::getUIDFromFile(OFString& uid)
149 {
150   if (uidFilename_.length() == 0)
151   {
152     DCMSIGN_ERROR("Cannot load UID file, filename not set");
153     return EC_IllegalCall;
154   }
155 
156   DcmFileFormat dfile;
157   OFCondition result = dfile.loadFile(uidFilename_);
158   if (result.good())
159   {
160     result = dfile.getDataset()->findAndGetOFString(DCM_DigitalSignatureUID, uid);
161     if (result.bad()) DCMSIGN_ERROR("No Digital Signature UID found in  UID file '" << uidFilename_ << "'");
162   }
163   else
164   {
165     DCMSIGN_ERROR("Cannot load UID file '" << uidFilename_ << "'");
166   }
167 
168   return result;
169 }
170 
171 
load_ts_query_from_file()172 OFCondition SiTimeStampFS::load_ts_query_from_file()
173 {
174   if (tsqFilename_.length() == 0)
175   {
176     DCMSIGN_ERROR("Cannot load timestamp query file, filename not set");
177     return EC_IllegalCall;
178   }
179 
180   return SiTimeStamp::load_ts_query(tsqFilename_.c_str());
181 }
182 
183 
load_ts_response_from_file()184 OFCondition SiTimeStampFS::load_ts_response_from_file()
185 {
186   if (tsrFilename_.length() == 0)
187   {
188     DCMSIGN_ERROR("Cannot load timestamp response file, filename not set");
189     return EC_IllegalCall;
190   }
191 
192   return SiTimeStamp::load_ts_response(tsrFilename_.c_str());
193 }
194 
195 
check_ts_response(DcmItem & ditem)196 OFCondition SiTimeStampFS::check_ts_response(DcmItem& ditem)
197 {
198   if (getTSQ() == NULL)
199   {
200     DCMSIGN_ERROR("Cannot check timestamp response, timestamp query not loaded");
201     return EC_IllegalCall;
202   }
203 
204   if (getTSR() == NULL)
205   {
206     DCMSIGN_ERROR("Cannot check timestamp response, not loaded");
207     return EC_IllegalCall;
208   }
209 
210   return  SiTimeStamp::check_ts_response(getTSQ(), getTSR(), ditem);
211 
212 }
213 
214 
write_ts_token(DcmItem & ditem)215 OFCondition SiTimeStampFS::write_ts_token(DcmItem& ditem)
216 {
217   return SiTimeStamp::write_ts_token(getTSR(), ditem);
218 }
219 
220 
221 
222 #else /* WITH_OPENSSL */
223 
224 int sitsfs_cc_dummy_to_keep_linker_from_moaning = 0;
225 
226 #endif
227