1<?php
2/*
3 * Copyright 2008-2010 GuardTime AS
4 *
5 * This file is part of the GuardTime PHP SDK.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20/**
21 * @package asn1
22 * @subpackage tsp
23 */
24
25/**
26 * TSP TSTInfo implementation.
27 *
28 * <pre>
29 * TSTInfo ::= SEQUENCE  {
30 *  version                      INTEGER  { v1(1) },
31 *  policy                       TSAPolicyId,
32 *  messageImprint               MessageImprint,
33 *  serialNumber                 INTEGER,
34 *  genTime                      GeneralizedTime,
35 *  accuracy                     Accuracy                 OPTIONAL,
36 *  ordering                     BOOLEAN             DEFAULT FALSE,
37 *  nonce                        INTEGER                  OPTIONAL,
38 *  tsa                          [0] GeneralName          OPTIONAL,
39 *  extensions                   [1] IMPLICIT Extensions   OPTIONAL
40 * }
41 * </pre>
42 *
43 * @package asn1
44 * @subpackage tsp
45 *
46 * @link http://tools.ietf.org/html/rfc3161#section-2.4.2 RFC 3161: Time-Stamp Protocol
47 */
48class TSPTSTInfo implements ASN1DEREncodable {
49
50    /**
51     * Object identifier for the TSTInfo content type.
52     */
53    const OID = "1.2.840.113549.1.9.16.1.4";
54
55    private $version;
56    private $policy;
57    private $messageImprint;
58    private $serialNumber;
59    private $genTime;
60    private $accuracy;
61    private $ordering;
62    private $nonce;
63    private $tsa;
64    private $extensions;
65
66    /**
67     * Constructs a new instance of TSPTSTInfo.
68     */
69    public function __construct() {
70    }
71
72    /**
73     * Decodes the given ASN1Sequence as TSPTSTInfo.
74     *
75     * @throws GTException
76     * @param  ASN1Sequence $object TSPTSTInfo encoded as ASN1Sequence
77     * @return void
78     */
79    public function decode($object) {
80
81        if (!$object instanceof ASN1Sequence) {
82            throw new GTException("Expecting an ASN1Sequence");
83        }
84
85        $size = $object->getObjectCount();
86
87        if ($size < 5 || $size > 10) {
88            throw new GTException("Invalid sequence size: {$size}");
89        }
90
91        $version = $object->getObjectAt(0);
92
93        if (!$version instanceof ASN1Integer) {
94            throw new GTException("Expecting an ASN1Integer");
95        }
96
97        $this->version = (int) $version->getValue();
98
99        if ($this->version !== 1) {
100            throw new GTException("Invalid version: {$this->version}");
101        }
102
103        $policy = $object->getObjectAt(1);
104
105        if (!$policy instanceof ASN1ObjectId) {
106            throw new GTException("Expecting an ASN1ObjectId");
107        }
108
109        $this->policy = $policy->getValue();
110
111        $messageImprint = new TSPMessageImprint();
112        $messageImprint->decode($object->getObjectAt(2));
113
114        $this->messageImprint = $messageImprint;
115
116        $serialNumber = $object->getObjectAt(3);
117
118        if (!$serialNumber instanceof ASN1Integer) {
119            throw new GTException("Expecting an ASN1Integer");
120        }
121
122        $this->serialNumber = $serialNumber->getValue();
123
124        $genTime = $object->getObjectAt(4);
125
126        if (!$genTime instanceof ASN1GeneralizedTime) {
127            throw new GTException("Expecting an ASN1GeneralizedTime");
128        }
129
130        $this->genTime = $genTime->getValue();
131
132        $this->ordering = false;
133
134        for ($i = 5; $i < $object->getObjectCount(); $i++) {
135
136            $item = $object->getObjectAt($i);
137
138            if ($item instanceof ASN1Sequence) {
139
140                // accuracy
141
142                $accuracy = new TSPAccuracy();
143                $accuracy->decode($item);
144
145                $this->accuracy = $accuracy;
146
147            } else if ($item instanceof ASN1Boolean) {
148
149                // ordering
150                $this->ordering = $item->getValue();
151
152            } else if ($item instanceof ASN1Integer) {
153
154                // nonce
155                $this->nonce = $item->getValue();
156
157            } else if ($item instanceof ASN1Tag) {
158
159                switch ($item->getTagValue()) {
160
161                    case 0:
162
163                        // tsa
164                        $tsa = new X509GeneralName();
165                        $tsa->decode($item->getObject());
166
167                        $this->tsa = $tsa;
168
169                        break;
170
171                    case 1:
172
173                        // extensions
174                        $set = $item->getObjectAs(ASN1_TAG_SET);
175
176                        $this->extensions = array();
177
178                        for ($i = 0; $i < $set->getObjectCount(); $i++) {
179
180                            $extension = new X509Extension();
181                            $extension->decode($set->getObjectAt($i));
182
183                            array_push($this->extensions, $extension);
184                        }
185
186                        foreach ($this->extensions as $extension) {
187                            if ($extension->isCritical()) {
188                                throw new GTException("Unknown critical extension present: {$extension->getId()}");
189                            }
190                        }
191
192                        break;
193
194                    default:
195
196                        throw new GTException("Unknown TAG in TSTINFO: " . $item->getTagValue());
197                }
198
199            } else {
200
201                throw new GTException("Unknown element in TSTINFO: " . get_class($item));
202
203            }
204
205        }
206    }
207
208    /**
209     * Encodes this TSPTSTInfo using DER.
210     *
211     * @return array byte array containing the DER encoding of this TSPTSTInfo
212     */
213    public function encodeDER() {
214
215        $sequence = new ASN1Sequence();
216
217        $sequence->add(new ASN1Integer((int) $this->version));
218        $sequence->add(new ASN1ObjectId($this->policy));
219        $sequence->add($this->messageImprint);
220        $sequence->add(new ASN1Integer($this->serialNumber));
221        $sequence->add(new ASN1GeneralizedTime($this->genTime));
222
223        if ($this->accuracy != null) {
224            $sequence->add($this->accuracy);
225        }
226
227        if ($this->ordering === true) {
228            $sequence->add(new ASN1Boolean($this->ordering));
229        }
230
231        if ($this->nonce != null) {
232            $sequence->add(new ASN1Integer($this->nonce));
233        }
234
235        if ($this->tsa != null) {
236            $tag = new ASN1Tag();
237            $tag->setTagValue(0);
238            $tag->setExplicit(true);
239            $tag->setTagClass(ASN1_TAG_CONTEXT);
240            $tag->setTagType(ASN1_TAG_CONSTRUCTED);
241            $tag->setObject($this->tsa);
242
243            $sequence->add($tag);
244
245        }
246
247        if ($this->extensions != null) {
248
249            $set = new ASN1Set();
250
251            foreach ($this->extensions as $extension) {
252                $set->add($extension);
253            }
254
255            $tag = new ASN1Tag();
256            $tag->setTagValue(1);
257            $tag->setExplicit(false);
258            $tag->setTagClass(ASN1_TAG_CONTEXT);
259            $tag->setTagType(ASN1_TAG_CONSTRUCTED);
260            $tag->setObject($set);
261
262            $sequence->add($tag);
263        }
264
265        return $sequence->encodeDER();
266    }
267
268    /**
269     * Gets the message imprint.
270     *
271     * @return TSPMessageImprint the message imprint
272     */
273    public function getMessageImprint() {
274        return $this->messageImprint;
275    }
276
277    /**
278     * Gets the policy.
279     *
280     * @return string oid
281     */
282    public function getPolicy() {
283        return $this->policy;
284    }
285
286    /**
287     * Gets the serial number.
288     *
289     * @return string serial number
290     */
291    public function getSerialNumber() {
292        return $this->serialNumber;
293    }
294
295    /**
296     * Gets the generalized time.
297     *
298     * @return string generalized time
299     */
300    public function getGenTime() {
301        return $this->genTime;
302    }
303
304    /**
305     * Gets the accuracy.
306     *
307     * @return TSPAccuracy accuracy
308     */
309    public function getAccuracy() {
310        return $this->accuracy;
311    }
312
313    /**
314     * Gets the TSA.
315     *
316     * @return X509GeneralName tsa
317     */
318    public function getTsa() {
319        return $this->tsa;
320    }
321
322    /**
323     * Gets the TSA formatted as string.
324     *
325     * @return string formatted tsa
326     */
327    public function getFormattedTsa() {
328
329        if ($this->tsa == null) {
330            return null;
331        }
332
333        return $this->tsa->getFormatted();
334    }
335
336}
337
338?>
339