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: DcmSignatureHelper
20  *
21  */
22 
23 #ifndef DCMSIGHLP_H
24 #define DCMSIGHLP_H
25 
26 #include "dcmtk/config/osconfig.h"
27 #include "dcmtk/ofstd/oftypes.h"     /* for Uint32 */
28 #include "dcmtk/ofstd/ofstring.h"    /* for class OFString */
29 #include "dcmtk/dcmdata/dcxfer.h"    /* for E_TransferSyntax */
30 #include "dcmtk/dcmsign/sidefine.h"  /* for DCMTK_DCMSIGN_EXPORT */
31 #include "dcmtk/dcmsign/sipurpos.h"  /* for class SiSignaturePurpose */
32 #include "dcmtk/dcmsign/sitypes.h"   /* for dcmsign enums */
33 
34 #ifdef WITH_OPENSSL
35 
36 class DcmAttributeTag;
37 class DcmItem;
38 class DcmStack;
39 class DcmTagKey;
40 class SiCertificate;
41 class SiMAC;
42 class SiPrivateKey;
43 class SiSecurityProfile;
44 class SiTimeStamp;
45 class SiTimeStampFS;
46 class SiCertificateVerifier;
47 class DcmSignature;
48 
49 /** this class provides helper functions for creating and verifying
50  *  digital signatures. It encapsulates most of the code that was part
51  *  of the main command line program "dcmsign" in prior DCMTK releases.
52  *  @remark this class is only available if DCMTK is compiled with
53  *  OpenSSL support enabled.
54  */
55 class DCMTK_DCMSIGN_EXPORT DcmSignatureHelper
56 {
57 public:
58 
59   /// default constructor
60   DcmSignatureHelper();
61 
62   /// destructor
63   virtual ~DcmSignatureHelper();
64 
65   /** locate a specific item within the given dataset.
66    * @param dataset dataset to be searched
67    * @param location location string. Format is "sequence[item]{.sequence[item]}*"
68    *   Where sequence can be (gggg,eeee) or a dictionary name and items
69    *   within sequences are counted from zero.
70    * @return pointer to the item searched if found, NULL otherwise
71    */
72   static DcmItem *locateItemforSignatureCreation(DcmItem& dataset, const char *location);
73 
74   /** read a list of attributes from a text file.
75    * The attributes can be in the form (gggg,eeee) or can be dictionary names,
76    * separated by arbitrary whitespace.
77    * @param filename file to be read from
78    * @param tagList attribute tags are added to this list
79    * @return 0 if successful, a program exit code otherwise
80    */
81   static int parseTextFile(const char *filename, DcmAttributeTag& tagList);
82 
83   /** read an attribute tag in the form "gggg,eeee" and adds it
84    * to the given attribute tag list
85    * @param c input string
86    * @param tagList list to be added to
87    * @return true if successful, false otherwise
88    */
89   static OFBool addTag(const char *c, DcmAttributeTag& tagList);
90 
91   /** print the location stack into the given stack.
92    * It is assumed that the stack top is a DigitalSignatureSequence which is not printed
93    * and that the stack bottom is the main dataset, which is also not printed.
94    * @param stack search stack, as returned by DcmSignature::findFirstSignatureItem() etc.
95    * @param str printable text returned in this string.
96    */
97   static void printSignatureItemPosition(DcmStack& stack, OFString& str);
98 
99   /** perform a signature operation on a given dataset
100    * @param dataset to sign
101    * @param key private key for signature
102    * @param cert certificate for signature
103    * @param opt_mac MAC for signature
104    * @param opt_profile security profile for signature
105    * @param opt_tagList list of attribute tags, may be NULL
106    * @param opt_signatureXfer signature transfer syntax
107    * @param dumpFile file to dump the byte stream to
108    * @param opt_sigPurpose signature purpose
109    * @param timeStamp pointer to timestamp client, may be NULL
110    * @return 0 if successful, a program exit code otherwise
111    */
112   static int do_sign(
113     DcmItem *dataset,
114     SiPrivateKey& key,
115     SiCertificate& cert,
116     SiMAC *opt_mac,
117     SiSecurityProfile *opt_profile,
118     DcmAttributeTag *opt_tagList,
119     E_TransferSyntax opt_signatureXfer,
120     FILE *dumpFile,
121     SiSignaturePurpose::E_SignaturePurposeType opt_sigPurpose,
122     SiTimeStamp *timeStamp = NULL);
123 
124   /** performs a signature operation on a sub-item within a dataset
125    * @param dataset in which to sign
126    * @param key private key for signature
127    * @param cert certificate for signature
128    * @param opt_mac MAC for signature
129    * @param opt_profile security profile for signature
130    * @param opt_tagList list of attribute tags, may be NULL
131    * @param location location string. Format is "sequence[item]{.sequence[item]}*"
132    *   Where sequence can be (gggg,eeee) or a dictionary name and items
133    *   within sequences are counted from zero.
134    * @param opt_signatureXfer signature transfer syntax
135    * @param dumpFile file to dump the byte stream to
136    * @param opt_sigPurpose signature purpose
137    * @param timeStamp pointer to timestamp client, may be NULL
138    * @return 0 if successful, a program exit code otherwise
139    */
140   static int do_sign_item(
141     DcmItem *dataset,
142     SiPrivateKey& key,
143     SiCertificate& cert,
144     SiMAC *opt_mac,
145     SiSecurityProfile *opt_profile,
146     DcmAttributeTag *opt_tagList,
147     const char *opt_location,
148     E_TransferSyntax opt_signatureXfer,
149     FILE *dumpFile,
150     SiSignaturePurpose::E_SignaturePurposeType opt_sigPurpose,
151     SiTimeStamp *timeStamp = NULL);
152 
153   /** verify all signatures in the given dataset and print results to stdout.
154    * @param dataset dataset to verify
155    * @param certVerifier certification verifier helper object
156    * @param verificationPolicy signature verification policy
157    * @param timstampPolicy timestamp verification policy
158    * @return 0 if successful, a program exit code otherwise
159    */
160   static int do_verify(
161     DcmItem *dataset,
162     SiCertificateVerifier& certVerifier,
163     E_SignatureVerificationPolicy verificationPolicy,
164     E_TimestampVerificationPolicy timstampPolicy);
165 
166   /** insert certified timestamp from file.
167    *  @param dataset in which to add timestamp
168    *  @param timeStamp handler, must not be NULL
169    */
170   static int do_insert_ts(DcmItem *dataset, SiTimeStampFS *timeStamp);
171 
172   /** remove all signatures from the given dataset, print action details.
173    * @param dataset dataset to modify
174    * @return 0 if successful, a program exit code otherwise
175    */
176   static int do_remove_all(DcmItem *dataset);
177 
178   /** remove the signature with the given UID from the dataset, print action details.
179    * @param dataset dataset to modify
180    * @param opt_location Digital Signature UID of the signature to remove
181    * @return 0 if successful, a program exit code otherwise
182    */
183   static int do_remove(
184     DcmItem *dataset,
185     const char *opt_location);
186 
187 private:
188 
189   /** scans a token from the given string and returns it. Ignores leading whitespace.
190    * @param c string to parse
191    * @param pos position within string, modified after successful scan
192    * @param key tag key returned in this parameter if return value is "tag key".
193    * @param idx index returned in this parameter if return value is "index".
194    * @return -1 for "EOF", 0 for "parse error", 1 for "tag key", 2 for "index", 3 for "period"
195    */
196   static int readNextToken(const char *c, int& pos, DcmTagKey& key, Uint32& idx);
197 
198   /** reads a complete text file (max 64K) into a memory block
199    * and returns a pointer to the memory block.
200    * memory must be freed by caller.
201    * @param filename file to be read
202    * @return pointer to memory block if successful, NULL otherwise.
203    */
204   static char *readTextFile(const char *filename);
205 
206   /** print the details of the current signature to the logger
207    *  @param sig signature object
208    *  @param stack position of the signature object in the dataset
209    *  @param count number of the signature (counter)
210    */
211   static void printSignatureDetails(DcmSignature& sig, DcmStack& stack, int count);
212 
213   /** print the details of the timestamp for the current signature to the logger
214    *  @param sig signature object
215    *  @param tsPolicy timestamp verification policy
216    */
217   static void printTimestampDetails(DcmSignature& sig, E_TimestampVerificationPolicy tsPolicy);
218 
219 };
220 
221 #endif
222 #endif
223