/src/libressl/crypto/ct/ct_sct.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: ct_sct.c,v 1.10 2023/07/22 17:02:49 tb Exp $ */ |
2 | | /* |
3 | | * Written by Rob Stradling (rob@comodo.com), Stephen Henson (steve@openssl.org) |
4 | | * and Adam Eijdenberg (adam.eijdenberg@gmail.com) for the OpenSSL project 2016. |
5 | | */ |
6 | | /* ==================================================================== |
7 | | * Copyright (c) 2014 The OpenSSL Project. All rights reserved. |
8 | | * |
9 | | * Redistribution and use in source and binary forms, with or without |
10 | | * modification, are permitted provided that the following conditions |
11 | | * are met: |
12 | | * |
13 | | * 1. Redistributions of source code must retain the above copyright |
14 | | * notice, this list of conditions and the following disclaimer. |
15 | | * |
16 | | * 2. Redistributions in binary form must reproduce the above copyright |
17 | | * notice, this list of conditions and the following disclaimer in |
18 | | * the documentation and/or other materials provided with the |
19 | | * distribution. |
20 | | * |
21 | | * 3. All advertising materials mentioning features or use of this |
22 | | * software must display the following acknowledgment: |
23 | | * "This product includes software developed by the OpenSSL Project |
24 | | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" |
25 | | * |
26 | | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
27 | | * endorse or promote products derived from this software without |
28 | | * prior written permission. For written permission, please contact |
29 | | * licensing@OpenSSL.org. |
30 | | * |
31 | | * 5. Products derived from this software may not be called "OpenSSL" |
32 | | * nor may "OpenSSL" appear in their names without prior written |
33 | | * permission of the OpenSSL Project. |
34 | | * |
35 | | * 6. Redistributions of any form whatsoever must retain the following |
36 | | * acknowledgment: |
37 | | * "This product includes software developed by the OpenSSL Project |
38 | | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" |
39 | | * |
40 | | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
41 | | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
43 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
44 | | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
45 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
46 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
47 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
49 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
50 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
51 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
52 | | * ==================================================================== |
53 | | * |
54 | | * This product includes cryptographic software written by Eric Young |
55 | | * (eay@cryptsoft.com). This product includes software written by Tim |
56 | | * Hudson (tjh@cryptsoft.com). |
57 | | * |
58 | | */ |
59 | | |
60 | | #ifdef OPENSSL_NO_CT |
61 | | # error "CT disabled" |
62 | | #endif |
63 | | |
64 | | #include <stdint.h> |
65 | | #include <stdlib.h> |
66 | | #include <string.h> |
67 | | |
68 | | #include <openssl/asn1.h> |
69 | | #include <openssl/ct.h> |
70 | | #include <openssl/err.h> |
71 | | #include <openssl/objects.h> |
72 | | #include <openssl/x509.h> |
73 | | |
74 | | #include "ct_local.h" |
75 | | |
76 | | SCT * |
77 | | SCT_new(void) |
78 | 15.7k | { |
79 | 15.7k | SCT *sct = calloc(1, sizeof(*sct)); |
80 | | |
81 | 15.7k | if (sct == NULL) { |
82 | 0 | CTerror(ERR_R_MALLOC_FAILURE); |
83 | 0 | return NULL; |
84 | 0 | } |
85 | | |
86 | 15.7k | sct->entry_type = CT_LOG_ENTRY_TYPE_NOT_SET; |
87 | 15.7k | sct->version = SCT_VERSION_NOT_SET; |
88 | 15.7k | return sct; |
89 | 15.7k | } |
90 | | LCRYPTO_ALIAS(SCT_new); |
91 | | |
92 | | void |
93 | | SCT_free(SCT *sct) |
94 | 15.7k | { |
95 | 15.7k | if (sct == NULL) |
96 | 0 | return; |
97 | | |
98 | 15.7k | free(sct->log_id); |
99 | 15.7k | free(sct->ext); |
100 | 15.7k | free(sct->sig); |
101 | 15.7k | free(sct->sct); |
102 | 15.7k | free(sct); |
103 | 15.7k | } |
104 | | LCRYPTO_ALIAS(SCT_free); |
105 | | |
106 | | void |
107 | | SCT_LIST_free(STACK_OF(SCT) *scts) |
108 | 12.3k | { |
109 | 12.3k | sk_SCT_pop_free(scts, SCT_free); |
110 | 12.3k | } |
111 | | LCRYPTO_ALIAS(SCT_LIST_free); |
112 | | |
113 | | int |
114 | | SCT_set_version(SCT *sct, sct_version_t version) |
115 | 0 | { |
116 | 0 | if (version != SCT_VERSION_V1) { |
117 | 0 | CTerror(CT_R_UNSUPPORTED_VERSION); |
118 | 0 | return 0; |
119 | 0 | } |
120 | 0 | sct->version = version; |
121 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
122 | 0 | return 1; |
123 | 0 | } |
124 | | LCRYPTO_ALIAS(SCT_set_version); |
125 | | |
126 | | int |
127 | | SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type) |
128 | 11.5k | { |
129 | 11.5k | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
130 | | |
131 | 11.5k | switch (entry_type) { |
132 | 8.06k | case CT_LOG_ENTRY_TYPE_X509: |
133 | 11.5k | case CT_LOG_ENTRY_TYPE_PRECERT: |
134 | 11.5k | sct->entry_type = entry_type; |
135 | 11.5k | return 1; |
136 | 0 | case CT_LOG_ENTRY_TYPE_NOT_SET: |
137 | 0 | break; |
138 | 11.5k | } |
139 | 0 | CTerror(CT_R_UNSUPPORTED_ENTRY_TYPE); |
140 | 0 | return 0; |
141 | 11.5k | } |
142 | | LCRYPTO_ALIAS(SCT_set_log_entry_type); |
143 | | |
144 | | int |
145 | | SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len) |
146 | 0 | { |
147 | 0 | if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) { |
148 | 0 | CTerror(CT_R_INVALID_LOG_ID_LENGTH); |
149 | 0 | return 0; |
150 | 0 | } |
151 | | |
152 | 0 | free(sct->log_id); |
153 | 0 | sct->log_id = log_id; |
154 | 0 | sct->log_id_len = log_id_len; |
155 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
156 | 0 | return 1; |
157 | 0 | } |
158 | | LCRYPTO_ALIAS(SCT_set0_log_id); |
159 | | |
160 | | int |
161 | | SCT_set1_log_id(SCT *sct, const unsigned char *log_id, size_t log_id_len) |
162 | 0 | { |
163 | 0 | if (sct->version == SCT_VERSION_V1 && log_id_len != CT_V1_HASHLEN) { |
164 | 0 | CTerror(CT_R_INVALID_LOG_ID_LENGTH); |
165 | 0 | return 0; |
166 | 0 | } |
167 | | |
168 | 0 | free(sct->log_id); |
169 | 0 | sct->log_id = NULL; |
170 | 0 | sct->log_id_len = 0; |
171 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
172 | |
|
173 | 0 | if (log_id != NULL && log_id_len > 0) { |
174 | 0 | sct->log_id = malloc(log_id_len); |
175 | 0 | if (sct->log_id == NULL) { |
176 | 0 | CTerror(ERR_R_MALLOC_FAILURE); |
177 | 0 | return 0; |
178 | 0 | } |
179 | 0 | memcpy(sct->log_id, log_id, log_id_len); |
180 | 0 | sct->log_id_len = log_id_len; |
181 | 0 | } |
182 | 0 | return 1; |
183 | 0 | } |
184 | | LCRYPTO_ALIAS(SCT_set1_log_id); |
185 | | |
186 | | |
187 | | void |
188 | | SCT_set_timestamp(SCT *sct, uint64_t timestamp) |
189 | 0 | { |
190 | 0 | sct->timestamp = timestamp; |
191 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
192 | 0 | } |
193 | | LCRYPTO_ALIAS(SCT_set_timestamp); |
194 | | |
195 | | int |
196 | | SCT_set_signature_nid(SCT *sct, int nid) |
197 | 0 | { |
198 | 0 | switch (nid) { |
199 | 0 | case NID_sha256WithRSAEncryption: |
200 | 0 | sct->hash_alg = 4; /* XXX */ |
201 | 0 | sct->sig_alg = 1; /* XXX */ |
202 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
203 | 0 | return 1; |
204 | 0 | case NID_ecdsa_with_SHA256: |
205 | 0 | sct->hash_alg = 4; /* XXX */ |
206 | 0 | sct->sig_alg = 3; /* XXX */ |
207 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
208 | 0 | return 1; |
209 | 0 | default: |
210 | 0 | CTerror(CT_R_UNRECOGNIZED_SIGNATURE_NID); |
211 | 0 | return 0; |
212 | 0 | } |
213 | 0 | } |
214 | | LCRYPTO_ALIAS(SCT_set_signature_nid); |
215 | | |
216 | | void |
217 | | SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len) |
218 | 0 | { |
219 | 0 | free(sct->ext); |
220 | 0 | sct->ext = ext; |
221 | 0 | sct->ext_len = ext_len; |
222 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
223 | 0 | } |
224 | | LCRYPTO_ALIAS(SCT_set0_extensions); |
225 | | |
226 | | int |
227 | | SCT_set1_extensions(SCT *sct, const unsigned char *ext, size_t ext_len) |
228 | 0 | { |
229 | 0 | free(sct->ext); |
230 | 0 | sct->ext = NULL; |
231 | 0 | sct->ext_len = 0; |
232 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
233 | |
|
234 | 0 | if (ext != NULL && ext_len > 0) { |
235 | 0 | sct->ext = malloc(ext_len); |
236 | 0 | if (sct->ext == NULL) { |
237 | 0 | CTerror(ERR_R_MALLOC_FAILURE); |
238 | 0 | return 0; |
239 | 0 | } |
240 | 0 | memcpy(sct->ext, ext, ext_len); |
241 | 0 | sct->ext_len = ext_len; |
242 | 0 | } |
243 | 0 | return 1; |
244 | 0 | } |
245 | | LCRYPTO_ALIAS(SCT_set1_extensions); |
246 | | |
247 | | void |
248 | | SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len) |
249 | 0 | { |
250 | 0 | free(sct->sig); |
251 | 0 | sct->sig = sig; |
252 | 0 | sct->sig_len = sig_len; |
253 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
254 | 0 | } |
255 | | LCRYPTO_ALIAS(SCT_set0_signature); |
256 | | |
257 | | int |
258 | | SCT_set1_signature(SCT *sct, const unsigned char *sig, size_t sig_len) |
259 | 4.94k | { |
260 | 4.94k | free(sct->sig); |
261 | 4.94k | sct->sig = NULL; |
262 | 4.94k | sct->sig_len = 0; |
263 | 4.94k | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
264 | | |
265 | 4.94k | if (sig != NULL && sig_len > 0) { |
266 | 4.94k | sct->sig = malloc(sig_len); |
267 | 4.94k | if (sct->sig == NULL) { |
268 | 0 | CTerror(ERR_R_MALLOC_FAILURE); |
269 | 0 | return 0; |
270 | 0 | } |
271 | 4.94k | memcpy(sct->sig, sig, sig_len); |
272 | 4.94k | sct->sig_len = sig_len; |
273 | 4.94k | } |
274 | 4.94k | return 1; |
275 | 4.94k | } |
276 | | LCRYPTO_ALIAS(SCT_set1_signature); |
277 | | |
278 | | sct_version_t |
279 | | SCT_get_version(const SCT *sct) |
280 | 0 | { |
281 | 0 | return sct->version; |
282 | 0 | } |
283 | | LCRYPTO_ALIAS(SCT_get_version); |
284 | | |
285 | | ct_log_entry_type_t |
286 | | SCT_get_log_entry_type(const SCT *sct) |
287 | 0 | { |
288 | 0 | return sct->entry_type; |
289 | 0 | } |
290 | | LCRYPTO_ALIAS(SCT_get_log_entry_type); |
291 | | |
292 | | size_t |
293 | | SCT_get0_log_id(const SCT *sct, unsigned char **log_id) |
294 | 0 | { |
295 | 0 | *log_id = sct->log_id; |
296 | 0 | return sct->log_id_len; |
297 | 0 | } |
298 | | LCRYPTO_ALIAS(SCT_get0_log_id); |
299 | | |
300 | | uint64_t |
301 | | SCT_get_timestamp(const SCT *sct) |
302 | 0 | { |
303 | 0 | return sct->timestamp; |
304 | 0 | } |
305 | | LCRYPTO_ALIAS(SCT_get_timestamp); |
306 | | |
307 | | int |
308 | | SCT_get_signature_nid(const SCT *sct) |
309 | 10.0k | { |
310 | 10.0k | if (sct->version == SCT_VERSION_V1) { |
311 | | /* XXX sigalg numbers */ |
312 | 10.0k | if (sct->hash_alg == 4) { |
313 | 9.95k | switch (sct->sig_alg) { |
314 | 4.05k | case 3: |
315 | 4.05k | return NID_ecdsa_with_SHA256; |
316 | 5.82k | case 1: |
317 | 5.82k | return NID_sha256WithRSAEncryption; |
318 | 79 | default: |
319 | 79 | return NID_undef; |
320 | 9.95k | } |
321 | 9.95k | } |
322 | 10.0k | } |
323 | 103 | return NID_undef; |
324 | 10.0k | } |
325 | | LCRYPTO_ALIAS(SCT_get_signature_nid); |
326 | | |
327 | | size_t |
328 | | SCT_get0_extensions(const SCT *sct, unsigned char **ext) |
329 | 0 | { |
330 | 0 | *ext = sct->ext; |
331 | 0 | return sct->ext_len; |
332 | 0 | } |
333 | | LCRYPTO_ALIAS(SCT_get0_extensions); |
334 | | |
335 | | size_t |
336 | | SCT_get0_signature(const SCT *sct, unsigned char **sig) |
337 | 0 | { |
338 | 0 | *sig = sct->sig; |
339 | 0 | return sct->sig_len; |
340 | 0 | } |
341 | | LCRYPTO_ALIAS(SCT_get0_signature); |
342 | | |
343 | | int |
344 | | SCT_is_complete(const SCT *sct) |
345 | 0 | { |
346 | 0 | switch (sct->version) { |
347 | 0 | case SCT_VERSION_NOT_SET: |
348 | 0 | return 0; |
349 | 0 | case SCT_VERSION_V1: |
350 | 0 | return sct->log_id != NULL && SCT_signature_is_complete(sct); |
351 | 0 | default: |
352 | 0 | return sct->sct != NULL; /* Just need cached encoding */ |
353 | 0 | } |
354 | 0 | } |
355 | | |
356 | | int |
357 | | SCT_signature_is_complete(const SCT *sct) |
358 | 0 | { |
359 | 0 | return SCT_get_signature_nid(sct) != NID_undef && |
360 | 0 | sct->sig != NULL && sct->sig_len > 0; |
361 | 0 | } |
362 | | |
363 | | sct_source_t |
364 | | SCT_get_source(const SCT *sct) |
365 | 0 | { |
366 | 0 | return sct->source; |
367 | 0 | } |
368 | | LCRYPTO_ALIAS(SCT_get_source); |
369 | | |
370 | | int |
371 | | SCT_set_source(SCT *sct, sct_source_t source) |
372 | 11.5k | { |
373 | 11.5k | sct->source = source; |
374 | 11.5k | sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET; |
375 | 11.5k | switch (source) { |
376 | 0 | case SCT_SOURCE_TLS_EXTENSION: |
377 | 8.06k | case SCT_SOURCE_OCSP_STAPLED_RESPONSE: |
378 | 8.06k | return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_X509); |
379 | 3.47k | case SCT_SOURCE_X509V3_EXTENSION: |
380 | 3.47k | return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT); |
381 | 0 | case SCT_SOURCE_UNKNOWN: |
382 | 0 | break; |
383 | 11.5k | } |
384 | | /* if we aren't sure, leave the log entry type alone */ |
385 | 0 | return 1; |
386 | 11.5k | } |
387 | | LCRYPTO_ALIAS(SCT_set_source); |
388 | | |
389 | | sct_validation_status_t |
390 | | SCT_get_validation_status(const SCT *sct) |
391 | 0 | { |
392 | 0 | return sct->validation_status; |
393 | 0 | } |
394 | | LCRYPTO_ALIAS(SCT_get_validation_status); |
395 | | |
396 | | int |
397 | | SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx) |
398 | 0 | { |
399 | 0 | int is_sct_valid = -1; |
400 | 0 | SCT_CTX *sctx = NULL; |
401 | 0 | X509_PUBKEY *pub = NULL, *log_pkey = NULL; |
402 | 0 | const CTLOG *log; |
403 | | |
404 | | /* |
405 | | * With an unrecognized SCT version we don't know what such an SCT means, |
406 | | * let alone validate one. So we return validation failure (0). |
407 | | */ |
408 | 0 | if (sct->version != SCT_VERSION_V1) { |
409 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION; |
410 | 0 | return 0; |
411 | 0 | } |
412 | | |
413 | 0 | log = CTLOG_STORE_get0_log_by_id(ctx->log_store, sct->log_id, |
414 | 0 | sct->log_id_len); |
415 | | |
416 | | /* Similarly, an SCT from an unknown log also cannot be validated. */ |
417 | 0 | if (log == NULL) { |
418 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG; |
419 | 0 | return 0; |
420 | 0 | } |
421 | | |
422 | 0 | sctx = SCT_CTX_new(); |
423 | 0 | if (sctx == NULL) |
424 | 0 | goto err; |
425 | | |
426 | 0 | if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(log)) != 1) |
427 | 0 | goto err; |
428 | 0 | if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1) |
429 | 0 | goto err; |
430 | | |
431 | 0 | if (SCT_get_log_entry_type(sct) == CT_LOG_ENTRY_TYPE_PRECERT) { |
432 | 0 | EVP_PKEY *issuer_pkey; |
433 | |
|
434 | 0 | if (ctx->issuer == NULL) { |
435 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; |
436 | 0 | goto end; |
437 | 0 | } |
438 | | |
439 | 0 | if ((issuer_pkey = X509_get0_pubkey(ctx->issuer)) == NULL) |
440 | 0 | goto err; |
441 | | |
442 | 0 | if (X509_PUBKEY_set(&pub, issuer_pkey) != 1) |
443 | 0 | goto err; |
444 | 0 | if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1) |
445 | 0 | goto err; |
446 | 0 | } |
447 | | |
448 | 0 | SCT_CTX_set_time(sctx, ctx->epoch_time_in_ms); |
449 | | |
450 | | /* |
451 | | * XXX: Potential for optimization. This repeats some idempotent heavy |
452 | | * lifting on the certificate for each candidate SCT, and appears to not |
453 | | * use any information in the SCT itself, only the certificate is |
454 | | * processed. So it may make more sense to to do this just once, perhaps |
455 | | * associated with the shared (by all SCTs) policy eval ctx. |
456 | | * |
457 | | * XXX: Failure here is global (SCT independent) and represents either an |
458 | | * issue with the certificate (e.g. duplicate extensions) or an out of |
459 | | * memory condition. When the certificate is incompatible with CT, we just |
460 | | * mark the SCTs invalid, rather than report a failure to determine the |
461 | | * validation status. That way, callbacks that want to do "soft" SCT |
462 | | * processing will not abort handshakes with false positive internal |
463 | | * errors. Since the function does not distinguish between certificate |
464 | | * issues (peer's fault) and internal problems (out fault) the safe thing |
465 | | * to do is to report a validation failure and let the callback or |
466 | | * application decide what to do. |
467 | | */ |
468 | 0 | if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1) |
469 | 0 | sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED; |
470 | 0 | else |
471 | 0 | sct->validation_status = SCT_CTX_verify(sctx, sct) == 1 ? |
472 | 0 | SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID; |
473 | |
|
474 | 0 | end: |
475 | 0 | is_sct_valid = sct->validation_status == SCT_VALIDATION_STATUS_VALID; |
476 | 0 | err: |
477 | 0 | X509_PUBKEY_free(pub); |
478 | 0 | X509_PUBKEY_free(log_pkey); |
479 | 0 | SCT_CTX_free(sctx); |
480 | |
|
481 | 0 | return is_sct_valid; |
482 | 0 | } |
483 | | LCRYPTO_ALIAS(SCT_validate); |
484 | | |
485 | | int |
486 | | SCT_LIST_validate(const STACK_OF(SCT) *scts, CT_POLICY_EVAL_CTX *ctx) |
487 | 0 | { |
488 | 0 | int are_scts_valid = 1; |
489 | 0 | int sct_count = scts != NULL ? sk_SCT_num(scts) : 0; |
490 | 0 | int i; |
491 | |
|
492 | 0 | for (i = 0; i < sct_count; ++i) { |
493 | 0 | int is_sct_valid = -1; |
494 | 0 | SCT *sct = sk_SCT_value(scts, i); |
495 | |
|
496 | 0 | if (sct == NULL) |
497 | 0 | continue; |
498 | | |
499 | 0 | is_sct_valid = SCT_validate(sct, ctx); |
500 | 0 | if (is_sct_valid < 0) |
501 | 0 | return is_sct_valid; |
502 | 0 | are_scts_valid &= is_sct_valid; |
503 | 0 | } |
504 | | |
505 | 0 | return are_scts_valid; |
506 | 0 | } |
507 | | LCRYPTO_ALIAS(SCT_LIST_validate); |