xref: /freebsd-src/crypto/openssl/crypto/ct/ct_oct.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1e71b7053SJung-uk Kim /*
2*b077aed3SPierre Pronchery  * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
8e71b7053SJung-uk Kim  */
9e71b7053SJung-uk Kim 
10e71b7053SJung-uk Kim #ifdef OPENSSL_NO_CT
11e71b7053SJung-uk Kim # error "CT is disabled"
12e71b7053SJung-uk Kim #endif
13e71b7053SJung-uk Kim 
14e71b7053SJung-uk Kim #include <limits.h>
15e71b7053SJung-uk Kim #include <string.h>
16e71b7053SJung-uk Kim 
17e71b7053SJung-uk Kim #include <openssl/asn1.h>
18e71b7053SJung-uk Kim #include <openssl/buffer.h>
19e71b7053SJung-uk Kim #include <openssl/ct.h>
20e71b7053SJung-uk Kim #include <openssl/err.h>
21e71b7053SJung-uk Kim 
2217f01e99SJung-uk Kim #include "ct_local.h"
23e71b7053SJung-uk Kim 
o2i_SCT_signature(SCT * sct,const unsigned char ** in,size_t len)24e71b7053SJung-uk Kim int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len)
25e71b7053SJung-uk Kim {
26e71b7053SJung-uk Kim     size_t siglen;
27e71b7053SJung-uk Kim     size_t len_remaining = len;
28e71b7053SJung-uk Kim     const unsigned char *p;
29e71b7053SJung-uk Kim 
30e71b7053SJung-uk Kim     if (sct->version != SCT_VERSION_V1) {
31*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION);
32e71b7053SJung-uk Kim         return -1;
33e71b7053SJung-uk Kim     }
34e71b7053SJung-uk Kim     /*
35e71b7053SJung-uk Kim      * digitally-signed struct header: (1 byte) Hash algorithm (1 byte)
36e71b7053SJung-uk Kim      * Signature algorithm (2 bytes + ?) Signature
37e71b7053SJung-uk Kim      *
38e71b7053SJung-uk Kim      * This explicitly rejects empty signatures: they're invalid for
39e71b7053SJung-uk Kim      * all supported algorithms.
40e71b7053SJung-uk Kim      */
41e71b7053SJung-uk Kim     if (len <= 4) {
42*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
43e71b7053SJung-uk Kim         return -1;
44e71b7053SJung-uk Kim     }
45e71b7053SJung-uk Kim 
46e71b7053SJung-uk Kim     p = *in;
47e71b7053SJung-uk Kim     /* Get hash and signature algorithm */
48e71b7053SJung-uk Kim     sct->hash_alg = *p++;
49e71b7053SJung-uk Kim     sct->sig_alg = *p++;
50e71b7053SJung-uk Kim     if (SCT_get_signature_nid(sct) == NID_undef) {
51*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
52e71b7053SJung-uk Kim         return -1;
53e71b7053SJung-uk Kim     }
54e71b7053SJung-uk Kim     /* Retrieve signature and check it is consistent with the buffer length */
55e71b7053SJung-uk Kim     n2s(p, siglen);
56e71b7053SJung-uk Kim     len_remaining -= (p - *in);
57e71b7053SJung-uk Kim     if (siglen > len_remaining) {
58*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
59e71b7053SJung-uk Kim         return -1;
60e71b7053SJung-uk Kim     }
61e71b7053SJung-uk Kim 
62e71b7053SJung-uk Kim     if (SCT_set1_signature(sct, p, siglen) != 1)
63e71b7053SJung-uk Kim         return -1;
64e71b7053SJung-uk Kim     len_remaining -= siglen;
65e71b7053SJung-uk Kim     *in = p + siglen;
66e71b7053SJung-uk Kim 
67e71b7053SJung-uk Kim     return len - len_remaining;
68e71b7053SJung-uk Kim }
69e71b7053SJung-uk Kim 
o2i_SCT(SCT ** psct,const unsigned char ** in,size_t len)70e71b7053SJung-uk Kim SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
71e71b7053SJung-uk Kim {
72e71b7053SJung-uk Kim     SCT *sct = NULL;
73e71b7053SJung-uk Kim     const unsigned char *p;
74e71b7053SJung-uk Kim 
75e71b7053SJung-uk Kim     if (len == 0 || len > MAX_SCT_SIZE) {
76*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
77e71b7053SJung-uk Kim         goto err;
78e71b7053SJung-uk Kim     }
79e71b7053SJung-uk Kim 
80e71b7053SJung-uk Kim     if ((sct = SCT_new()) == NULL)
81e71b7053SJung-uk Kim         goto err;
82e71b7053SJung-uk Kim 
83e71b7053SJung-uk Kim     p = *in;
84e71b7053SJung-uk Kim 
85e71b7053SJung-uk Kim     sct->version = *p;
86e71b7053SJung-uk Kim     if (sct->version == SCT_VERSION_V1) {
87e71b7053SJung-uk Kim         int sig_len;
88e71b7053SJung-uk Kim         size_t len2;
89e71b7053SJung-uk Kim         /*-
90e71b7053SJung-uk Kim          * Fixed-length header:
91e71b7053SJung-uk Kim          *   struct {
92e71b7053SJung-uk Kim          *     Version sct_version;     (1 byte)
93e71b7053SJung-uk Kim          *     log_id id;               (32 bytes)
94e71b7053SJung-uk Kim          *     uint64 timestamp;        (8 bytes)
95e71b7053SJung-uk Kim          *     CtExtensions extensions; (2 bytes + ?)
96e71b7053SJung-uk Kim          *   }
97e71b7053SJung-uk Kim          */
98e71b7053SJung-uk Kim         if (len < 43) {
99*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
100e71b7053SJung-uk Kim             goto err;
101e71b7053SJung-uk Kim         }
102e71b7053SJung-uk Kim         len -= 43;
103e71b7053SJung-uk Kim         p++;
104*b077aed3SPierre Pronchery         sct->log_id = OPENSSL_memdup(p, CT_V1_HASHLEN);
105e71b7053SJung-uk Kim         if (sct->log_id == NULL)
106e71b7053SJung-uk Kim             goto err;
107e71b7053SJung-uk Kim         sct->log_id_len = CT_V1_HASHLEN;
108e71b7053SJung-uk Kim         p += CT_V1_HASHLEN;
109e71b7053SJung-uk Kim 
110e71b7053SJung-uk Kim         n2l8(p, sct->timestamp);
111e71b7053SJung-uk Kim 
112e71b7053SJung-uk Kim         n2s(p, len2);
113e71b7053SJung-uk Kim         if (len < len2) {
114*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
115e71b7053SJung-uk Kim             goto err;
116e71b7053SJung-uk Kim         }
117e71b7053SJung-uk Kim         if (len2 > 0) {
118*b077aed3SPierre Pronchery             sct->ext = OPENSSL_memdup(p, len2);
119e71b7053SJung-uk Kim             if (sct->ext == NULL)
120e71b7053SJung-uk Kim                 goto err;
121e71b7053SJung-uk Kim         }
122e71b7053SJung-uk Kim         sct->ext_len = len2;
123e71b7053SJung-uk Kim         p += len2;
124e71b7053SJung-uk Kim         len -= len2;
125e71b7053SJung-uk Kim 
126e71b7053SJung-uk Kim         sig_len = o2i_SCT_signature(sct, &p, len);
127e71b7053SJung-uk Kim         if (sig_len <= 0) {
128*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
129e71b7053SJung-uk Kim             goto err;
130e71b7053SJung-uk Kim         }
131e71b7053SJung-uk Kim         len -= sig_len;
132e71b7053SJung-uk Kim         *in = p + len;
133e71b7053SJung-uk Kim     } else {
134e71b7053SJung-uk Kim         /* If not V1 just cache encoding */
135*b077aed3SPierre Pronchery         sct->sct = OPENSSL_memdup(p, len);
136e71b7053SJung-uk Kim         if (sct->sct == NULL)
137e71b7053SJung-uk Kim             goto err;
138e71b7053SJung-uk Kim         sct->sct_len = len;
139e71b7053SJung-uk Kim         *in = p + len;
140e71b7053SJung-uk Kim     }
141e71b7053SJung-uk Kim 
142e71b7053SJung-uk Kim     if (psct != NULL) {
143e71b7053SJung-uk Kim         SCT_free(*psct);
144e71b7053SJung-uk Kim         *psct = sct;
145e71b7053SJung-uk Kim     }
146e71b7053SJung-uk Kim 
147e71b7053SJung-uk Kim     return sct;
148e71b7053SJung-uk Kim err:
149e71b7053SJung-uk Kim     SCT_free(sct);
150e71b7053SJung-uk Kim     return NULL;
151e71b7053SJung-uk Kim }
152e71b7053SJung-uk Kim 
i2o_SCT_signature(const SCT * sct,unsigned char ** out)153e71b7053SJung-uk Kim int i2o_SCT_signature(const SCT *sct, unsigned char **out)
154e71b7053SJung-uk Kim {
155e71b7053SJung-uk Kim     size_t len;
156e71b7053SJung-uk Kim     unsigned char *p = NULL, *pstart = NULL;
157e71b7053SJung-uk Kim 
158e71b7053SJung-uk Kim     if (!SCT_signature_is_complete(sct)) {
159*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
160e71b7053SJung-uk Kim         goto err;
161e71b7053SJung-uk Kim     }
162e71b7053SJung-uk Kim 
163e71b7053SJung-uk Kim     if (sct->version != SCT_VERSION_V1) {
164*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION);
165e71b7053SJung-uk Kim         goto err;
166e71b7053SJung-uk Kim     }
167e71b7053SJung-uk Kim 
168e71b7053SJung-uk Kim     /*
169e71b7053SJung-uk Kim     * (1 byte) Hash algorithm
170e71b7053SJung-uk Kim     * (1 byte) Signature algorithm
171e71b7053SJung-uk Kim     * (2 bytes + ?) Signature
172e71b7053SJung-uk Kim     */
173e71b7053SJung-uk Kim     len = 4 + sct->sig_len;
174e71b7053SJung-uk Kim 
175e71b7053SJung-uk Kim     if (out != NULL) {
176e71b7053SJung-uk Kim         if (*out != NULL) {
177e71b7053SJung-uk Kim             p = *out;
178e71b7053SJung-uk Kim             *out += len;
179e71b7053SJung-uk Kim         } else {
180e71b7053SJung-uk Kim             pstart = p = OPENSSL_malloc(len);
181e71b7053SJung-uk Kim             if (p == NULL) {
182*b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
183e71b7053SJung-uk Kim                 goto err;
184e71b7053SJung-uk Kim             }
185e71b7053SJung-uk Kim             *out = p;
186e71b7053SJung-uk Kim         }
187e71b7053SJung-uk Kim 
188e71b7053SJung-uk Kim         *p++ = sct->hash_alg;
189e71b7053SJung-uk Kim         *p++ = sct->sig_alg;
190e71b7053SJung-uk Kim         s2n(sct->sig_len, p);
191e71b7053SJung-uk Kim         memcpy(p, sct->sig, sct->sig_len);
192e71b7053SJung-uk Kim     }
193e71b7053SJung-uk Kim 
194e71b7053SJung-uk Kim     return len;
195e71b7053SJung-uk Kim err:
196e71b7053SJung-uk Kim     OPENSSL_free(pstart);
197e71b7053SJung-uk Kim     return -1;
198e71b7053SJung-uk Kim }
199e71b7053SJung-uk Kim 
i2o_SCT(const SCT * sct,unsigned char ** out)200e71b7053SJung-uk Kim int i2o_SCT(const SCT *sct, unsigned char **out)
201e71b7053SJung-uk Kim {
202e71b7053SJung-uk Kim     size_t len;
203e71b7053SJung-uk Kim     unsigned char *p = NULL, *pstart = NULL;
204e71b7053SJung-uk Kim 
205e71b7053SJung-uk Kim     if (!SCT_is_complete(sct)) {
206*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_SCT_NOT_SET);
207e71b7053SJung-uk Kim         goto err;
208e71b7053SJung-uk Kim     }
209e71b7053SJung-uk Kim     /*
210e71b7053SJung-uk Kim      * Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes)
211e71b7053SJung-uk Kim      * log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions
212e71b7053SJung-uk Kim      * extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2
213e71b7053SJung-uk Kim      * bytes + ?) Signature
214e71b7053SJung-uk Kim      */
215e71b7053SJung-uk Kim     if (sct->version == SCT_VERSION_V1)
216e71b7053SJung-uk Kim         len = 43 + sct->ext_len + 4 + sct->sig_len;
217e71b7053SJung-uk Kim     else
218e71b7053SJung-uk Kim         len = sct->sct_len;
219e71b7053SJung-uk Kim 
220e71b7053SJung-uk Kim     if (out == NULL)
221e71b7053SJung-uk Kim         return len;
222e71b7053SJung-uk Kim 
223e71b7053SJung-uk Kim     if (*out != NULL) {
224e71b7053SJung-uk Kim         p = *out;
225e71b7053SJung-uk Kim         *out += len;
226e71b7053SJung-uk Kim     } else {
227e71b7053SJung-uk Kim         pstart = p = OPENSSL_malloc(len);
228e71b7053SJung-uk Kim         if (p == NULL) {
229*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
230e71b7053SJung-uk Kim             goto err;
231e71b7053SJung-uk Kim         }
232e71b7053SJung-uk Kim         *out = p;
233e71b7053SJung-uk Kim     }
234e71b7053SJung-uk Kim 
235e71b7053SJung-uk Kim     if (sct->version == SCT_VERSION_V1) {
236e71b7053SJung-uk Kim         *p++ = sct->version;
237e71b7053SJung-uk Kim         memcpy(p, sct->log_id, CT_V1_HASHLEN);
238e71b7053SJung-uk Kim         p += CT_V1_HASHLEN;
239e71b7053SJung-uk Kim         l2n8(sct->timestamp, p);
240e71b7053SJung-uk Kim         s2n(sct->ext_len, p);
241e71b7053SJung-uk Kim         if (sct->ext_len > 0) {
242e71b7053SJung-uk Kim             memcpy(p, sct->ext, sct->ext_len);
243e71b7053SJung-uk Kim             p += sct->ext_len;
244e71b7053SJung-uk Kim         }
245e71b7053SJung-uk Kim         if (i2o_SCT_signature(sct, &p) <= 0)
246e71b7053SJung-uk Kim             goto err;
247e71b7053SJung-uk Kim     } else {
248e71b7053SJung-uk Kim         memcpy(p, sct->sct, len);
249e71b7053SJung-uk Kim     }
250e71b7053SJung-uk Kim 
251e71b7053SJung-uk Kim     return len;
252e71b7053SJung-uk Kim err:
253e71b7053SJung-uk Kim     OPENSSL_free(pstart);
254e71b7053SJung-uk Kim     return -1;
255e71b7053SJung-uk Kim }
256e71b7053SJung-uk Kim 
STACK_OF(SCT)257e71b7053SJung-uk Kim STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
258e71b7053SJung-uk Kim                             size_t len)
259e71b7053SJung-uk Kim {
260e71b7053SJung-uk Kim     STACK_OF(SCT) *sk = NULL;
261e71b7053SJung-uk Kim     size_t list_len, sct_len;
262e71b7053SJung-uk Kim 
263e71b7053SJung-uk Kim     if (len < 2 || len > MAX_SCT_LIST_SIZE) {
264*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
265e71b7053SJung-uk Kim         return NULL;
266e71b7053SJung-uk Kim     }
267e71b7053SJung-uk Kim 
268e71b7053SJung-uk Kim     n2s(*pp, list_len);
269e71b7053SJung-uk Kim     if (list_len != len - 2) {
270*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
271e71b7053SJung-uk Kim         return NULL;
272e71b7053SJung-uk Kim     }
273e71b7053SJung-uk Kim 
274e71b7053SJung-uk Kim     if (a == NULL || *a == NULL) {
275e71b7053SJung-uk Kim         sk = sk_SCT_new_null();
276e71b7053SJung-uk Kim         if (sk == NULL)
277e71b7053SJung-uk Kim             return NULL;
278e71b7053SJung-uk Kim     } else {
279e71b7053SJung-uk Kim         SCT *sct;
280e71b7053SJung-uk Kim 
281e71b7053SJung-uk Kim         /* Use the given stack, but empty it first. */
282e71b7053SJung-uk Kim         sk = *a;
283e71b7053SJung-uk Kim         while ((sct = sk_SCT_pop(sk)) != NULL)
284e71b7053SJung-uk Kim             SCT_free(sct);
285e71b7053SJung-uk Kim     }
286e71b7053SJung-uk Kim 
287e71b7053SJung-uk Kim     while (list_len > 0) {
288e71b7053SJung-uk Kim         SCT *sct;
289e71b7053SJung-uk Kim 
290e71b7053SJung-uk Kim         if (list_len < 2) {
291*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
292e71b7053SJung-uk Kim             goto err;
293e71b7053SJung-uk Kim         }
294e71b7053SJung-uk Kim         n2s(*pp, sct_len);
295e71b7053SJung-uk Kim         list_len -= 2;
296e71b7053SJung-uk Kim 
297e71b7053SJung-uk Kim         if (sct_len == 0 || sct_len > list_len) {
298*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
299e71b7053SJung-uk Kim             goto err;
300e71b7053SJung-uk Kim         }
301e71b7053SJung-uk Kim         list_len -= sct_len;
302e71b7053SJung-uk Kim 
303e71b7053SJung-uk Kim         if ((sct = o2i_SCT(NULL, pp, sct_len)) == NULL)
304e71b7053SJung-uk Kim             goto err;
305e71b7053SJung-uk Kim         if (!sk_SCT_push(sk, sct)) {
306e71b7053SJung-uk Kim             SCT_free(sct);
307e71b7053SJung-uk Kim             goto err;
308e71b7053SJung-uk Kim         }
309e71b7053SJung-uk Kim     }
310e71b7053SJung-uk Kim 
311e71b7053SJung-uk Kim     if (a != NULL && *a == NULL)
312e71b7053SJung-uk Kim         *a = sk;
313e71b7053SJung-uk Kim     return sk;
314e71b7053SJung-uk Kim 
315e71b7053SJung-uk Kim  err:
316e71b7053SJung-uk Kim     if (a == NULL || *a == NULL)
317e71b7053SJung-uk Kim         SCT_LIST_free(sk);
318e71b7053SJung-uk Kim     return NULL;
319e71b7053SJung-uk Kim }
320e71b7053SJung-uk Kim 
i2o_SCT_LIST(const STACK_OF (SCT)* a,unsigned char ** pp)321e71b7053SJung-uk Kim int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp)
322e71b7053SJung-uk Kim {
323e71b7053SJung-uk Kim     int len, sct_len, i, is_pp_new = 0;
324e71b7053SJung-uk Kim     size_t len2;
325e71b7053SJung-uk Kim     unsigned char *p = NULL, *p2;
326e71b7053SJung-uk Kim 
327e71b7053SJung-uk Kim     if (pp != NULL) {
328e71b7053SJung-uk Kim         if (*pp == NULL) {
329e71b7053SJung-uk Kim             if ((len = i2o_SCT_LIST(a, NULL)) == -1) {
330*b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
331e71b7053SJung-uk Kim                 return -1;
332e71b7053SJung-uk Kim             }
333e71b7053SJung-uk Kim             if ((*pp = OPENSSL_malloc(len)) == NULL) {
334*b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
335e71b7053SJung-uk Kim                 return -1;
336e71b7053SJung-uk Kim             }
337e71b7053SJung-uk Kim             is_pp_new = 1;
338e71b7053SJung-uk Kim         }
339e71b7053SJung-uk Kim         p = *pp + 2;
340e71b7053SJung-uk Kim     }
341e71b7053SJung-uk Kim 
342e71b7053SJung-uk Kim     len2 = 2;
343e71b7053SJung-uk Kim     for (i = 0; i < sk_SCT_num(a); i++) {
344e71b7053SJung-uk Kim         if (pp != NULL) {
345e71b7053SJung-uk Kim             p2 = p;
346e71b7053SJung-uk Kim             p += 2;
347e71b7053SJung-uk Kim             if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1)
348e71b7053SJung-uk Kim                 goto err;
349e71b7053SJung-uk Kim             s2n(sct_len, p2);
350e71b7053SJung-uk Kim         } else {
351e71b7053SJung-uk Kim           if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1)
352e71b7053SJung-uk Kim               goto err;
353e71b7053SJung-uk Kim         }
354e71b7053SJung-uk Kim         len2 += 2 + sct_len;
355e71b7053SJung-uk Kim     }
356e71b7053SJung-uk Kim 
357e71b7053SJung-uk Kim     if (len2 > MAX_SCT_LIST_SIZE)
358e71b7053SJung-uk Kim         goto err;
359e71b7053SJung-uk Kim 
360e71b7053SJung-uk Kim     if (pp != NULL) {
361e71b7053SJung-uk Kim         p = *pp;
362e71b7053SJung-uk Kim         s2n(len2 - 2, p);
363e71b7053SJung-uk Kim         if (!is_pp_new)
364e71b7053SJung-uk Kim             *pp += len2;
365e71b7053SJung-uk Kim     }
366e71b7053SJung-uk Kim     return len2;
367e71b7053SJung-uk Kim 
368e71b7053SJung-uk Kim  err:
369e71b7053SJung-uk Kim     if (is_pp_new) {
370e71b7053SJung-uk Kim         OPENSSL_free(*pp);
371e71b7053SJung-uk Kim         *pp = NULL;
372e71b7053SJung-uk Kim     }
373e71b7053SJung-uk Kim     return -1;
374e71b7053SJung-uk Kim }
375e71b7053SJung-uk Kim 
STACK_OF(SCT)376e71b7053SJung-uk Kim STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
377e71b7053SJung-uk Kim                             long len)
378e71b7053SJung-uk Kim {
379e71b7053SJung-uk Kim     ASN1_OCTET_STRING *oct = NULL;
380e71b7053SJung-uk Kim     STACK_OF(SCT) *sk = NULL;
381e71b7053SJung-uk Kim     const unsigned char *p;
382e71b7053SJung-uk Kim 
383e71b7053SJung-uk Kim     p = *pp;
384e71b7053SJung-uk Kim     if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL)
385e71b7053SJung-uk Kim         return NULL;
386e71b7053SJung-uk Kim 
387e71b7053SJung-uk Kim     p = oct->data;
388e71b7053SJung-uk Kim     if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL)
389e71b7053SJung-uk Kim         *pp += len;
390e71b7053SJung-uk Kim 
391e71b7053SJung-uk Kim     ASN1_OCTET_STRING_free(oct);
392e71b7053SJung-uk Kim     return sk;
393e71b7053SJung-uk Kim }
394e71b7053SJung-uk Kim 
i2d_SCT_LIST(const STACK_OF (SCT)* a,unsigned char ** out)395e71b7053SJung-uk Kim int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **out)
396e71b7053SJung-uk Kim {
397e71b7053SJung-uk Kim     ASN1_OCTET_STRING oct;
398e71b7053SJung-uk Kim     int len;
399e71b7053SJung-uk Kim 
400e71b7053SJung-uk Kim     oct.data = NULL;
401e71b7053SJung-uk Kim     if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1)
402e71b7053SJung-uk Kim         return -1;
403e71b7053SJung-uk Kim 
404e71b7053SJung-uk Kim     len = i2d_ASN1_OCTET_STRING(&oct, out);
405e71b7053SJung-uk Kim     OPENSSL_free(oct.data);
406e71b7053SJung-uk Kim     return len;
407e71b7053SJung-uk Kim }
408