Branch data Line data Source code
1 : : /* crypto/ts/ts_resp_sign.c */
2 : : /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
3 : : * project 2002.
4 : : */
5 : : /* ====================================================================
6 : : * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
7 : : *
8 : : * Redistribution and use in source and binary forms, with or without
9 : : * modification, are permitted provided that the following conditions
10 : : * are met:
11 : : *
12 : : * 1. Redistributions of source code must retain the above copyright
13 : : * notice, this list of conditions and the following disclaimer.
14 : : *
15 : : * 2. Redistributions in binary form must reproduce the above copyright
16 : : * notice, this list of conditions and the following disclaimer in
17 : : * the documentation and/or other materials provided with the
18 : : * distribution.
19 : : *
20 : : * 3. All advertising materials mentioning features or use of this
21 : : * software must display the following acknowledgment:
22 : : * "This product includes software developed by the OpenSSL Project
23 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 : : *
25 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 : : * endorse or promote products derived from this software without
27 : : * prior written permission. For written permission, please contact
28 : : * licensing@OpenSSL.org.
29 : : *
30 : : * 5. Products derived from this software may not be called "OpenSSL"
31 : : * nor may "OpenSSL" appear in their names without prior written
32 : : * permission of the OpenSSL Project.
33 : : *
34 : : * 6. Redistributions of any form whatsoever must retain the following
35 : : * acknowledgment:
36 : : * "This product includes software developed by the OpenSSL Project
37 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 : : *
39 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
51 : : * ====================================================================
52 : : *
53 : : * This product includes cryptographic software written by Eric Young
54 : : * (eay@cryptsoft.com). This product includes software written by Tim
55 : : * Hudson (tjh@cryptsoft.com).
56 : : *
57 : : */
58 : :
59 : : #include "cryptlib.h"
60 : :
61 : : #if defined(OPENSSL_SYS_UNIX)
62 : : #include <sys/time.h>
63 : : #endif
64 : :
65 : : #include <openssl/objects.h>
66 : : #include <openssl/ts.h>
67 : : #include <openssl/pkcs7.h>
68 : :
69 : : /* Private function declarations. */
70 : :
71 : : static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *, void *);
72 : : static int def_time_cb(struct TS_resp_ctx *, void *, long *sec, long *usec);
73 : : static int def_extension_cb(struct TS_resp_ctx *, X509_EXTENSION *, void *);
74 : :
75 : : static void TS_RESP_CTX_init(TS_RESP_CTX *ctx);
76 : : static void TS_RESP_CTX_cleanup(TS_RESP_CTX *ctx);
77 : : static int TS_RESP_check_request(TS_RESP_CTX *ctx);
78 : : static ASN1_OBJECT *TS_RESP_get_policy(TS_RESP_CTX *ctx);
79 : : static TS_TST_INFO *TS_RESP_create_tst_info(TS_RESP_CTX *ctx,
80 : : ASN1_OBJECT *policy);
81 : : static int TS_RESP_process_extensions(TS_RESP_CTX *ctx);
82 : : static int TS_RESP_sign(TS_RESP_CTX *ctx);
83 : :
84 : : static ESS_SIGNING_CERT *ESS_SIGNING_CERT_new_init(X509 *signcert,
85 : : STACK_OF(X509) *certs);
86 : : static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed);
87 : : static int TS_TST_INFO_content_new(PKCS7 *p7);
88 : : static int ESS_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc);
89 : :
90 : : static ASN1_GENERALIZEDTIME *TS_RESP_set_genTime_with_precision(
91 : : ASN1_GENERALIZEDTIME *, long, long, unsigned);
92 : :
93 : : /* Default callbacks for response generation. */
94 : :
95 : 0 : static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *ctx, void *data)
96 : : {
97 : 0 : ASN1_INTEGER *serial = ASN1_INTEGER_new();
98 [ # # ]: 0 : if (!serial) goto err;
99 [ # # ]: 0 : if (!ASN1_INTEGER_set(serial, 1)) goto err;
100 : : return serial;
101 : : err:
102 : 0 : TSerr(TS_F_DEF_SERIAL_CB, ERR_R_MALLOC_FAILURE);
103 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
104 : : "Error during serial number generation.");
105 : 0 : return NULL;
106 : : }
107 : :
108 : : #if defined(OPENSSL_SYS_UNIX)
109 : :
110 : : /* Use the gettimeofday function call. */
111 : 3 : static int def_time_cb(struct TS_resp_ctx *ctx, void *data,
112 : : long *sec, long *usec)
113 : : {
114 : : struct timeval tv;
115 [ - + ]: 3 : if (gettimeofday(&tv, NULL) != 0)
116 : : {
117 : 0 : TSerr(TS_F_DEF_TIME_CB, TS_R_TIME_SYSCALL_ERROR);
118 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
119 : : "Time is not available.");
120 : 0 : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_TIME_NOT_AVAILABLE);
121 : 0 : return 0;
122 : : }
123 : : /* Return time to caller. */
124 : 3 : *sec = tv.tv_sec;
125 : 3 : *usec = tv.tv_usec;
126 : :
127 : 3 : return 1;
128 : : }
129 : :
130 : : #else
131 : :
132 : : /* Use the time function call that provides only seconds precision. */
133 : : static int def_time_cb(struct TS_resp_ctx *ctx, void *data,
134 : : long *sec, long *usec)
135 : : {
136 : : time_t t;
137 : : if (time(&t) == (time_t) -1)
138 : : {
139 : : TSerr(TS_F_DEF_TIME_CB, TS_R_TIME_SYSCALL_ERROR);
140 : : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
141 : : "Time is not available.");
142 : : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_TIME_NOT_AVAILABLE);
143 : : return 0;
144 : : }
145 : : /* Return time to caller, only second precision. */
146 : : *sec = (long) t;
147 : : *usec = 0;
148 : :
149 : : return 1;
150 : : }
151 : :
152 : : #endif
153 : :
154 : 0 : static int def_extension_cb(struct TS_resp_ctx *ctx, X509_EXTENSION *ext,
155 : : void *data)
156 : : {
157 : : /* No extensions are processed here. */
158 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
159 : : "Unsupported extension.");
160 : 0 : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_UNACCEPTED_EXTENSION);
161 : 0 : return 0;
162 : : }
163 : :
164 : : /* TS_RESP_CTX management functions. */
165 : :
166 : 3 : TS_RESP_CTX *TS_RESP_CTX_new()
167 : : {
168 : : TS_RESP_CTX *ctx;
169 : :
170 [ - + ]: 3 : if (!(ctx = (TS_RESP_CTX *) OPENSSL_malloc(sizeof(TS_RESP_CTX))))
171 : : {
172 : 0 : TSerr(TS_F_TS_RESP_CTX_NEW, ERR_R_MALLOC_FAILURE);
173 : 0 : return NULL;
174 : : }
175 : : memset(ctx, 0, sizeof(TS_RESP_CTX));
176 : :
177 : : /* Setting default callbacks. */
178 : 3 : ctx->serial_cb = def_serial_cb;
179 : 3 : ctx->time_cb = def_time_cb;
180 : 3 : ctx->extension_cb = def_extension_cb;
181 : :
182 : 3 : return ctx;
183 : : }
184 : :
185 : 3 : void TS_RESP_CTX_free(TS_RESP_CTX *ctx)
186 : : {
187 [ + - ]: 3 : if (!ctx) return;
188 : :
189 : 3 : X509_free(ctx->signer_cert);
190 : 3 : EVP_PKEY_free(ctx->signer_key);
191 : 3 : sk_X509_pop_free(ctx->certs, X509_free);
192 : 3 : sk_ASN1_OBJECT_pop_free(ctx->policies, ASN1_OBJECT_free);
193 : 3 : ASN1_OBJECT_free(ctx->default_policy);
194 : 3 : sk_EVP_MD_free(ctx->mds); /* No EVP_MD_free method exists. */
195 : 3 : ASN1_INTEGER_free(ctx->seconds);
196 : 3 : ASN1_INTEGER_free(ctx->millis);
197 : 3 : ASN1_INTEGER_free(ctx->micros);
198 : 3 : OPENSSL_free(ctx);
199 : : }
200 : :
201 : 3 : int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer)
202 : : {
203 [ - + ]: 3 : if (X509_check_purpose(signer, X509_PURPOSE_TIMESTAMP_SIGN, 0) != 1)
204 : : {
205 : 0 : TSerr(TS_F_TS_RESP_CTX_SET_SIGNER_CERT,
206 : : TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE);
207 : 0 : return 0;
208 : : }
209 [ - + ]: 3 : if (ctx->signer_cert) X509_free(ctx->signer_cert);
210 : 3 : ctx->signer_cert = signer;
211 : 3 : CRYPTO_add(&ctx->signer_cert->references, +1, CRYPTO_LOCK_X509);
212 : 3 : return 1;
213 : : }
214 : :
215 : 3 : int TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key)
216 : : {
217 [ - + ]: 3 : if (ctx->signer_key) EVP_PKEY_free(ctx->signer_key);
218 : 3 : ctx->signer_key = key;
219 : 3 : CRYPTO_add(&ctx->signer_key->references, +1, CRYPTO_LOCK_EVP_PKEY);
220 : :
221 : 3 : return 1;
222 : : }
223 : :
224 : 3 : int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, ASN1_OBJECT *def_policy)
225 : : {
226 [ - + ]: 3 : if (ctx->default_policy) ASN1_OBJECT_free(ctx->default_policy);
227 [ - + ]: 3 : if (!(ctx->default_policy = OBJ_dup(def_policy))) goto err;
228 : : return 1;
229 : : err:
230 : 0 : TSerr(TS_F_TS_RESP_CTX_SET_DEF_POLICY, ERR_R_MALLOC_FAILURE);
231 : 0 : return 0;
232 : : }
233 : :
234 : 3 : int TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs)
235 : : {
236 : :
237 [ - + ]: 3 : if (ctx->certs)
238 : : {
239 : 0 : sk_X509_pop_free(ctx->certs, X509_free);
240 : 0 : ctx->certs = NULL;
241 : : }
242 [ + - ]: 3 : if (!certs) return 1;
243 [ - + ]: 3 : if (!(ctx->certs = X509_chain_up_ref(certs)))
244 : : {
245 : 0 : TSerr(TS_F_TS_RESP_CTX_SET_CERTS, ERR_R_MALLOC_FAILURE);
246 : 0 : return 0;
247 : : }
248 : :
249 : : return 1;
250 : : }
251 : :
252 : 6 : int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, ASN1_OBJECT *policy)
253 : : {
254 : 6 : ASN1_OBJECT *copy = NULL;
255 : :
256 : : /* Create new policy stack if necessary. */
257 [ + + ][ + - ]: 6 : if (!ctx->policies && !(ctx->policies = sk_ASN1_OBJECT_new_null()))
258 : : goto err;
259 [ + - ]: 6 : if (!(copy = OBJ_dup(policy))) goto err;
260 [ - + ]: 6 : if (!sk_ASN1_OBJECT_push(ctx->policies, copy)) goto err;
261 : :
262 : : return 1;
263 : : err:
264 : 0 : TSerr(TS_F_TS_RESP_CTX_ADD_POLICY, ERR_R_MALLOC_FAILURE);
265 : 0 : ASN1_OBJECT_free(copy);
266 : 0 : return 0;
267 : : }
268 : :
269 : 6 : int TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md)
270 : : {
271 : : /* Create new md stack if necessary. */
272 [ + + ][ + - ]: 6 : if (!ctx->mds && !(ctx->mds = sk_EVP_MD_new_null()))
273 : : goto err;
274 : : /* Add the shared md, no copy needed. */
275 [ - + ]: 6 : if (!sk_EVP_MD_push(ctx->mds, (EVP_MD *)md)) goto err;
276 : :
277 : : return 1;
278 : : err:
279 : 0 : TSerr(TS_F_TS_RESP_CTX_ADD_MD, ERR_R_MALLOC_FAILURE);
280 : 0 : return 0;
281 : : }
282 : :
283 : : #define TS_RESP_CTX_accuracy_free(ctx) \
284 : : ASN1_INTEGER_free(ctx->seconds); \
285 : : ctx->seconds = NULL; \
286 : : ASN1_INTEGER_free(ctx->millis); \
287 : : ctx->millis = NULL; \
288 : : ASN1_INTEGER_free(ctx->micros); \
289 : : ctx->micros = NULL;
290 : :
291 : 3 : int TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx,
292 : : int secs, int millis, int micros)
293 : : {
294 : :
295 : 3 : TS_RESP_CTX_accuracy_free(ctx);
296 [ + - ][ + - ]: 3 : if (secs && (!(ctx->seconds = ASN1_INTEGER_new())
297 [ + - ]: 3 : || !ASN1_INTEGER_set(ctx->seconds, secs)))
298 : : goto err;
299 [ + - ][ + - ]: 3 : if (millis && (!(ctx->millis = ASN1_INTEGER_new())
300 [ + - ]: 3 : || !ASN1_INTEGER_set(ctx->millis, millis)))
301 : : goto err;
302 [ + - ][ + - ]: 3 : if (micros && (!(ctx->micros = ASN1_INTEGER_new())
303 [ - + ]: 3 : || !ASN1_INTEGER_set(ctx->micros, micros)))
304 : : goto err;
305 : :
306 : : return 1;
307 : : err:
308 : 0 : TS_RESP_CTX_accuracy_free(ctx);
309 : 0 : TSerr(TS_F_TS_RESP_CTX_SET_ACCURACY, ERR_R_MALLOC_FAILURE);
310 : 0 : return 0;
311 : : }
312 : :
313 : 9 : void TS_RESP_CTX_add_flags(TS_RESP_CTX *ctx, int flags)
314 : : {
315 : 9 : ctx->flags |= flags;
316 : 9 : }
317 : :
318 : 3 : void TS_RESP_CTX_set_serial_cb(TS_RESP_CTX *ctx, TS_serial_cb cb, void *data)
319 : : {
320 : 3 : ctx->serial_cb = cb;
321 : 3 : ctx->serial_cb_data = data;
322 : 3 : }
323 : :
324 : 0 : void TS_RESP_CTX_set_time_cb(TS_RESP_CTX *ctx, TS_time_cb cb, void *data)
325 : : {
326 : 0 : ctx->time_cb = cb;
327 : 0 : ctx->time_cb_data = data;
328 : 0 : }
329 : :
330 : 0 : void TS_RESP_CTX_set_extension_cb(TS_RESP_CTX *ctx,
331 : : TS_extension_cb cb, void *data)
332 : : {
333 : 0 : ctx->extension_cb = cb;
334 : 0 : ctx->extension_cb_data = data;
335 : 0 : }
336 : :
337 : 3 : int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx,
338 : : int status, const char *text)
339 : : {
340 : 3 : TS_STATUS_INFO *si = NULL;
341 : 3 : ASN1_UTF8STRING *utf8_text = NULL;
342 : 3 : int ret = 0;
343 : :
344 [ + - ]: 3 : if (!(si = TS_STATUS_INFO_new())) goto err;
345 [ + - ]: 3 : if (!ASN1_INTEGER_set(si->status, status)) goto err;
346 [ - + ]: 3 : if (text)
347 : : {
348 [ # # ]: 0 : if (!(utf8_text = ASN1_UTF8STRING_new())
349 [ # # ]: 0 : || !ASN1_STRING_set(utf8_text, text, strlen(text)))
350 : : goto err;
351 [ # # ][ # # ]: 0 : if (!si->text && !(si->text = sk_ASN1_UTF8STRING_new_null()))
352 : : goto err;
353 [ # # ]: 0 : if (!sk_ASN1_UTF8STRING_push(si->text, utf8_text)) goto err;
354 : : utf8_text = NULL; /* Ownership is lost. */
355 : : }
356 [ + - ]: 3 : if (!TS_RESP_set_status_info(ctx->response, si)) goto err;
357 : 3 : ret = 1;
358 : : err:
359 [ - + ]: 3 : if (!ret)
360 : 0 : TSerr(TS_F_TS_RESP_CTX_SET_STATUS_INFO, ERR_R_MALLOC_FAILURE);
361 : 3 : TS_STATUS_INFO_free(si);
362 : 3 : ASN1_UTF8STRING_free(utf8_text);
363 : 3 : return ret;
364 : : }
365 : :
366 : 0 : int TS_RESP_CTX_set_status_info_cond(TS_RESP_CTX *ctx,
367 : : int status, const char *text)
368 : : {
369 : 0 : int ret = 1;
370 : 0 : TS_STATUS_INFO *si = TS_RESP_get_status_info(ctx->response);
371 : :
372 [ # # ]: 0 : if (ASN1_INTEGER_get(si->status) == TS_STATUS_GRANTED)
373 : : {
374 : : /* Status has not been set, set it now. */
375 : 0 : ret = TS_RESP_CTX_set_status_info(ctx, status, text);
376 : : }
377 : 0 : return ret;
378 : : }
379 : :
380 : 0 : int TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure)
381 : : {
382 : 0 : TS_STATUS_INFO *si = TS_RESP_get_status_info(ctx->response);
383 [ # # ][ # # ]: 0 : if (!si->failure_info && !(si->failure_info = ASN1_BIT_STRING_new()))
384 : : goto err;
385 [ # # ]: 0 : if (!ASN1_BIT_STRING_set_bit(si->failure_info, failure, 1))
386 : : goto err;
387 : : return 1;
388 : : err:
389 : 0 : TSerr(TS_F_TS_RESP_CTX_ADD_FAILURE_INFO, ERR_R_MALLOC_FAILURE);
390 : 0 : return 0;
391 : : }
392 : :
393 : 0 : TS_REQ *TS_RESP_CTX_get_request(TS_RESP_CTX *ctx)
394 : : {
395 : 0 : return ctx->request;
396 : : }
397 : :
398 : 0 : TS_TST_INFO *TS_RESP_CTX_get_tst_info(TS_RESP_CTX *ctx)
399 : : {
400 : 0 : return ctx->tst_info;
401 : : }
402 : :
403 : 3 : int TS_RESP_CTX_set_clock_precision_digits(TS_RESP_CTX *ctx, unsigned precision)
404 : : {
405 [ + - ]: 3 : if (precision > TS_MAX_CLOCK_PRECISION_DIGITS)
406 : : return 0;
407 : 3 : ctx->clock_precision_digits = precision;
408 : 3 : return 1;
409 : : }
410 : :
411 : : /* Main entry method of the response generation. */
412 : 3 : TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio)
413 : : {
414 : : ASN1_OBJECT *policy;
415 : : TS_RESP *response;
416 : 3 : int result = 0;
417 : :
418 : 3 : TS_RESP_CTX_init(ctx);
419 : :
420 : : /* Creating the response object. */
421 [ - + ]: 3 : if (!(ctx->response = TS_RESP_new()))
422 : : {
423 : 0 : TSerr(TS_F_TS_RESP_CREATE_RESPONSE, ERR_R_MALLOC_FAILURE);
424 : 0 : goto end;
425 : : }
426 : :
427 : : /* Parsing DER request. */
428 [ - + ]: 3 : if (!(ctx->request = d2i_TS_REQ_bio(req_bio, NULL)))
429 : : {
430 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
431 : : "Bad request format or "
432 : : "system error.");
433 : 0 : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT);
434 : 0 : goto end;
435 : : }
436 : :
437 : : /* Setting default status info. */
438 [ + - ]: 3 : if (!TS_RESP_CTX_set_status_info(ctx, TS_STATUS_GRANTED, NULL))
439 : : goto end;
440 : :
441 : : /* Checking the request format. */
442 [ + - ]: 3 : if (!TS_RESP_check_request(ctx)) goto end;
443 : :
444 : : /* Checking acceptable policies. */
445 [ + - ]: 3 : if (!(policy = TS_RESP_get_policy(ctx))) goto end;
446 : :
447 : : /* Creating the TS_TST_INFO object. */
448 [ + - ]: 3 : if (!(ctx->tst_info = TS_RESP_create_tst_info(ctx, policy)))
449 : : goto end;
450 : :
451 : : /* Processing extensions. */
452 [ + - ]: 3 : if (!TS_RESP_process_extensions(ctx)) goto end;
453 : :
454 : : /* Generating the signature. */
455 [ + - ]: 3 : if (!TS_RESP_sign(ctx)) goto end;
456 : :
457 : : /* Everything was successful. */
458 : 3 : result = 1;
459 : : end:
460 [ - + ]: 3 : if (!result)
461 : : {
462 : 0 : TSerr(TS_F_TS_RESP_CREATE_RESPONSE, TS_R_RESPONSE_SETUP_ERROR);
463 [ # # ]: 0 : if (ctx->response != NULL)
464 : : {
465 [ # # ]: 0 : if (TS_RESP_CTX_set_status_info_cond(ctx,
466 : : TS_STATUS_REJECTION, "Error during response "
467 : : "generation.") == 0)
468 : : {
469 : 0 : TS_RESP_free(ctx->response);
470 : 0 : ctx->response = NULL;
471 : : }
472 : : }
473 : : }
474 : 3 : response = ctx->response;
475 : 3 : ctx->response = NULL; /* Ownership will be returned to caller. */
476 : 3 : TS_RESP_CTX_cleanup(ctx);
477 : 3 : return response;
478 : : }
479 : :
480 : : /* Initializes the variable part of the context. */
481 : 3 : static void TS_RESP_CTX_init(TS_RESP_CTX *ctx)
482 : : {
483 : 3 : ctx->request = NULL;
484 : 3 : ctx->response = NULL;
485 : 3 : ctx->tst_info = NULL;
486 : 3 : }
487 : :
488 : : /* Cleans up the variable part of the context. */
489 : 3 : static void TS_RESP_CTX_cleanup(TS_RESP_CTX *ctx)
490 : : {
491 : 3 : TS_REQ_free(ctx->request);
492 : 3 : ctx->request = NULL;
493 : 3 : TS_RESP_free(ctx->response);
494 : 3 : ctx->response = NULL;
495 : 3 : TS_TST_INFO_free(ctx->tst_info);
496 : 3 : ctx->tst_info = NULL;
497 : 3 : }
498 : :
499 : : /* Checks the format and content of the request. */
500 : 3 : static int TS_RESP_check_request(TS_RESP_CTX *ctx)
501 : : {
502 : 3 : TS_REQ *request = ctx->request;
503 : : TS_MSG_IMPRINT *msg_imprint;
504 : : X509_ALGOR *md_alg;
505 : : int md_alg_id;
506 : : const ASN1_OCTET_STRING *digest;
507 : 3 : EVP_MD *md = NULL;
508 : : int i;
509 : :
510 : : /* Checking request version. */
511 [ - + ]: 3 : if (TS_REQ_get_version(request) != 1)
512 : : {
513 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
514 : : "Bad request version.");
515 : 0 : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_REQUEST);
516 : 0 : return 0;
517 : : }
518 : :
519 : : /* Checking message digest algorithm. */
520 : 3 : msg_imprint = TS_REQ_get_msg_imprint(request);
521 : 3 : md_alg = TS_MSG_IMPRINT_get_algo(msg_imprint);
522 : 3 : md_alg_id = OBJ_obj2nid(md_alg->algorithm);
523 [ + + ][ + - ]: 9 : for (i = 0; !md && i < sk_EVP_MD_num(ctx->mds); ++i)
524 : : {
525 : 6 : EVP_MD *current_md = sk_EVP_MD_value(ctx->mds, i);
526 [ + + ]: 6 : if (md_alg_id == EVP_MD_type(current_md))
527 : 3 : md = current_md;
528 : : }
529 [ - + ]: 3 : if (!md)
530 : : {
531 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
532 : : "Message digest algorithm is "
533 : : "not supported.");
534 : 0 : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_ALG);
535 : 0 : return 0;
536 : : }
537 : :
538 : : /* No message digest takes parameter. */
539 [ + - ]: 3 : if (md_alg->parameter
540 [ - + ]: 3 : && ASN1_TYPE_get(md_alg->parameter) != V_ASN1_NULL)
541 : : {
542 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
543 : : "Superfluous message digest "
544 : : "parameter.");
545 : 0 : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_ALG);
546 : 0 : return 0;
547 : : }
548 : : /* Checking message digest size. */
549 : 3 : digest = TS_MSG_IMPRINT_get_msg(msg_imprint);
550 [ - + ]: 3 : if (digest->length != EVP_MD_size(md))
551 : : {
552 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
553 : : "Bad message digest.");
554 : 0 : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT);
555 : 0 : return 0;
556 : : }
557 : :
558 : : return 1;
559 : : }
560 : :
561 : : /* Returns the TSA policy based on the requested and acceptable policies. */
562 : 3 : static ASN1_OBJECT *TS_RESP_get_policy(TS_RESP_CTX *ctx)
563 : : {
564 : 3 : ASN1_OBJECT *requested = TS_REQ_get_policy_id(ctx->request);
565 : 3 : ASN1_OBJECT *policy = NULL;
566 : : int i;
567 : :
568 [ - + ]: 3 : if (ctx->default_policy == NULL)
569 : : {
570 : 0 : TSerr(TS_F_TS_RESP_GET_POLICY, TS_R_INVALID_NULL_POINTER);
571 : 0 : return NULL;
572 : : }
573 : : /* Return the default policy if none is requested or the default is
574 : : requested. */
575 [ + - ][ + + ]: 3 : if (!requested || !OBJ_cmp(requested, ctx->default_policy))
576 : 3 : policy = ctx->default_policy;
577 : :
578 : : /* Check if the policy is acceptable. */
579 [ + + ][ + - ]: 5 : for (i = 0; !policy && i < sk_ASN1_OBJECT_num(ctx->policies); ++i)
580 : : {
581 : 2 : ASN1_OBJECT *current = sk_ASN1_OBJECT_value(ctx->policies, i);
582 [ + - ]: 2 : if (!OBJ_cmp(requested, current))
583 : 2 : policy = current;
584 : : }
585 [ - + ]: 3 : if (!policy)
586 : : {
587 : 0 : TSerr(TS_F_TS_RESP_GET_POLICY, TS_R_UNACCEPTABLE_POLICY);
588 : 0 : TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
589 : : "Requested policy is not "
590 : : "supported.");
591 : 0 : TS_RESP_CTX_add_failure_info(ctx, TS_INFO_UNACCEPTED_POLICY);
592 : : }
593 : 3 : return policy;
594 : : }
595 : :
596 : : /* Creates the TS_TST_INFO object based on the settings of the context. */
597 : 3 : static TS_TST_INFO *TS_RESP_create_tst_info(TS_RESP_CTX *ctx,
598 : : ASN1_OBJECT *policy)
599 : : {
600 : 3 : int result = 0;
601 : 3 : TS_TST_INFO *tst_info = NULL;
602 : 3 : ASN1_INTEGER *serial = NULL;
603 : 3 : ASN1_GENERALIZEDTIME *asn1_time = NULL;
604 : : long sec, usec;
605 : 3 : TS_ACCURACY *accuracy = NULL;
606 : : const ASN1_INTEGER *nonce;
607 : 3 : GENERAL_NAME *tsa_name = NULL;
608 : :
609 [ + - ]: 3 : if (!(tst_info = TS_TST_INFO_new())) goto end;
610 [ + - ]: 3 : if (!TS_TST_INFO_set_version(tst_info, 1)) goto end;
611 [ + - ]: 3 : if (!TS_TST_INFO_set_policy_id(tst_info, policy)) goto end;
612 [ + - ]: 3 : if (!TS_TST_INFO_set_msg_imprint(tst_info, ctx->request->msg_imprint))
613 : : goto end;
614 [ + - ]: 3 : if (!(serial = (*ctx->serial_cb)(ctx, ctx->serial_cb_data))
615 [ + - ]: 3 : || !TS_TST_INFO_set_serial(tst_info, serial))
616 : : goto end;
617 [ + - ]: 3 : if (!(*ctx->time_cb)(ctx, ctx->time_cb_data, &sec, &usec)
618 [ + - ]: 3 : || !(asn1_time = TS_RESP_set_genTime_with_precision(NULL,
619 : : sec, usec,
620 : : ctx->clock_precision_digits))
621 [ + - ]: 3 : || !TS_TST_INFO_set_time(tst_info, asn1_time))
622 : : goto end;
623 : :
624 : : /* Setting accuracy if needed. */
625 [ - + ][ # # ]: 3 : if ((ctx->seconds || ctx->millis || ctx->micros)
[ # # ]
626 [ + - ]: 3 : && !(accuracy = TS_ACCURACY_new()))
627 : : goto end;
628 : :
629 [ + - ][ + - ]: 3 : if (ctx->seconds && !TS_ACCURACY_set_seconds(accuracy, ctx->seconds))
630 : : goto end;
631 [ + - ][ + - ]: 3 : if (ctx->millis && !TS_ACCURACY_set_millis(accuracy, ctx->millis))
632 : : goto end;
633 [ + - ][ + - ]: 3 : if (ctx->micros && !TS_ACCURACY_set_micros(accuracy, ctx->micros))
634 : : goto end;
635 [ + - ][ + - ]: 3 : if (accuracy && !TS_TST_INFO_set_accuracy(tst_info, accuracy))
636 : : goto end;
637 : :
638 : : /* Setting ordering. */
639 [ + - ]: 3 : if ((ctx->flags & TS_ORDERING)
640 [ + - ]: 3 : && !TS_TST_INFO_set_ordering(tst_info, 1))
641 : : goto end;
642 : :
643 : : /* Setting nonce if needed. */
644 [ + + ]: 3 : if ((nonce = TS_REQ_get_nonce(ctx->request)) != NULL
645 [ + - ]: 1 : && !TS_TST_INFO_set_nonce(tst_info, nonce))
646 : : goto end;
647 : :
648 : : /* Setting TSA name to subject of signer certificate. */
649 [ + - ]: 3 : if (ctx->flags & TS_TSA_NAME)
650 : : {
651 [ + - ]: 3 : if (!(tsa_name = GENERAL_NAME_new())) goto end;
652 : 3 : tsa_name->type = GEN_DIRNAME;
653 : 3 : tsa_name->d.dirn =
654 : 3 : X509_NAME_dup(ctx->signer_cert->cert_info->subject);
655 [ + - ]: 3 : if (!tsa_name->d.dirn) goto end;
656 [ + - ]: 3 : if (!TS_TST_INFO_set_tsa(tst_info, tsa_name)) goto end;
657 : : }
658 : :
659 : : result = 1;
660 : : end:
661 [ - + ]: 3 : if (!result)
662 : : {
663 : 0 : TS_TST_INFO_free(tst_info);
664 : 0 : tst_info = NULL;
665 : 0 : TSerr(TS_F_TS_RESP_CREATE_TST_INFO, TS_R_TST_INFO_SETUP_ERROR);
666 : 0 : TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION,
667 : : "Error during TSTInfo "
668 : : "generation.");
669 : : }
670 : 3 : GENERAL_NAME_free(tsa_name);
671 : 3 : TS_ACCURACY_free(accuracy);
672 : 3 : ASN1_GENERALIZEDTIME_free(asn1_time);
673 : 3 : ASN1_INTEGER_free(serial);
674 : :
675 : 3 : return tst_info;
676 : : }
677 : :
678 : : /* Processing the extensions of the request. */
679 : 3 : static int TS_RESP_process_extensions(TS_RESP_CTX *ctx)
680 : : {
681 : 3 : STACK_OF(X509_EXTENSION) *exts = TS_REQ_get_exts(ctx->request);
682 : : int i;
683 : 3 : int ok = 1;
684 : :
685 [ + - ][ - + ]: 3 : for (i = 0; ok && i < sk_X509_EXTENSION_num(exts); ++i)
686 : : {
687 : 0 : X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
688 : : /* XXXXX The last argument was previously
689 : : (void *)ctx->extension_cb, but ISO C doesn't permit
690 : : converting a function pointer to void *. For lack of
691 : : better information, I'm placing a NULL there instead.
692 : : The callback can pick its own address out from the ctx
693 : : anyway...
694 : : */
695 : 0 : ok = (*ctx->extension_cb)(ctx, ext, NULL);
696 : : }
697 : :
698 : 3 : return ok;
699 : : }
700 : :
701 : : /* Functions for signing the TS_TST_INFO structure of the context. */
702 : 3 : static int TS_RESP_sign(TS_RESP_CTX *ctx)
703 : : {
704 : 3 : int ret = 0;
705 : 3 : PKCS7 *p7 = NULL;
706 : : PKCS7_SIGNER_INFO *si;
707 : : STACK_OF(X509) *certs; /* Certificates to include in sc. */
708 : 3 : ESS_SIGNING_CERT *sc = NULL;
709 : : ASN1_OBJECT *oid;
710 : 3 : BIO *p7bio = NULL;
711 : : int i;
712 : :
713 : : /* Check if signcert and pkey match. */
714 [ - + ]: 3 : if (!X509_check_private_key(ctx->signer_cert, ctx->signer_key)) {
715 : 0 : TSerr(TS_F_TS_RESP_SIGN,
716 : : TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
717 : 0 : goto err;
718 : : }
719 : :
720 : : /* Create a new PKCS7 signed object. */
721 [ - + ]: 3 : if (!(p7 = PKCS7_new())) {
722 : 0 : TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE);
723 : 0 : goto err;
724 : : }
725 [ + - ]: 3 : if (!PKCS7_set_type(p7, NID_pkcs7_signed)) goto err;
726 : :
727 : : /* Force SignedData version to be 3 instead of the default 1. */
728 [ + - ]: 3 : if (!ASN1_INTEGER_set(p7->d.sign->version, 3)) goto err;
729 : :
730 : : /* Add signer certificate and optional certificate chain. */
731 [ + + ]: 3 : if (TS_REQ_get_cert_req(ctx->request))
732 : : {
733 : 1 : PKCS7_add_certificate(p7, ctx->signer_cert);
734 [ + - ]: 1 : if (ctx->certs)
735 : : {
736 [ + + ]: 2 : for(i = 0; i < sk_X509_num(ctx->certs); ++i)
737 : : {
738 : 1 : X509 *cert = sk_X509_value(ctx->certs, i);
739 : 1 : PKCS7_add_certificate(p7, cert);
740 : : }
741 : : }
742 : : }
743 : :
744 : : /* Add a new signer info. */
745 [ - + ]: 3 : if (!(si = PKCS7_add_signature(p7, ctx->signer_cert,
746 : : ctx->signer_key, EVP_sha1())))
747 : : {
748 : 0 : TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNATURE_ERROR);
749 : 0 : goto err;
750 : : }
751 : :
752 : : /* Add content type signed attribute to the signer info. */
753 : 3 : oid = OBJ_nid2obj(NID_id_smime_ct_TSTInfo);
754 [ - + ]: 3 : if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
755 : : V_ASN1_OBJECT, oid))
756 : : {
757 : 0 : TSerr(TS_F_TS_RESP_SIGN, TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR);
758 : 0 : goto err;
759 : : }
760 : :
761 : : /* Create the ESS SigningCertificate attribute which contains
762 : : the signer certificate id and optionally the certificate chain. */
763 [ + - ]: 3 : certs = ctx->flags & TS_ESS_CERT_ID_CHAIN ? ctx->certs : NULL;
764 [ + - ]: 3 : if (!(sc = ESS_SIGNING_CERT_new_init(ctx->signer_cert, certs)))
765 : : goto err;
766 : :
767 : : /* Add SigningCertificate signed attribute to the signer info. */
768 [ - + ]: 3 : if (!ESS_add_signing_cert(si, sc))
769 : : {
770 : 0 : TSerr(TS_F_TS_RESP_SIGN, TS_R_ESS_ADD_SIGNING_CERT_ERROR);
771 : 0 : goto err;
772 : : }
773 : :
774 : : /* Add a new empty NID_id_smime_ct_TSTInfo encapsulated content. */
775 [ + - ]: 3 : if (!TS_TST_INFO_content_new(p7)) goto err;
776 : :
777 : : /* Add the DER encoded tst_info to the PKCS7 structure. */
778 [ - + ]: 3 : if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
779 : 0 : TSerr(TS_F_TS_RESP_SIGN, ERR_R_MALLOC_FAILURE);
780 : 0 : goto err;
781 : : }
782 : :
783 : : /* Convert tst_info to DER. */
784 [ - + ]: 3 : if (!i2d_TS_TST_INFO_bio(p7bio, ctx->tst_info))
785 : : {
786 : 0 : TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN);
787 : 0 : goto err;
788 : : }
789 : :
790 : : /* Create the signature and add it to the signer info. */
791 [ - + ]: 3 : if (!PKCS7_dataFinal(p7, p7bio))
792 : : {
793 : 0 : TSerr(TS_F_TS_RESP_SIGN, TS_R_TS_DATASIGN);
794 : 0 : goto err;
795 : : }
796 : :
797 : : /* Set new PKCS7 and TST_INFO objects. */
798 : 3 : TS_RESP_set_tst_info(ctx->response, p7, ctx->tst_info);
799 : 3 : p7 = NULL; /* Ownership is lost. */
800 : 3 : ctx->tst_info = NULL; /* Ownership is lost. */
801 : :
802 : 3 : ret = 1;
803 : : err:
804 [ - + ]: 3 : if (!ret)
805 : 0 : TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION,
806 : : "Error during signature "
807 : : "generation.");
808 : 3 : BIO_free_all(p7bio);
809 : 3 : ESS_SIGNING_CERT_free(sc);
810 : 3 : PKCS7_free(p7);
811 : 3 : return ret;
812 : : }
813 : :
814 : 3 : static ESS_SIGNING_CERT *ESS_SIGNING_CERT_new_init(X509 *signcert,
815 : : STACK_OF(X509) *certs)
816 : : {
817 : : ESS_CERT_ID *cid;
818 : 3 : ESS_SIGNING_CERT *sc = NULL;
819 : : int i;
820 : :
821 : : /* Creating the ESS_CERT_ID stack. */
822 [ + - ]: 3 : if (!(sc = ESS_SIGNING_CERT_new())) goto err;
823 [ - + ][ # # ]: 3 : if (!sc->cert_ids && !(sc->cert_ids = sk_ESS_CERT_ID_new_null()))
824 : : goto err;
825 : :
826 : : /* Adding the signing certificate id. */
827 [ + - ]: 3 : if (!(cid = ESS_CERT_ID_new_init(signcert, 0))
828 [ + - ]: 3 : || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
829 : : goto err;
830 : : /* Adding the certificate chain ids. */
831 [ + + ]: 6 : for (i = 0; i < sk_X509_num(certs); ++i)
832 : : {
833 : 3 : X509 *cert = sk_X509_value(certs, i);
834 [ + - ]: 3 : if (!(cid = ESS_CERT_ID_new_init(cert, 1))
835 [ + - ]: 3 : || !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
836 : : goto err;
837 : : }
838 : :
839 : : return sc;
840 : : err:
841 : 0 : ESS_SIGNING_CERT_free(sc);
842 : 0 : TSerr(TS_F_ESS_SIGNING_CERT_NEW_INIT, ERR_R_MALLOC_FAILURE);
843 : 0 : return NULL;
844 : : }
845 : :
846 : 6 : static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
847 : : {
848 : 6 : ESS_CERT_ID *cid = NULL;
849 : 6 : GENERAL_NAME *name = NULL;
850 : :
851 : : /* Recompute SHA1 hash of certificate if necessary (side effect). */
852 : 6 : X509_check_purpose(cert, -1, 0);
853 : :
854 [ + - ]: 6 : if (!(cid = ESS_CERT_ID_new())) goto err;
855 [ + - ]: 6 : if (!ASN1_OCTET_STRING_set(cid->hash, cert->sha1_hash,
856 : : sizeof(cert->sha1_hash)))
857 : : goto err;
858 : :
859 : : /* Setting the issuer/serial if requested. */
860 [ + + ]: 6 : if (issuer_needed)
861 : : {
862 : : /* Creating issuer/serial structure. */
863 [ + - ]: 3 : if (!cid->issuer_serial
864 [ + - ]: 3 : && !(cid->issuer_serial = ESS_ISSUER_SERIAL_new()))
865 : : goto err;
866 : : /* Creating general name from the certificate issuer. */
867 [ + - ]: 3 : if (!(name = GENERAL_NAME_new())) goto err;
868 : 3 : name->type = GEN_DIRNAME;
869 [ + - ]: 3 : if (!(name->d.dirn = X509_NAME_dup(cert->cert_info->issuer)))
870 : : goto err;
871 [ + - ]: 3 : if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name))
872 : : goto err;
873 : 3 : name = NULL; /* Ownership is lost. */
874 : : /* Setting the serial number. */
875 : 3 : ASN1_INTEGER_free(cid->issuer_serial->serial);
876 [ + - ]: 3 : if (!(cid->issuer_serial->serial =
877 : 3 : ASN1_INTEGER_dup(cert->cert_info->serialNumber)))
878 : : goto err;
879 : : }
880 : :
881 : 6 : return cid;
882 : : err:
883 : 0 : GENERAL_NAME_free(name);
884 : 0 : ESS_CERT_ID_free(cid);
885 : 0 : TSerr(TS_F_ESS_CERT_ID_NEW_INIT, ERR_R_MALLOC_FAILURE);
886 : 0 : return NULL;
887 : : }
888 : :
889 : 3 : static int TS_TST_INFO_content_new(PKCS7 *p7)
890 : : {
891 : 3 : PKCS7 *ret = NULL;
892 : 3 : ASN1_OCTET_STRING *octet_string = NULL;
893 : :
894 : : /* Create new encapsulated NID_id_smime_ct_TSTInfo content. */
895 [ + - ]: 3 : if (!(ret = PKCS7_new())) goto err;
896 [ + - ]: 3 : if (!(ret->d.other = ASN1_TYPE_new())) goto err;
897 : 3 : ret->type = OBJ_nid2obj(NID_id_smime_ct_TSTInfo);
898 [ + - ]: 3 : if (!(octet_string = ASN1_OCTET_STRING_new())) goto err;
899 : 3 : ASN1_TYPE_set(ret->d.other, V_ASN1_OCTET_STRING, octet_string);
900 : 3 : octet_string = NULL;
901 : :
902 : : /* Add encapsulated content to signed PKCS7 structure. */
903 [ - + ]: 3 : if (!PKCS7_set_content(p7, ret)) goto err;
904 : :
905 : : return 1;
906 : : err:
907 : 0 : ASN1_OCTET_STRING_free(octet_string);
908 : 0 : PKCS7_free(ret);
909 : 0 : return 0;
910 : : }
911 : :
912 : 3 : static int ESS_add_signing_cert(PKCS7_SIGNER_INFO *si, ESS_SIGNING_CERT *sc)
913 : : {
914 : 3 : ASN1_STRING *seq = NULL;
915 : 3 : unsigned char *p, *pp = NULL;
916 : : int len;
917 : :
918 : 3 : len = i2d_ESS_SIGNING_CERT(sc, NULL);
919 [ - + ]: 3 : if (!(pp = (unsigned char *) OPENSSL_malloc(len)))
920 : : {
921 : 0 : TSerr(TS_F_ESS_ADD_SIGNING_CERT, ERR_R_MALLOC_FAILURE);
922 : 0 : goto err;
923 : : }
924 : 3 : p = pp;
925 : 3 : i2d_ESS_SIGNING_CERT(sc, &p);
926 [ + - ][ - + ]: 3 : if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len))
927 : : {
928 : 0 : TSerr(TS_F_ESS_ADD_SIGNING_CERT, ERR_R_MALLOC_FAILURE);
929 : 0 : goto err;
930 : : }
931 : 3 : OPENSSL_free(pp); pp = NULL;
932 : 3 : return PKCS7_add_signed_attribute(si,
933 : : NID_id_smime_aa_signingCertificate,
934 : : V_ASN1_SEQUENCE, seq);
935 : : err:
936 : 0 : ASN1_STRING_free(seq);
937 : 0 : OPENSSL_free(pp);
938 : :
939 : 0 : return 0;
940 : : }
941 : :
942 : :
943 : : static ASN1_GENERALIZEDTIME *
944 : 3 : TS_RESP_set_genTime_with_precision(ASN1_GENERALIZEDTIME *asn1_time,
945 : : long sec, long usec, unsigned precision)
946 : : {
947 : 3 : time_t time_sec = (time_t) sec;
948 : 3 : struct tm *tm = NULL;
949 : : char genTime_str[17 + TS_MAX_CLOCK_PRECISION_DIGITS];
950 : 3 : char *p = genTime_str;
951 : 3 : char *p_end = genTime_str + sizeof(genTime_str);
952 : :
953 [ + - ]: 3 : if (precision > TS_MAX_CLOCK_PRECISION_DIGITS)
954 : : goto err;
955 : :
956 : :
957 [ + - ]: 3 : if (!(tm = gmtime(&time_sec)))
958 : : goto err;
959 : :
960 : : /*
961 : : * Put "genTime_str" in GeneralizedTime format. We work around the
962 : : * restrictions imposed by rfc3280 (i.e. "GeneralizedTime values MUST
963 : : * NOT include fractional seconds") and OpenSSL related functions to
964 : : * meet the rfc3161 requirement: "GeneralizedTime syntax can include
965 : : * fraction-of-second details".
966 : : */
967 : 3 : p += BIO_snprintf(p, p_end - p,
968 : : "%04d%02d%02d%02d%02d%02d",
969 : 6 : tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
970 : : tm->tm_hour, tm->tm_min, tm->tm_sec);
971 [ - + ]: 3 : if (precision > 0)
972 : : {
973 : : /* Add fraction of seconds (leave space for dot and null). */
974 : 0 : BIO_snprintf(p, 2 + precision, ".%ld", usec);
975 : : /* We cannot use the snprintf return value,
976 : : because it might have been truncated. */
977 : 0 : p += strlen(p);
978 : :
979 : : /* To make things a bit harder, X.690 | ISO/IEC 8825-1 provides
980 : : the following restrictions for a DER-encoding, which OpenSSL
981 : : (specifically ASN1_GENERALIZEDTIME_check() function) doesn't
982 : : support:
983 : : "The encoding MUST terminate with a "Z" (which means "Zulu"
984 : : time). The decimal point element, if present, MUST be the
985 : : point option ".". The fractional-seconds elements,
986 : : if present, MUST omit all trailing 0's;
987 : : if the elements correspond to 0, they MUST be wholly
988 : : omitted, and the decimal point element also MUST be
989 : : omitted." */
990 : : /* Remove trailing zeros. The dot guarantees the exit
991 : : condition of this loop even if all the digits are zero. */
992 [ # # ]: 0 : while (*--p == '0')
993 : : /* empty */;
994 : : /* p points to either the dot or the last non-zero digit. */
995 [ # # ]: 0 : if (*p != '.') ++p;
996 : : }
997 : : /* Add the trailing Z and the terminating null. */
998 : 3 : *p++ = 'Z';
999 : 3 : *p++ = '\0';
1000 : :
1001 : : /* Now call OpenSSL to check and set our genTime value */
1002 [ + - ][ + - ]: 3 : if (!asn1_time && !(asn1_time = M_ASN1_GENERALIZEDTIME_new()))
1003 : : goto err;
1004 [ - + ]: 3 : if (!ASN1_GENERALIZEDTIME_set_string(asn1_time, genTime_str))
1005 : : {
1006 : 0 : ASN1_GENERALIZEDTIME_free(asn1_time);
1007 : 0 : goto err;
1008 : : }
1009 : :
1010 : : return asn1_time;
1011 : : err:
1012 : 0 : TSerr(TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION, TS_R_COULD_NOT_SET_TIME);
1013 : 0 : return NULL;
1014 : : }
|