Coverage Report

Created: 2023-11-19 06:33

/src/strongswan/src/libstrongswan/plugins/x509/x509_ocsp_request.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2017-2019 Tobias Brunner
3
 * Copyright (C) 2008-2009 Martin Willi
4
 * Copyright (C) 2007-2023 Andreas Steffen, strongSec GmbH
5
 * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
6
 *
7
 * Copyright (C) secunet Security Networks AG
8
 *
9
 * This program is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU General Public License as published by the
11
 * Free Software Foundation; either version 2 of the License, or (at your
12
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
13
 *
14
 * This program is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17
 * for more details.
18
 */
19
20
#include "x509_ocsp_request.h"
21
22
#include <library.h>
23
#include <asn1/oid.h>
24
#include <asn1/asn1.h>
25
#include <asn1/asn1_parser.h>
26
#include <utils/identification.h>
27
#include <collections/linked_list.h>
28
#include <utils/debug.h>
29
#include <credentials/certificates/x509.h>
30
#include <credentials/keys/private_key.h>
31
32
/* RFC 8954 OCSP Nonce Extension */
33
0
#define NONCE_LEN   32
34
35
typedef struct private_x509_ocsp_request_t private_x509_ocsp_request_t;
36
37
/**
38
 * private data of x509_ocsp_request
39
 */
40
struct private_x509_ocsp_request_t {
41
42
  /**
43
   * public functions
44
   */
45
  x509_ocsp_request_t public;
46
47
  /**
48
   * CA the certificates where issued by
49
   */
50
  certificate_t *cacert;
51
52
  /**
53
   * Requestor name, subject of cert used if not set
54
   */
55
  identification_t *requestor;
56
57
  /**
58
   * Requestor certificate, included in request
59
   */
60
  certificate_t *cert;
61
62
  /**
63
   * Requestor private key to sign request
64
   */
65
  private_key_t *key;
66
67
  /**
68
   * list of X.509 certificates to check
69
   */
70
  linked_list_t *reqCerts;
71
72
  /**
73
   * nonce used in request
74
   */
75
  chunk_t nonce;
76
77
  /**
78
   * encoded OCSP request
79
   */
80
  chunk_t encoding;
81
82
  /**
83
   * data for signature verification
84
   */
85
  chunk_t tbsRequest;
86
87
  /**
88
   * signature scheme
89
   */
90
  signature_params_t *scheme;
91
92
  /**
93
   * signature
94
   */
95
  chunk_t signature;
96
97
  /**
98
   * reference count
99
   */
100
  refcount_t ref;
101
};
102
103
/**
104
 * Single reqCert object sent in OCSP request
105
 */
106
typedef struct {
107
  /** hash algorithm for the two hashes */
108
  hash_algorithm_t hashAlgorithm;
109
  /** hash of issuer DN */
110
  chunk_t issuerNameHash;
111
  /** issuerKeyID */
112
  chunk_t issuerKeyHash;
113
  /** serial number of certificate */
114
  chunk_t serialNumber;
115
} req_cert_t;
116
117
/**
118
 * Clean up a reqCert object
119
 */
120
CALLBACK(req_cert_destroy, void,
121
  req_cert_t *reqCert)
122
0
{
123
0
  chunk_free(&reqCert->issuerNameHash);
124
0
  chunk_free(&reqCert->issuerKeyHash);
125
0
  chunk_free(&reqCert->serialNumber);
126
0
  free(reqCert);
127
0
}
128
129
static const chunk_t ASN1_nonce_oid = chunk_from_chars(
130
  0x06, 0x09,
131
      0x2B, 0x06,
132
        0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
133
);
134
static const chunk_t ASN1_response_oid = chunk_from_chars(
135
  0x06, 0x09,
136
      0x2B, 0x06,
137
        0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
138
);
139
static const chunk_t ASN1_response_content = chunk_from_chars(
140
  0x04, 0x0D,
141
      0x30, 0x0B,
142
        0x06, 0x09,
143
        0x2B, 0x06,
144
        0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
145
);
146
147
/**
148
 * build requestorName
149
 */
150
static chunk_t build_requestorName(private_x509_ocsp_request_t *this)
151
0
{
152
0
  if (this->requestor || this->cert)
153
0
  { /* use requestor name, fallback to his cert subject */
154
0
    if (!this->requestor)
155
0
    {
156
0
      this->requestor = this->cert->get_subject(this->cert);
157
0
      this->requestor = this->requestor->clone(this->requestor);
158
0
    }
159
0
    return asn1_wrap(ASN1_CONTEXT_C_1, "m",
160
0
          asn1_simple_object(ASN1_CONTEXT_C_4,
161
0
            this->requestor->get_encoding(this->requestor)));
162
163
0
  }
164
0
  return chunk_empty;
165
0
}
166
167
/**
168
 * build Request, not using singleRequestExtensions
169
 */
170
static chunk_t build_Request(private_x509_ocsp_request_t *this,
171
               req_cert_t *reqCert)
172
0
{
173
0
  return asn1_wrap(ASN1_SEQUENCE, "m",
174
0
      asn1_wrap(ASN1_SEQUENCE, "mmmm",
175
0
        asn1_algorithmIdentifier(
176
0
          hasher_algorithm_to_oid(reqCert->hashAlgorithm)),
177
0
        asn1_simple_object(ASN1_OCTET_STRING, reqCert->issuerNameHash),
178
0
        asn1_simple_object(ASN1_OCTET_STRING, reqCert->issuerKeyHash),
179
0
        asn1_integer("c", reqCert->serialNumber)));
180
0
}
181
182
/**
183
 * build requestList
184
 */
185
static chunk_t build_requestList(private_x509_ocsp_request_t *this)
186
0
{
187
0
  chunk_t list = chunk_empty, request;
188
0
  enumerator_t *enumerator;
189
0
  req_cert_t *reqCert;
190
191
0
  enumerator = this->reqCerts->create_enumerator(this->reqCerts);
192
0
  while (enumerator->enumerate(enumerator, &reqCert))
193
0
  {
194
0
    request = build_Request(this, reqCert);
195
0
    list = chunk_cat("mm", list, request);
196
0
  }
197
0
  enumerator->destroy(enumerator);
198
199
0
  return asn1_wrap(ASN1_SEQUENCE, "m", list);
200
0
}
201
202
/**
203
 * build nonce extension
204
 */
205
static chunk_t build_nonce(private_x509_ocsp_request_t *this)
206
0
{
207
0
  rng_t *rng;
208
209
0
  rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
210
0
  if (!rng || !rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
211
0
  {
212
0
    DBG1(DBG_LIB, "failed to create RNG");
213
0
    DESTROY_IF(rng);
214
0
    return chunk_empty;
215
0
  }
216
0
  rng->destroy(rng);
217
0
  return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid,
218
0
        asn1_wrap(ASN1_OCTET_STRING, "m",
219
0
          asn1_simple_object(ASN1_OCTET_STRING, this->nonce)));
220
0
}
221
222
/**
223
 * build acceptableResponses extension
224
 */
225
static chunk_t build_acceptableResponses(private_x509_ocsp_request_t *this)
226
0
{
227
0
  return asn1_wrap(ASN1_SEQUENCE, "cc",
228
0
        ASN1_response_oid,
229
0
        ASN1_response_content);
230
0
}
231
232
/**
233
 * build requestExtensions
234
 */
235
static chunk_t build_requestExtensions(private_x509_ocsp_request_t *this)
236
0
{
237
0
  return asn1_wrap(ASN1_CONTEXT_C_2, "m",
238
0
        asn1_wrap(ASN1_SEQUENCE, "mm",
239
0
          build_nonce(this),
240
0
          build_acceptableResponses(this)));
241
0
}
242
243
/**
244
 * Build tbsRequest
245
 */
246
static chunk_t build_tbsRequest(private_x509_ocsp_request_t *this)
247
0
{
248
0
  return asn1_wrap(ASN1_SEQUENCE, "mmm",
249
0
        build_requestorName(this),
250
0
        build_requestList(this),
251
0
        build_requestExtensions(this));
252
0
}
253
254
/**
255
 * Build the optionalSignature
256
 */
257
static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
258
                     chunk_t tbsRequest)
