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