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