259
0
{
260
0
  int oid;
261
0
  signature_scheme_t scheme;
262
0
  chunk_t certs = chunk_empty, signature, encoding;
263
264
0
  switch (this->key->get_type(this->key))
265
0
  {
266
    /* TODO: use a generic mapping function */
267
0
    case KEY_RSA:
268
0
      oid = OID_SHA1_WITH_RSA;
269
0
      scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
270
0
      break;
271
0
    case KEY_ECDSA:
272
0
      oid = OID_ECDSA_WITH_SHA1;
273
0
      scheme = SIGN_ECDSA_WITH_SHA1_DER;
274
0
      break;
275
0
    case KEY_BLISS:
276
0
      oid = OID_BLISS_WITH_SHA2_512;
277
0
      scheme = SIGN_BLISS_WITH_SHA2_512;
278
0
      break;
279
0
    default:
280
0
      DBG1(DBG_LIB, "unable to sign OCSP request, %N signature not "
281
0
         "supported", key_type_names, this->key->get_type(this->key));
282
0
      return chunk_empty;
283
0
  }
284
285
0
  if (!this->key->sign(this->key, scheme, NULL, tbsRequest, &signature))
286
0
  {
287
0
    DBG1(DBG_LIB, "creating OCSP signature failed, skipped");
288
0
    return chunk_empty;
289
0
  }
290
0
  if (this->cert &&
291
0
    this->cert->get_encoding(this->cert, CERT_ASN1_DER, &encoding))
292
0
  {
293
0
    certs = asn1_wrap(ASN1_CONTEXT_C_0, "m",
294
0
          asn1_wrap(ASN1_SEQUENCE, "m", encoding));
295
0
  }
296
0
  return asn1_wrap(ASN1_CONTEXT_C_0, "m",
297
0
        asn1_wrap(ASN1_SEQUENCE, "cmm",
298
0
          asn1_algorithmIdentifier(oid),
299
0
          asn1_bitstring("m", signature),
300
0
          certs));
301
0
}
302
303
/**
304
 * Build the OCSPRequest data
305
 */
