123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- /*
- * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
- #ifdef OPENSSL_NO_CT
- # error "CT is disabled"
- #endif
- #include <limits.h>
- #include <string.h>
- #include <openssl/asn1.h>
- #include <openssl/buffer.h>
- #include <openssl/ct.h>
- #include <openssl/err.h>
- #include "ct_local.h"
- int o2i_SCT_signature(SCT *sct, const unsigned char **in, size_t len)
- {
- size_t siglen;
- size_t len_remaining = len;
- const unsigned char *p;
- if (sct->version != SCT_VERSION_V1) {
- ERR_raise(ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION);
- return -1;
- }
- /*
- * digitally-signed struct header: (1 byte) Hash algorithm (1 byte)
- * Signature algorithm (2 bytes + ?) Signature
- *
- * This explicitly rejects empty signatures: they're invalid for
- * all supported algorithms.
- */
- if (len <= 4) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
- return -1;
- }
- p = *in;
- /* Get hash and signature algorithm */
- sct->hash_alg = *p++;
- sct->sig_alg = *p++;
- if (SCT_get_signature_nid(sct) == NID_undef) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
- return -1;
- }
- /* Retrieve signature and check it is consistent with the buffer length */
- n2s(p, siglen);
- len_remaining -= (p - *in);
- if (siglen > len_remaining) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
- return -1;
- }
- if (SCT_set1_signature(sct, p, siglen) != 1)
- return -1;
- len_remaining -= siglen;
- *in = p + siglen;
- return len - len_remaining;
- }
- SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
- {
- SCT *sct = NULL;
- const unsigned char *p;
- if (len == 0 || len > MAX_SCT_SIZE) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
- goto err;
- }
- if ((sct = SCT_new()) == NULL)
- goto err;
- p = *in;
- sct->version = *p;
- if (sct->version == SCT_VERSION_V1) {
- int sig_len;
- size_t len2;
- /*-
- * Fixed-length header:
- * struct {
- * Version sct_version; (1 byte)
- * log_id id; (32 bytes)
- * uint64 timestamp; (8 bytes)
- * CtExtensions extensions; (2 bytes + ?)
- * }
- */
- if (len < 43) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
- goto err;
- }
- len -= 43;
- p++;
- sct->log_id = OPENSSL_memdup(p, CT_V1_HASHLEN);
- if (sct->log_id == NULL)
- goto err;
- sct->log_id_len = CT_V1_HASHLEN;
- p += CT_V1_HASHLEN;
- n2l8(p, sct->timestamp);
- n2s(p, len2);
- if (len < len2) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
- goto err;
- }
- if (len2 > 0) {
- sct->ext = OPENSSL_memdup(p, len2);
- if (sct->ext == NULL)
- goto err;
- }
- sct->ext_len = len2;
- p += len2;
- len -= len2;
- sig_len = o2i_SCT_signature(sct, &p, len);
- if (sig_len <= 0) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID);
- goto err;
- }
- len -= sig_len;
- *in = p + len;
- } else {
- /* If not V1 just cache encoding */
- sct->sct = OPENSSL_memdup(p, len);
- if (sct->sct == NULL)
- goto err;
- sct->sct_len = len;
- *in = p + len;
- }
- if (psct != NULL) {
- SCT_free(*psct);
- *psct = sct;
- }
- return sct;
- err:
- SCT_free(sct);
- return NULL;
- }
- int i2o_SCT_signature(const SCT *sct, unsigned char **out)
- {
- size_t len;
- unsigned char *p = NULL, *pstart = NULL;
- if (!SCT_signature_is_complete(sct)) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_INVALID_SIGNATURE);
- goto err;
- }
- if (sct->version != SCT_VERSION_V1) {
- ERR_raise(ERR_LIB_CT, CT_R_UNSUPPORTED_VERSION);
- goto err;
- }
- /*
- * (1 byte) Hash algorithm
- * (1 byte) Signature algorithm
- * (2 bytes + ?) Signature
- */
- len = 4 + sct->sig_len;
- if (out != NULL) {
- if (*out != NULL) {
- p = *out;
- *out += len;
- } else {
- pstart = p = OPENSSL_malloc(len);
- if (p == NULL)
- goto err;
- *out = p;
- }
- *p++ = sct->hash_alg;
- *p++ = sct->sig_alg;
- s2n(sct->sig_len, p);
- memcpy(p, sct->sig, sct->sig_len);
- }
- return len;
- err:
- OPENSSL_free(pstart);
- return -1;
- }
- int i2o_SCT(const SCT *sct, unsigned char **out)
- {
- size_t len;
- unsigned char *p = NULL, *pstart = NULL;
- if (!SCT_is_complete(sct)) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_NOT_SET);
- goto err;
- }
- /*
- * Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes)
- * log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions
- * extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2
- * bytes + ?) Signature
- */
- if (sct->version == SCT_VERSION_V1)
- len = 43 + sct->ext_len + 4 + sct->sig_len;
- else
- len = sct->sct_len;
- if (out == NULL)
- return len;
- if (*out != NULL) {
- p = *out;
- *out += len;
- } else {
- pstart = p = OPENSSL_malloc(len);
- if (p == NULL)
- goto err;
- *out = p;
- }
- if (sct->version == SCT_VERSION_V1) {
- *p++ = sct->version;
- memcpy(p, sct->log_id, CT_V1_HASHLEN);
- p += CT_V1_HASHLEN;
- l2n8(sct->timestamp, p);
- s2n(sct->ext_len, p);
- if (sct->ext_len > 0) {
- memcpy(p, sct->ext, sct->ext_len);
- p += sct->ext_len;
- }
- if (i2o_SCT_signature(sct, &p) <= 0)
- goto err;
- } else {
- memcpy(p, sct->sct, len);
- }
- return len;
- err:
- OPENSSL_free(pstart);
- return -1;
- }
- STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
- size_t len)
- {
- STACK_OF(SCT) *sk = NULL;
- size_t list_len, sct_len;
- if (len < 2 || len > MAX_SCT_LIST_SIZE) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
- return NULL;
- }
- n2s(*pp, list_len);
- if (list_len != len - 2) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
- return NULL;
- }
- if (a == NULL || *a == NULL) {
- sk = sk_SCT_new_null();
- if (sk == NULL)
- return NULL;
- } else {
- SCT *sct;
- /* Use the given stack, but empty it first. */
- sk = *a;
- while ((sct = sk_SCT_pop(sk)) != NULL)
- SCT_free(sct);
- }
- while (list_len > 0) {
- SCT *sct;
- if (list_len < 2) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
- goto err;
- }
- n2s(*pp, sct_len);
- list_len -= 2;
- if (sct_len == 0 || sct_len > list_len) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
- goto err;
- }
- list_len -= sct_len;
- if ((sct = o2i_SCT(NULL, pp, sct_len)) == NULL)
- goto err;
- if (!sk_SCT_push(sk, sct)) {
- SCT_free(sct);
- goto err;
- }
- }
- if (a != NULL && *a == NULL)
- *a = sk;
- return sk;
- err:
- if (a == NULL || *a == NULL)
- SCT_LIST_free(sk);
- return NULL;
- }
- int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp)
- {
- int len, sct_len, i, is_pp_new = 0;
- size_t len2;
- unsigned char *p = NULL, *p2;
- if (pp != NULL) {
- if (*pp == NULL) {
- if ((len = i2o_SCT_LIST(a, NULL)) == -1) {
- ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID);
- return -1;
- }
- if ((*pp = OPENSSL_malloc(len)) == NULL)
- return -1;
- is_pp_new = 1;
- }
- p = *pp + 2;
- }
- len2 = 2;
- for (i = 0; i < sk_SCT_num(a); i++) {
- if (pp != NULL) {
- p2 = p;
- p += 2;
- if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1)
- goto err;
- s2n(sct_len, p2);
- } else {
- if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1)
- goto err;
- }
- len2 += 2 + sct_len;
- }
- if (len2 > MAX_SCT_LIST_SIZE)
- goto err;
- if (pp != NULL) {
- p = *pp;
- s2n(len2 - 2, p);
- if (!is_pp_new)
- *pp += len2;
- }
- return len2;
- err:
- if (is_pp_new) {
- OPENSSL_free(*pp);
- *pp = NULL;
- }
- return -1;
- }
- STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
- long len)
- {
- ASN1_OCTET_STRING *oct = NULL;
- STACK_OF(SCT) *sk = NULL;
- const unsigned char *p;
- p = *pp;
- if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL)
- return NULL;
- p = oct->data;
- if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL)
- *pp += len;
- ASN1_OCTET_STRING_free(oct);
- return sk;
- }
- int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **out)
- {
- ASN1_OCTET_STRING oct;
- int len;
- oct.data = NULL;
- if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1)
- return -1;
- len = i2d_ASN1_OCTET_STRING(&oct, out);
- OPENSSL_free(oct.data);
- return len;
- }
|