Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/ct/ct_sct_ctx.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: ct_sct_ctx.c,v 1.6 2022/06/30 11:14:47 tb Exp $ */
2
/*
3
 * Written by Rob Stradling (rob@comodo.com) and Stephen Henson
4
 * (steve@openssl.org) for the OpenSSL project 2014.
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 is disabled"
62
#endif
63
64
#include <stddef.h>
65
#include <string.h>
66
67
#include <openssl/err.h>
68
#include <openssl/objects.h>
69
#include <openssl/x509.h>
70
71
#include "ct_local.h"
72
73
SCT_CTX *
74
SCT_CTX_new(void)
75
0
{
76
0
  SCT_CTX *sctx = calloc(1, sizeof(*sctx));
77
78
0
  if (sctx == NULL)
79
0
    CTerror(ERR_R_MALLOC_FAILURE);
80
81
0
  return sctx;
82
0
}
83
84
void
85
SCT_CTX_free(SCT_CTX *sctx)
86
0
{
87
0
  if (sctx == NULL)
88
0
    return;
89
0
  EVP_PKEY_free(sctx->pkey);
90
0
  free(sctx->pkeyhash);
91
0
  free(sctx->ihash);
92
0
  free(sctx->certder);
93
0
  free(sctx->preder);
94
0
  free(sctx);
95
0
}
96
97
/*
98
 * Finds the index of the first extension with the given NID in cert.
99
 * If there is more than one extension with that NID, *is_duplicated is set to
100
 * 1, otherwise 0 (unless it is NULL).
101
 */
102
static int
103
ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated)
104
0
{
105
0
  int ret = X509_get_ext_by_NID(cert, nid, -1);
106
107
0
  if (is_duplicated != NULL)
108
0
    *is_duplicated = ret >= 0 &&
109
0
        X509_get_ext_by_NID(cert, nid, ret) >= 0;
110
111
0
  return ret;
112
0
}
113
114
/*
115
 * Modifies a certificate by deleting extensions and copying the issuer and
116
 * AKID from the presigner certificate, if necessary.
117
 * Returns 1 on success, 0 otherwise.
118
 */
119
static int
120
ct_x509_cert_fixup(X509 *cert, X509 *presigner)
121
0
{
122
0
  int preidx, certidx;
123
0
  int pre_akid_ext_is_dup, cert_akid_ext_is_dup;
124
125
0
  if (presigner == NULL)
126
0
    return 1;
127
128
0
  preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier,
129
0
      &pre_akid_ext_is_dup);
130
0
  certidx = ct_x509_get_ext(cert, NID_authority_key_identifier,
131
0
      &cert_akid_ext_is_dup);
132
133
  /* An error occurred whilst searching for the extension */
134
0
  if (preidx < -1 || certidx < -1)
135
0
    return 0;
136
  /* Invalid certificate if they contain duplicate extensions */
137
0
  if (pre_akid_ext_is_dup || cert_akid_ext_is_dup)
138
0
    return 0;
139
  /* AKID must be present in both certificate or absent in both */
140
0
  if (preidx >= 0 && certidx == -1)
141
0
    return 0;
142
0
  if (preidx == -1 && certidx >= 0)
143
0
    return 0;
144
  /* Copy issuer name */
145
0
  if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner)))
146
0
    return 0;
147
0
  if (preidx != -1) {
148
    /* Retrieve and copy AKID encoding */
149
0
    X509_EXTENSION *preext = X509_get_ext(presigner, preidx);
150
0
    X509_EXTENSION *certext = X509_get_ext(cert, certidx);
151
0
    ASN1_OCTET_STRING *preextdata;
152
153
    /* Should never happen */
154
0
    if (preext == NULL || certext == NULL)
155
0
      return 0;
156
0
    preextdata = X509_EXTENSION_get_data(preext);
157
0
    if (preextdata == NULL ||
158
0
        !X509_EXTENSION_set_data(certext, preextdata))
159
0
      return 0;
160
0
  }
161
0
  return 1;
162
0
}
163
164
int
165
SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner)
166
0
{
167
0
  unsigned char *certder = NULL, *preder = NULL;
168
0
  X509 *pretmp = NULL;
169
0
  int certderlen = 0, prederlen = 0;
170
0
  int idx = -1;
171
0
  int poison_ext_is_dup, sct_ext_is_dup;
172
0
  int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup);
173
174
  /* Duplicate poison extensions are present - error */
175
0
  if (poison_ext_is_dup)
