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