306
static chunk_t build_OCSPRequest(private_x509_ocsp_request_t *this)
307
0
{
308
0
  chunk_t tbsRequest, optionalSignature = chunk_empty;
309
310
0
  tbsRequest = build_tbsRequest(this);
311
0
  if (this->key)
312
0
  {
313
0
    optionalSignature = build_optionalSignature(this, tbsRequest);
314
0
  }
315
0
  return asn1_wrap(ASN1_SEQUENCE, "mm", tbsRequest, optionalSignature);
316
0
}
317
318
/**
319
 * ASN.1 definition of ocspRequest
320
 */
321
static const asn1Object_t ocspRequestObjects[] = {
322
  { 0, "OCSPRequest",                     ASN1_SEQUENCE,     ASN1_NONE }, /*  0 */
323
  { 1,   "tbsRequest",                    ASN1_SEQUENCE,     ASN1_OBJ  }, /*  1 */
324
  { 2,     "versionContext",              ASN1_CONTEXT_C_0,  ASN1_NONE |
325
                                                             ASN1_DEF  }, /*  2 */
326
  { 3,       "version",                   ASN1_INTEGER,      ASN1_BODY }, /*  3 */
327
  { 2,     "requestorNameContext",        ASN1_CONTEXT_C_1,  ASN1_OPT  }, /*  4 */
328
  { 3,       "requestorName",             ASN1_CONTEXT_C_4,  ASN1_BODY }, /*  5 */
329
  { 2,     "end opt",                     ASN1_EOC,          ASN1_END  }, /*  6 */
330
  { 2,     "requestList",                 ASN1_SEQUENCE,     ASN1_LOOP }, /*  7 */
331
  { 3,       "request",                   ASN1_SEQUENCE,     ASN1_BODY }, /*  8 */
332
  { 4,         "reqCert",                 ASN1_SEQUENCE,     ASN1_NONE }, /*  9 */
333
  { 5,           "hashAlgorithm",         ASN1_EOC,          ASN1_RAW  }, /* 10 */
334
  { 5,           "issuerNameHash",        ASN1_OCTET_STRING, ASN1_BODY }, /* 11 */
335
  { 5,           "issuerKeyHash",         ASN1_OCTET_STRING, ASN1_BODY }, /* 12 */
336
  { 5,           "serialNumber",          ASN1_INTEGER,      ASN1_BODY }, /* 13 */
337
  { 4,         "singleRequestExtensions", ASN1_CONTEXT_C_0,  ASN1_OPT  }, /* 14 */
338
  { 4,         "end opt",                 ASN1_EOC,          ASN1_END  }, /* 15 */
339
  { 2,     "end loop",                    ASN1_EOC,          ASN1_END  }, /* 16 */
340
  { 2,     "requestExtensions",           ASN1_CONTEXT_C_2,  ASN1_OPT  }, /* 17 */
341
  { 3,       "Extensions",                ASN1_SEQUENCE,     ASN1_LOOP }, /* 18 */
342
  { 4,         "Extension",               ASN1_SEQUENCE,     ASN1_NONE }, /* 19 */
343
  { 5,           "extnID",                ASN1_OID,          ASN1_BODY }, /* 20 */
344
  { 5,           "critical",              ASN1_BOOLEAN,      ASN1_BODY |
345
                                                             ASN1_DEF  }, /* 21 */
346
  { 5,           "extnValue",             ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
347
  { 3,       "end loop",                  ASN1_EOC,          ASN1_END  }, /* 23 */
348
  { 2,     "end opt",                     ASN1_EOC,          ASN1_END  }, /* 24 */
349
  { 1,   "optionalSignature",             ASN1_CONTEXT_C_0,  ASN1_OPT  }, /* 25 */
350
  { 2,     "signature",                   ASN1_SEQUENCE,     ASN1_NONE }, /* 26 */
351
  { 3,       "signatureAlgorithm",        ASN1_EOC,          ASN1_RAW  }, /* 27 */
352
  { 3,       "signature",                 ASN1_BIT_STRING,   ASN1_BODY }, /* 28 */
353
  { 3,       "certsContext",              ASN1_CONTEXT_C_0,  ASN1_OPT  }, /* 29 */
354
  { 4,         "certs",                   ASN1_SEQUENCE,     ASN1_LOOP }, /* 30 */
355
  { 5,           "certificate",           ASN1_EOC,          ASN1_RAW  }, /* 31 */
356
  { 4,         "end loop",                ASN1_EOC,          ASN1_END  }, /* 32 */
357
  { 3,       "end opt",                   ASN1_EOC,          ASN1_END  }, /* 33 */
358
  { 1,   "end opt",                       ASN1_EOC,          ASN1_END  }, /* 34 */
359
  { 0, "exit",                            ASN1_EOC,          ASN1_EXIT }
360
};
361
362
0
#define OCSP_REQ_TBS_REQUEST         1
363
0
#define OCSP_REQ_REQUESTOR           5
364
0
#define OCSP_REQ_REQ_CERT            9
365
0
#define OCSP_REQ_HASH_ALG           10
366
0
#define OCSP_REQ_ISSUER_NAME_HASH   11
367
0
#define OCSP_REQ_ISSUER_KEY_HASH    12
368
0
#define OCSP_REQ_SERIAL_NUMBER      13
369
0
#define OCSP_REQ_EXTN_ID            20
370
0
#define OCSP_REQ_CRITICAL           21
371
0
#define OCSP_REQ_EXTN_VALUE         22
372
0
#define OCSP_REQ_SIG_ALG            27
373
0
#define OCSP_REQ_SIGNATURE          28
374
0
#define OCSP_REQ_CERTIFICATE      31
375
376
/**
377
 * Parse the OCSPRequest data
378
 *
379
 */
380
static bool parse_OCSPRequest(private_x509_ocsp_request_t *this)
381
0
{
382
0
  asn1_parser_t *parser;
383
0
  req_cert_t *reqCert = NULL;
384
0
  chunk_t object;
385
0
  int extn_oid = OID_UNKNOWN;
386
0
  int objectID;
387
0
  bool critical = FALSE, success = FALSE;
388
389
0
  parser = asn1_parser_create(ocspRequestObjects, this->encoding);
390
391
0
  while (parser->iterate(parser, &objectID, &object))
392
0
  {
393
0
    u_int level = parser->get_level(parser)+1;
394
395
0
    switch (objectID)
396
0
    {
397
398
0
      case OCSP_REQ_TBS_REQUEST:
399
0
        this->tbsRequest = object;
400
0
        break;
401
0
      case OCSP_REQ_REQUESTOR:
402
0
        this->requestor = identification_create_from_encoding(ID_DER_ASN1_DN, object);
403
0
        break;
404
0
      case OCSP_REQ_REQ_CERT:
405
0
        INIT(reqCert);
406
0
        this->reqCerts->insert_last(this->reqCerts, reqCert);
407
0
        break;
408
0
      case OCSP_REQ_HASH_ALG:
409
0
        reqCert->hashAlgorithm = hasher_algorithm_from_oid(
410
0
              asn1_parse_algorithmIdentifier(object, level, NULL));
411
0
        if (reqCert->hashAlgorithm == HASH_UNKNOWN)
412
0
        {
413
0
          DBG1(DBG_ASN, "unknowm hash algorithm");
414
0
          goto end;
415
0
        }
416
0
        break;
417
0
      case OCSP_REQ_ISSUER_NAME_HASH:
418
0
        reqCert->issuerNameHash = chunk_clone(object);
419
0
        break;
420
0
      case OCSP_REQ_ISSUER_KEY_HASH:
421
0
        reqCert->issuerKeyHash = chunk_clone(object);
422
0
        break;
423
0
      case OCSP_REQ_SERIAL_NUMBER:
424
0
        reqCert->serialNumber = chunk_clone(chunk_skip_zero(object));
425
0
        break;
426
0
      case OCSP_REQ_EXTN_ID:
427
0
        extn_oid = asn1_known_oid(object);
428
0
        break;
429
0
      case OCSP_REQ_CRITICAL:
430
0
        critical = object.len && *object.ptr;
431
0
        DBG2(DBG_ASN, "  %s", critical ? "TRUE" : "FALSE");
432
0
        break;
433
0
      case OCSP_REQ_EXTN_VALUE:
434
0
      {
435
0
        switch (extn_oid)
436
0
        {
437
0
          case OID_NONCE:
438
0
            if (!asn1_parse_simple_object(&object, ASN1_OCTET_STRING,
439
0
                        level, "nonce"))
440
0
            {
441
0
              goto end;
442
0
            }
443
0
            this->nonce = chunk_clone(object);
444
0
            break;
445
0
          case OID_RESPONSE:
446
0
            if (!asn1_parse_simple_object(&object, ASN1_SEQUENCE,
447
0
                        level, "acceptableResponses"))
448
0
            {
449
0
              goto end;
450
0
            }
451
0
            break;
452
0
          default:
453
0
            if (critical && lib->settings->get_bool(lib->settings,
454
0
              "%s.x509.enforce_critical", TRUE, lib->ns))
455
0
            {
456
0
              DBG1(DBG_ASN, "critical '%s' extension not supported",
457
0
                 (extn_oid == OID_UNKNOWN) ? "unknown" :
458
0
                 (char*)oid_names[extn_oid].name);
459
0
              goto end;
460
0
            }
461
0
            break;
462
0
        }
463
0
        break;
464
0
      }
465
0
      case OCSP_REQ_SIG_ALG:
466
0
        INIT(this->scheme);
467
0
        if (!signature_params_parse(object, level, this->scheme))
468
0
        {
469
0
          DBG1(DBG_ASN, "  unable to parse signature algorithm");
470
0
          goto end;
471
0
        }
472
473
0
        break;
474
0
      case OCSP_REQ_SIGNATURE:
475
0
        this->signature = chunk_skip(object, 1);
476
0
        break;
477
0
      case OCSP_REQ_CERTIFICATE:
478
0
        if (this->cert)
479
0
        {
480
0
          DBG1(DBG_LIB, "  skipping additional signing certificate");
481
0
          break;
482
0
        }
483
0
        this->cert = lib->creds->create(lib->creds,
484
0
                  CRED_CERTIFICATE,CERT_X509,
485
0
                  BUILD_BLOB_ASN1_DER, object, BUILD_END);
486
0
        if (!this->cert)
487
0
        {
488
0
          goto end;
489
0
        }
490
0
        break;
491
0
    }
492
0
  }
493
0
  success = parser->success(parser);
494
495
0
end:
496
0
  parser->destroy(parser);
497
0
  return success;
498
0
}
499
500
METHOD(certificate_t, get_type, certificate_type_t,
501
  private_x509_ocsp_request_t *this)
502
0
{
503
0
  return CERT_X509_OCSP_REQUEST;
504
0
}
505
506
METHOD(certificate_t, get_subject, identification_t*,
507
  private_x509_ocsp_request_t *this)
508
0
{
509
0
  if (this->requestor)
510
0
  {
511
0
    return this->requestor;
512
0
  }
513
0
  return (this->cert) ? this->cert->get_subject(this->cert) : NULL;
514
0
}
515
516
METHOD(certificate_t, get_issuer, identification_t*,
517
  private_x509_ocsp_request_t *this)
518
0
{
519
0
  return this->cacert ? this->cacert->get_subject(this->cacert) : NULL;
520
0
}
521
522
METHOD(certificate_t, has_subject, id_match_t,
523
  private_x509_ocsp_request_t *this, identification_t *subject)
524
0
{
525
0
  return ID_MATCH_NONE;
526
0
}
527
528
METHOD(certificate_t, has_issuer, id_match_t,
529
  private_x509_ocsp_request_t *this,
530
               identification_t *issuer)
531
0
{
532
0
  return this->cacert ? this->cacert->has_subject(this->cacert, issuer) :
533
0
              ID_MATCH_NONE;
534
0
}
535
536
METHOD(certificate_t, issued_by, bool,
537
  private_x509_ocsp_request_t *this, certificate_t *issuer,
538
  signature_params_t **scheme)
539
0
{
540
0
  public_key_t *key;
541
0
  bool valid;
542
543
0
  if (issuer->get_type(issuer) != CERT_X509 || this->cert == NULL ||
544
0
     !issuer->equals(issuer, this->cert))
545
0
  {
546
0
    return FALSE;
547
0
  }
548
549
0
  key = issuer->get_public_key(issuer);
550
0
  if (!key)
551
0
  {
552
0
    return FALSE;
553
0
  }
554
0
  valid = key->verify(key, this->scheme->scheme, this->scheme->params,
555
0
            this->tbsRequest, this->signature);
556
0
  key->destroy(key);
557
558
0
  if (valid && scheme)
559
0
  {
560
0
    *scheme = signature_params_clone(this->scheme);
561
0
  }
562
0
  return valid;
563
0
}
564
565
METHOD(certificate_t, get_public_key, public_key_t*,
566
  private_x509_ocsp_request_t *this)
567
0
{
568
0
  return NULL;
569
0
}
570
571
METHOD(certificate_t, get_validity, bool,
572
  private_x509_ocsp_request_t *this, time_t *when, time_t *not_before,
573
  time_t *not_after)
574
0
{
575
0
  return FALSE;
576
0
}
577
578
METHOD(certificate_t, get_encoding, bool,
579
  private_x509_ocsp_request_t *this, cred_encoding_type_t type,
580
  chunk_t *encoding)
581
0
{
582
0
  if (type == CERT_ASN1_DER)
583
0
  {
584
0
    *encoding = chunk_clone(this->encoding);
585
0
    return TRUE;
586
0
  }
587
0
  return lib->encoding->encode(lib->encoding, type, NULL, encoding,
588
0
        CRED_PART_X509_OCSP_REQ_ASN1_DER, this->encoding, CRED_PART_END);
589
0
}
590
591
METHOD(certificate_t, equals, bool,
592
  private_x509_ocsp_request_t *this, certificate_t *other)
593
0
{
594
0
  chunk_t encoding;
595
0
  bool equal;
596
597
0
  if (this == (private_x509_ocsp_request_t*)other)
598
0
  {
599
0
    return TRUE;
600
0
  }
601
0
  if (other->get_type(other) != CERT_X509_OCSP_REQUEST)
602
0
  {
603
0
    return FALSE;
604
0
  }
605
0
  if (other->equals == (void*)equals)
606
0
  { /* skip allocation if we have the same implementation */
607
0
    return chunk_equals(this->encoding, ((private_x509_ocsp_request_t*)other)->encoding);
608
0
  }
609
0
  if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
610
0
  {
611
0
    return FALSE;
612
0
  }
613
0
  equal = chunk_equals(this->encoding, encoding);
614
0
  free(encoding.ptr);
615
0
  return equal;
616
0
}
617
618
METHOD(certificate_t, get_ref, certificate_t*,
619
  private_x509_ocsp_request_t *this)
620
0
{
621
0
  ref_get(&this->ref);
622
0
  return &this->public.interface.interface;
623
0
}
624
625
METHOD(certificate_t, destroy, void,
626
  private_x509_ocsp_request_t *this)
627
0
{
628
0
  if (ref_put(&this->ref))
629
0
  {
630
0
    DESTROY_IF(this->cacert);
631
0
    DESTROY_IF(this->requestor);
632
0
    DESTROY_IF(this->cert);
633
0
    DESTROY_IF(this->key);
634
0
    signature_params_destroy(this->scheme);
635
0
    this->reqCerts->destroy_function(this->reqCerts, req_cert_destroy);
636
0
    chunk_free(&this->nonce);
637
0
    chunk_free(&this->encoding);
638
0
    free(this);
639
0
  }
640
0
}
641
642
METHOD(ocsp_request_t, get_nonce, chunk_t,
643
  private_x509_ocsp_request_t *this)
644
0
{
645
0
  return this->nonce;
646
0
}
647
648
METHOD(ocsp_request_t, get_signer_cert, certificate_t*,
649
  private_x509_ocsp_request_t *this)
650
0
{
651
0
  return this->cert;
652
0
}
653
654
CALLBACK(filter, bool,
655
  void *data, enumerator_t *orig, va_list args)
656
0
{
657
0
  req_cert_t *reqCert;
658
0
  hash_algorithm_t *hashAlgorithm;
659
0
  chunk_t *issuerNameHash, *issuerKeyHash, *serialNumber;
660
661
0
  VA_ARGS_VGET(args, hashAlgorithm, issuerNameHash, issuerKeyHash, serialNumber);
662
663
0
  if (orig->enumerate(orig, &reqCert))
664
0
  {
665
0
    if (hashAlgorithm)
666
0
    {
667
0
      *hashAlgorithm = reqCert->hashAlgorithm;
668
0
    }
669
0
    if (issuerNameHash)
670
0
    {
671
0
      *issuerNameHash = reqCert->issuerNameHash;
672
0
    }
673
0
    if (issuerKeyHash)
674
0
    {
675
0
      *issuerKeyHash = reqCert->issuerKeyHash;
676
0
    }
677
0
    if (serialNumber)
678
0
    {
679
0
      *serialNumber = reqCert->serialNumber;
680
0
    }
681
0
    return TRUE;
682
0
  }
683
0
  return FALSE;
684
0
}
685
686
METHOD(ocsp_request_t, create_request_enumerator, enumerator_t*,
687
  private_x509_ocsp_request_t *this)
688
0
{
689
0
  return enumerator_create_filter(
690
0
        this->reqCerts->create_enumerator(this->reqCerts),
691
0
        filter, NULL, NULL);
692
0
}
693
694
/**
695
 * create an empty but initialized OCSP request
696
 */
697
static private_x509_ocsp_request_t *create_empty()
698
0
{
699
0
  private_x509_ocsp_request_t *this;
700
701
0
  INIT(this,
702
0
    .public = {
703
0
      .interface = {
704
0
        .interface = {
705
0
          .get_type = _get_type,
706
0
          .get_subject = _get_subject,
707
0
          .get_issuer = _get_issuer,
708
0
          .has_subject = _has_subject,
709
0
          .has_issuer = _has_issuer,
710
0
          .issued_by = _issued_by,
711
0
          .get_public_key = _get_public_key,
712
0
          .get_validity = _get_validity,
713
0
          .get_encoding = _get_encoding,
714
0
          .equals = _equals,
715
0
          .get_ref = _get_ref,
716
0
          .destroy = _destroy,
717
0
        },
718
0
        .get_nonce = _get_nonce,
719
0
        .get_signer_cert = _get_signer_cert,
720
0
        .create_request_enumerator = _create_request_enumerator,
721
0
      },
722
0
    },
723
0
    .reqCerts = linked_list_create(),
724
0
    .ref = 1,
725
0
  );
726
727
0
  return this;
728
0
}
729
730
/**
731
 * See header.
732
 */
733
x509_ocsp_request_t *x509_ocsp_request_gen(certificate_type_t type, va_list args)
734
0
{
735
0
  private_x509_ocsp_request_t *this;
736
0
  private_key_t *private;
737
0
  identification_t *subject;
738
0
  certificate_t *cert;
739
0
  x509_t *x509;
740
0
  req_cert_t *reqCert;
741
742
0
  this = create_empty();
743
744
0
  while (TRUE)
745
0
  {
746
0
    switch (va_arg(args, builder_part_t))
747
0
    {
748
0
      case BUILD_CA_CERT:
749
0
        cert = va_arg(args, certificate_t*);
750
0
        if (cert->get_type(cert) == CERT_X509)
751
0
        {
752
0
          this->cacert = cert->get_ref(cert);
753
0
        }
754
0
        continue;
755
0
      case BUILD_CERT:
756
0
        cert = va_arg(args, certificate_t*);
757
0
        if (cert->get_type(cert) == CERT_X509)
758
0
        {
759
0
          x509 = (x509_t*)cert;
760
0
          INIT(reqCert,
761
0
            .serialNumber = chunk_clone(x509->get_serial(x509)),
762
0
          );
763
0
          this->reqCerts->insert_last(this->reqCerts, reqCert);
764
0
        }
765
0
        continue;
766
0
      case BUILD_SIGNING_CERT:
767
0
        cert = va_arg(args, certificate_t*);
768
0
        this->cert = cert->get_ref(cert);
769
0
        continue;
770
0
      case BUILD_SIGNING_KEY:
771
0
        private = va_arg(args, private_key_t*);
772
0
        this->key = private->get_ref(private);
773
0
        continue;
774
0
      case BUILD_SUBJECT:
775
0
        subject = va_arg(args, identification_t*);
776
0
        this->requestor = subject->clone(subject);
777
0
        continue;
778
0
      case BUILD_END:
779
0
        break;
780
0
      default:
781
0
        goto error;
782
0
    }
783
0
    break;
784
0
  }
785
786
0
  if (this->cacert)
787
0
  {
788
0
    chunk_t  issuerNameHash, issuerKeyHash;
789
0
    enumerator_t *enumerator;
790
0
    identification_t *issuer;
791
0
    public_key_t *public;
792
0
    req_cert_t *reqCert;
793
0
    hasher_t *hasher;
794
795
0
    public = this->cacert->get_public_key(this->cacert);
796
0
    if (!public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &issuerKeyHash))
797
0
    {
798
0
      DBG1(DBG_LIB, "failed to compute SHA1 issuerKeyHash");
799
0
      public->destroy(public);
800
0
      goto error;
801
0
    }
802
0
    public->destroy(public);
803
804
0
    hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
805
0
    if (!hasher)
806
0
    {
807
0
      DBG1(DBG_LIB, "failed to create SHA1 hasher");
808
0
      goto error;
809
0
    }
810
811
0
    issuer = this->cacert->get_subject(this->cacert);
812
0
    if (!hasher->allocate_hash(hasher, issuer->get_encoding(issuer),
813
0
                      &issuerNameHash))
814
0
    {
815
0
      DBG1(DBG_LIB, "failed to compute SHA1 issuerNameHash");
816
0
      hasher->destroy(hasher);
817
0
      goto error;
818
0
    }
819
0
    hasher->destroy(hasher);
820
821
0
    enumerator = this->reqCerts->create_enumerator(this->reqCerts);
822
0
    while (enumerator->enumerate(enumerator, &reqCert))
823
0
    {
824
0
      reqCert->hashAlgorithm  = HASH_SHA1;
825
0
      reqCert->issuerNameHash = chunk_clone(issuerNameHash);
826
0
      reqCert->issuerKeyHash  = chunk_clone(issuerKeyHash);
827
0
    }
828
0
    enumerator->destroy(enumerator);
829
0
    chunk_free(&issuerNameHash);
830
831
0
    this->encoding = build_OCSPRequest(this);
832
833
0
    return &this->public;
834
0
  }
835
836
0
error:
837
0
  destroy(this);
838
0
  return NULL;
839
0
}
840
841
/**
842
 * load an OCSP request
843
 */
844
static x509_ocsp_request_t *load(chunk_t blob)
845
0
{
846
0
  private_x509_ocsp_request_t *this;
847
848
0
  this = create_empty();
849
0
  this->encoding = chunk_clone(blob);
850
851
0
  if (!parse_OCSPRequest(this))
852
0
  {
853
0
    destroy(this);
854
0
    return NULL;
855
0
  }
856
0
  return &this->public;
857
0
}
858
859
/**
860
 * See header.
861
 */
862
x509_ocsp_request_t *x509_ocsp_request_load(certificate_type_t type, va_list args)
863
0
{
864
0
  chunk_t blob = chunk_empty;
865
866
0
  while (TRUE)
867
0
  {
868
0
    switch (va_arg(args, builder_part_t))
869
0
    {
870
0
      case BUILD_BLOB_ASN1_DER:
871
0
        blob = va_arg(args, chunk_t);
872
0
        continue;
873
0
      case BUILD_END:
874
0
        break;
875
0
      default:
876
0
        return NULL;
877
0
    }
878
0
    break;
879
0
  }
880
0
  if (blob.ptr)
881
0
  {
882
0
    return load(blob);
883
0
  }
884
0
  return NULL;
885
0
}