xref: /aosp_15_r20/external/pdfium/fpdfsdk/fpdf_signature.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2020 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "public/fpdf_signature.h"
6 
7 #include <utility>
8 #include <vector>
9 
10 #include "constants/form_fields.h"
11 #include "core/fpdfapi/parser/cpdf_array.h"
12 #include "core/fpdfapi/parser/cpdf_dictionary.h"
13 #include "core/fpdfapi/parser/cpdf_document.h"
14 #include "core/fxcrt/stl_util.h"
15 #include "fpdfsdk/cpdfsdk_helpers.h"
16 #include "third_party/base/numerics/safe_conversions.h"
17 
18 namespace {
19 
CollectSignatures(CPDF_Document * doc)20 std::vector<RetainPtr<const CPDF_Dictionary>> CollectSignatures(
21     CPDF_Document* doc) {
22   std::vector<RetainPtr<const CPDF_Dictionary>> signatures;
23   const CPDF_Dictionary* root = doc->GetRoot();
24   if (!root)
25     return signatures;
26 
27   RetainPtr<const CPDF_Dictionary> acro_form = root->GetDictFor("AcroForm");
28   if (!acro_form)
29     return signatures;
30 
31   RetainPtr<const CPDF_Array> fields = acro_form->GetArrayFor("Fields");
32   if (!fields)
33     return signatures;
34 
35   CPDF_ArrayLocker locker(std::move(fields));
36   for (auto& field : locker) {
37     RetainPtr<const CPDF_Dictionary> field_dict = field->GetDict();
38     if (field_dict && field_dict->GetNameFor(pdfium::form_fields::kFT) ==
39                           pdfium::form_fields::kSig) {
40       signatures.push_back(std::move(field_dict));
41     }
42   }
43   return signatures;
44 }
45 
46 }  // namespace
47 
FPDF_GetSignatureCount(FPDF_DOCUMENT document)48 FPDF_EXPORT int FPDF_CALLCONV FPDF_GetSignatureCount(FPDF_DOCUMENT document) {
49   auto* doc = CPDFDocumentFromFPDFDocument(document);
50   if (!doc)
51     return -1;
52 
53   return fxcrt::CollectionSize<int>(CollectSignatures(doc));
54 }
55 
56 FPDF_EXPORT FPDF_SIGNATURE FPDF_CALLCONV
FPDF_GetSignatureObject(FPDF_DOCUMENT document,int index)57 FPDF_GetSignatureObject(FPDF_DOCUMENT document, int index) {
58   auto* doc = CPDFDocumentFromFPDFDocument(document);
59   if (!doc)
60     return nullptr;
61 
62   std::vector<RetainPtr<const CPDF_Dictionary>> signatures =
63       CollectSignatures(doc);
64   if (!fxcrt::IndexInBounds(signatures, index))
65     return nullptr;
66 
67   return FPDFSignatureFromCPDFDictionary(signatures[index].Get());
68 }
69 
70 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetContents(FPDF_SIGNATURE signature,void * buffer,unsigned long length)71 FPDFSignatureObj_GetContents(FPDF_SIGNATURE signature,
72                              void* buffer,
73                              unsigned long length) {
74   const CPDF_Dictionary* signature_dict =
75       CPDFDictionaryFromFPDFSignature(signature);
76   if (!signature_dict)
77     return 0;
78 
79   RetainPtr<const CPDF_Dictionary> value_dict =
80       signature_dict->GetDictFor(pdfium::form_fields::kV);
81   if (!value_dict)
82     return 0;
83 
84   ByteString contents = value_dict->GetByteStringFor("Contents");
85   const unsigned long contents_len =
86       pdfium::base::checked_cast<unsigned long>(contents.GetLength());
87   if (buffer && length >= contents_len)
88     memcpy(buffer, contents.c_str(), contents_len);
89 
90   return contents_len;
91 }
92 
93 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetByteRange(FPDF_SIGNATURE signature,int * buffer,unsigned long length)94 FPDFSignatureObj_GetByteRange(FPDF_SIGNATURE signature,
95                               int* buffer,
96                               unsigned long length) {
97   const CPDF_Dictionary* signature_dict =
98       CPDFDictionaryFromFPDFSignature(signature);
99   if (!signature_dict)
100     return 0;
101 
102   RetainPtr<const CPDF_Dictionary> value_dict =
103       signature_dict->GetDictFor(pdfium::form_fields::kV);
104   if (!value_dict)
105     return 0;
106 
107   RetainPtr<const CPDF_Array> byte_range = value_dict->GetArrayFor("ByteRange");
108   if (!byte_range)
109     return 0;
110 
111   const unsigned long byte_range_len =
112       fxcrt::CollectionSize<unsigned long>(*byte_range);
113   if (buffer && length >= byte_range_len) {
114     for (size_t i = 0; i < byte_range_len; ++i)
115       buffer[i] = byte_range->GetIntegerAt(i);
116   }
117   return byte_range_len;
118 }
119 
120 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetSubFilter(FPDF_SIGNATURE signature,char * buffer,unsigned long length)121 FPDFSignatureObj_GetSubFilter(FPDF_SIGNATURE signature,
122                               char* buffer,
123                               unsigned long length) {
124   const CPDF_Dictionary* signature_dict =
125       CPDFDictionaryFromFPDFSignature(signature);
126   if (!signature_dict)
127     return 0;
128 
129   RetainPtr<const CPDF_Dictionary> value_dict =
130       signature_dict->GetDictFor(pdfium::form_fields::kV);
131   if (!value_dict || !value_dict->KeyExist("SubFilter"))
132     return 0;
133 
134   ByteString sub_filter = value_dict->GetNameFor("SubFilter");
135   return NulTerminateMaybeCopyAndReturnLength(sub_filter, buffer, length);
136 }
137 
138 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetReason(FPDF_SIGNATURE signature,void * buffer,unsigned long length)139 FPDFSignatureObj_GetReason(FPDF_SIGNATURE signature,
140                            void* buffer,
141                            unsigned long length) {
142   const CPDF_Dictionary* signature_dict =
143       CPDFDictionaryFromFPDFSignature(signature);
144   if (!signature_dict)
145     return 0;
146 
147   RetainPtr<const CPDF_Dictionary> value_dict =
148       signature_dict->GetDictFor(pdfium::form_fields::kV);
149   if (!value_dict)
150     return 0;
151 
152   RetainPtr<const CPDF_Object> obj = value_dict->GetObjectFor("Reason");
153   if (!obj || !obj->IsString())
154     return 0;
155 
156   return Utf16EncodeMaybeCopyAndReturnLength(obj->GetUnicodeText(), buffer,
157                                              length);
158 }
159 
160 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature,char * buffer,unsigned long length)161 FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature,
162                          char* buffer,
163                          unsigned long length) {
164   const CPDF_Dictionary* signature_dict =
165       CPDFDictionaryFromFPDFSignature(signature);
166   if (!signature_dict)
167     return 0;
168 
169   RetainPtr<const CPDF_Dictionary> value_dict =
170       signature_dict->GetDictFor(pdfium::form_fields::kV);
171   if (!value_dict)
172     return 0;
173 
174   RetainPtr<const CPDF_Object> obj = value_dict->GetObjectFor("M");
175   if (!obj || !obj->IsString())
176     return 0;
177 
178   return NulTerminateMaybeCopyAndReturnLength(obj->GetString(), buffer, length);
179 }
180 
181 FPDF_EXPORT unsigned int FPDF_CALLCONV
FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature)182 FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature) {
183   int permission = 0;
184   const CPDF_Dictionary* signature_dict =
185       CPDFDictionaryFromFPDFSignature(signature);
186   if (!signature_dict)
187     return permission;
188 
189   RetainPtr<const CPDF_Dictionary> value_dict =
190       signature_dict->GetDictFor(pdfium::form_fields::kV);
191   if (!value_dict)
192     return permission;
193 
194   RetainPtr<const CPDF_Array> references = value_dict->GetArrayFor("Reference");
195   if (!references)
196     return permission;
197 
198   CPDF_ArrayLocker locker(std::move(references));
199   for (auto& reference : locker) {
200     RetainPtr<const CPDF_Dictionary> reference_dict = reference->GetDict();
201     if (!reference_dict)
202       continue;
203 
204     ByteString transform_method = reference_dict->GetNameFor("TransformMethod");
205     if (transform_method != "DocMDP")
206       continue;
207 
208     RetainPtr<const CPDF_Dictionary> transform_params =
209         reference_dict->GetDictFor("TransformParams");
210     if (!transform_params)
211       continue;
212 
213     // Valid values are 1, 2 and 3; 2 is the default.
214     permission = transform_params->GetIntegerFor("P", 2);
215     if (permission < 1 || permission > 3)
216       permission = 0;
217 
218     return permission;
219   }
220 
221   return permission;
222 }
223