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: SiMACConstructor
20  *
21  */
22 
23 #ifndef SIMACCON_H
24 #define SIMACCON_H
25 
26 #include "dcmtk/config/osconfig.h"
27 
28 #ifdef WITH_OPENSSL
29 
30 #include "dcmtk/dcmsign/sitypes.h"
31 #include "dcmtk/dcmdata/dcostrmb.h"  /* for DcmOutputBufferStream */
32 #include "dcmtk/dcmdata/dcxfer.h"    /* for E_TransferSyntax */
33 #include "dcmtk/dcmdata/dcdeftag.h"
34 
35 #define INCLUDE_CSTDIO
36 #include "dcmtk/ofstd/ofstdinc.h"
37 
38 class SiMAC;
39 class DcmItem;
40 class DcmElement;
41 class DcmAttributeTag;
42 
43 /** a class that allows to feed selected parts of a DICOM dataset into the MAC generation code
44  *  @remark this class is only available if DCMTK is compiled with
45  *  OpenSSL support enabled.
46  */
47 class DCMTK_DCMSIGN_EXPORT SiMACConstructor
48 {
49 public:
50 
51   /// constructor
52   SiMACConstructor();
53 
54   /// destructor
55   virtual ~SiMACConstructor();
56 
57   /** encodes a DICOM dataset (or parts of it) as a byte stream in the format
58    *  required for DICOM digital signatures and feeds the byte stream into
59    *  the given MAC codec.
60    *  If a dump file was set with setDumpFile(), the byte stream is written
61    *  to file as well.
62    *  @param item the DICOM dataset to be encoded
63    *  @param mac the MAC codec into which the resulting byte stream is fed
64    *  @param oxfer the transfer syntax to be used when encoding the dataset.
65    *     The caller might wish to use DcmItem::canWriteXfer() to check beforehand
66    *     whether this transfer syntax can be used.
67    *  @param tagListOut upon return this parameter contains the list of attribute
68    *     tags which were fed into the MAC codec. For sequences, only the sequence
69    *     attribute tag is contained in this list; the items and elements within the items
70    *     are not encoded.
71    *  @param tagListIn optional parameter restricting the parts of the dataset
72    *     to be encoded. Only elements which are present in this list of tags,
73    *     which are signable (see DcmTagKey::isSignable()) and are present in the dataset
74    *     are encoded.  Upon verification of a signature the caller might wish to compare
75    *     tagListIn and tagListOut after successful return to see whether the lists of
76    *     attributes are the same.
77    *     If parameter is absent or NULL, a global match is assumed, i.e. all elements
78    *     of the dataset which are present and signable are encoded.
79    *  @return status code
80    */
81   OFCondition encodeDataset(
82     DcmItem& item,
83     SiMAC& mac,
84     E_TransferSyntax oxfer,
85     DcmAttributeTag &tagListOut,
86     DcmAttributeTag *tagListIn = NULL);
87 
88    /** encodes a DICOM dataset (or parts of it) as a byte stream in the format
89    *  required for DICOM digital signatures and feeds the byte stream into
90    *  the given MAC codec, for the purpose of signature verification
91    *  If a dump file was set with setDumpFile(), the byte stream is written
92    *  to file as well.
93    *  @param item the DICOM dataset to be encoded
94    *  @param mac the MAC codec into which the resulting byte stream is fed
95    *  @param oxfer the transfer syntax to be used when encoding the dataset.
96    *     The caller might wish to use DcmItem::canWriteXfer() to check beforehand
97    *     whether this transfer syntax can be used.
98    *  @param tagListIn list of elements to be encoded.
99    *  @return status code
100    */
101    OFCondition encodeDatasetForVerification(
102     DcmItem& item,
103     SiMAC& mac,
104     E_TransferSyntax oxfer,
105     DcmAttributeTag *tagListIn);
106 
107   /** encodes the contents of the digital signature sequence
108    *  except CertificateOfSigner, Signature, CertifiedTimestampType
109    *  and CertifiedTimestamp as a byte stream in the format
110    *  required for DICOM digital signatures and feeds the byte stream into
111    *  the given MAC codec.
112    *  If a dump file was set with setDumpFile(), the byte stream is written
113    *  to file as well.
114    *  @param signatureItem the DICOM digital signature item to be encoded
115    *  @param mac the MAC codec into which the resulting byte stream is fed
116    *  @param oxfer the transfer syntax to be used when encoding the dataset.
117    *     The caller might wish to use DcmItem::canWriteXfer() to check beforehand
118    *     whether this transfer syntax can be used.
119    *  @return status code
120    */
121   OFCondition encodeDigitalSignatureItem(
122     DcmItem& signatureItem,
123     SiMAC& mac,
124     E_TransferSyntax oxfer);
125 
126   /** flushes all buffers inside this object, finalizing the MAC code
127    *  @param mac the MAC codec into which the resulting byte stream is fed
128    *  @return status code
129    */
130   OFCondition flush(SiMAC& mac);
131 
132   /** dump all data that is fed into the MAC algorithm into the given file,
133    *  which must be opened and closed by caller.
134    *  @param f pointer to file already opened for writing; may be NULL.
135    */
136   void setDumpFile(FILE *f);
137 
138 private:
139 
140   /// private undefined copy constructor
141   SiMACConstructor(SiMACConstructor& arg);
142 
143   /// private undefined copy assignment operator
144   SiMACConstructor& operator=(SiMACConstructor& arg);
145 
146   /** flushes the internal buffer to the given MAC and to dumpFile if open
147    *  @param mac MAC to which the buffer content is added
148    *  @return error code from MAC
149    */
150   OFCondition flushBuffer(SiMAC& mac);
151 
152   /** feeds a DcmElement into the MAC data stream if is signable.
153    *  If the element is a sequence, all signable elements from all items are added.
154    *  @param element pointer to element, must not be NULL
155    *  @param mac MAC to use
156    *  @param oxfer transfer syntax in which data is encoded
157    *  @return status code
158    */
159   OFCondition encodeElement(DcmElement *element, SiMAC& mac, E_TransferSyntax oxfer);
160 
161   /** checks whether the attribute tag of the given DcmElement is contained
162    *  in the given list of tags.  If the list is absent (NULL), a universal match
163    *  is assumed, i.e. always returns true if element is nonzero.
164    *  Does not check whether an element is signable.
165    *  @param element pointer to element to check
166    *  @param tagList pointer to list of attribute tags, may be NULL
167    *  @return true if attribute is in tag list, false otherwise
168    */
169   static OFBool inTagList(const DcmElement *element, DcmAttributeTag *tagList);
170 
171   /// the buffer to which data is written
172   unsigned char *buf;
173 
174   /// the internal buffer stream
175   DcmOutputBufferStream stream;
176 
177   /** if nonzero, the data fed to the MAC algorithm
178    *  is also stored in this file.
179    */
180   FILE *dumpFile;
181 };
182 
183 
184 #endif
185 #endif
186