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