176
0
    goto err;
177
178
  /* If *cert doesn't have a poison extension, it isn't a precert */
179
0
  if (poison_idx == -1) {
180
    /* cert isn't a precert, so we shouldn't have a presigner */
181
0
    if (presigner != NULL)
182
0
      goto err;
183
184
0
    certderlen = i2d_X509(cert, &certder);
185
0
    if (certderlen < 0)
186
0
      goto err;
187
0
  }
188
189
  /* See if cert has a precert SCTs extension */
190
0
  idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup);
191
  /* Duplicate SCT extensions are present - error */
192
0
  if (sct_ext_is_dup)
193
0
    goto err;
194
195
0
  if (idx >= 0 && poison_idx >= 0) {
196
    /*
197
     * cert can't both contain SCTs (i.e. have an SCT extension) and be a
198
     * precert (i.e. have a poison extension).
199
     */
200
0
    goto err;
201
0
  }
202
203
0
  if (idx == -1) {
204
0
    idx = poison_idx;
205
0
  }
206
207
  /*
208
   * If either a poison or SCT extension is present, remove it before encoding
209
   * cert. This, along with ct_x509_cert_fixup(), gets a TBSCertificate (see
210
   * RFC5280) from cert, which is what the CT log signed when it produced the
211
   * SCT.
212
   */
213
0
  if (idx >= 0) {
214
0
    X509_EXTENSION *ext;
215
216
    /* Take a copy of certificate so we don't modify passed version */
217
0
    pretmp = X509_dup(cert);
218
0
    if (pretmp == NULL)
219
0
      goto err;
220
221
0
    ext = X509_delete_ext(pretmp, idx);
222
0
    X509_EXTENSION_free(ext);
223
224
0
    if (!ct_x509_cert_fixup(pretmp, presigner))
225
0
      goto err;
226
227
0
    prederlen = i2d_re_X509_tbs(pretmp, &preder);
228
0
    if (prederlen <= 0)
229
0
      goto err;
230
0
  }
231
232
0
  X509_free(pretmp);
233
234
0
  free(sctx->certder);
235
0
  sctx->certder = certder;
236
0
  sctx->certderlen = certderlen;
237
238
0
  free(sctx->preder);
239
0
  sctx->preder = preder;
240
0
  sctx->prederlen = prederlen;
241
242
0
  return 1;
243
0
 err:
244
0
  free(certder);
245
0
  free(preder);
246
0
  X509_free(pretmp);
247
0
  return 0;
248
0
}
249
250
static int
251
ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash, size_t *hash_len)
252
0
{
253
0
  int ret = 0;
254
0
  unsigned char *md = NULL, *der = NULL;
255
0
  int der_len;
256
0
  unsigned int md_len;
257
258
  /* Reuse buffer if possible */
259
0
  if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) {
260
0
    md = *hash;
261
0
  } else {
262
0
    md = malloc(SHA256_DIGEST_LENGTH);
263
0
    if (md == NULL)
264
0
      goto err;
265
0
  }
266
267
  /* Calculate key hash */
268
0
  der_len = i2d_X509_PUBKEY(pkey, &der);
269
0
  if (der_len <= 0)
270
0
    goto err;
271
272
0
  if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL))
273
0
    goto err;
274
275
0
  if (md != *hash) {
276
0
    free(*hash);
277
0
    *hash = md;
278
0
    *hash_len = SHA256_DIGEST_LENGTH;
279
0
  }
280
281
0
  md = NULL;
282
0
  ret = 1;
283
0
 err:
284
0
  free(md);
285
0
  free(der);
286
0
  return ret;
287
0
}
288
289
int
290
SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer)
291
0
{
292
0
  return SCT_CTX_set1_issuer_pubkey(sctx, X509_get_X509_PUBKEY(issuer));
293
0
}
294
295
int
296
SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
297
0
{
298
0
  return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen);
299
0
}
300
301
int
302
SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
303
0
{
304
0
  EVP_PKEY *pkey = X509_PUBKEY_get(pubkey);
305
306
0
  if (pkey == NULL)
307
0
    return 0;
308
309
0
  if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
310
0
    EVP_PKEY_free(pkey);
311
0
    return 0;
312
0
  }
313
314
0
  EVP_PKEY_free(sctx->pkey);
315
0
  sctx->pkey = pkey;
316
0
  return 1;
317
0
}
318
319
void
320
SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms)
321
0
{
322
0
  sctx->epoch_time_in_ms = time_in_ms;
323
0
}