1
#include "source/common/tls/ocsp/ocsp.h"
2

            
3
#include "source/common/common/utility.h"
4
#include "source/common/tls/ocsp/asn1_utility.h"
5
#include "source/common/tls/utility.h"
6

            
7
namespace Envoy {
8
namespace Extensions {
9
namespace TransportSockets {
10
namespace Tls {
11
namespace Ocsp {
12

            
13
namespace CertUtility = Envoy::Extensions::TransportSockets::Tls::Utility;
14

            
15
namespace {
16

            
17
1
int attemptParseTagForErrorMessage(CBS& cbs) {
18
1
  unsigned tag = 0;
19
1
  if (!CBS_get_any_asn1_element(&cbs, nullptr, &tag, nullptr)) {
20
    return -1;
21
  }
22
1
  return tag;
23
1
}
24

            
25
absl::StatusOr<std::unique_ptr<OcspResponse>>
26
1196
readDerEncodedOcspResponse(const std::vector<uint8_t>& der) {
27
1196
  CBS cbs;
28
1196
  CBS_init(&cbs, der.data(), der.size());
29

            
30
1196
  auto resp = Asn1OcspUtility::parseOcspResponse(cbs);
31
1196
  if (CBS_len(&cbs) != 0) {
32
1
    return absl::InvalidArgumentError("Data contained more than a single OCSP response");
33
1
  }
34

            
35
1195
  return resp;
36
1196
}
37

            
38
1193
absl::Status skipResponderId(CBS& cbs) {
39
  // ResponderID ::= CHOICE {
40
  //    byName               [1] Name,
41
  //    byKey                [2] KeyHash
42
  // }
43
  //
44
  // KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
45
  //    (excluding the tag and length fields)
46

            
47
1193
  auto opt1 = Asn1Utility::getOptional(cbs, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1);
48
1193
  RETURN_IF_NOT_OK_REF(opt1.status());
49
1193
  auto opt2 = Asn1Utility::getOptional(cbs, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2);
50
1193
  RETURN_IF_NOT_OK_REF(opt2.status());
51

            
52
1193
  if (opt1.value() || opt2.value()) {
53
1192
    return absl::OkStatus();
54
1192
  }
55

            
56
1
  return absl::InvalidArgumentError(
57
1
      absl::StrCat("Unknown choice for Responder ID: ", attemptParseTagForErrorMessage(cbs)));
58
1193
}
59

            
60
1193
absl::Status skipCertStatus(CBS& cbs) {
61
  // CertStatus ::= CHOICE {
62
  //  good                [0] IMPLICIT NULL,
63
  //  revoked             [1] IMPLICIT RevokedInfo,
64
  //  unknown             [2] IMPLICIT UnknownInfo
65
  // }
66
1193
  auto opt1 = Asn1Utility::getOptional(cbs, CBS_ASN1_CONTEXT_SPECIFIC | 0);
67
1193
  RETURN_IF_NOT_OK_REF(opt1.status());
68
1193
  auto opt2 = Asn1Utility::getOptional(cbs, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1);
69
1193
  RETURN_IF_NOT_OK_REF(opt2.status());
70
1193
  auto opt3 = Asn1Utility::getOptional(cbs, CBS_ASN1_CONTEXT_SPECIFIC | 2);
71
1193
  RETURN_IF_NOT_OK_REF(opt3.status());
72

            
73
1193
  if (!(opt1.value() || opt2.value() || opt3.value())) {
74
    return absl::InvalidArgumentError(
75
        absl::StrCat("Unknown OcspCertStatus tag: ", attemptParseTagForErrorMessage(cbs)));
76
  }
77
1193
  return absl::OkStatus();
78
1193
}
79

            
80
} // namespace
81

            
82
OcspResponse::OcspResponse(OcspResponseStatus status, ResponsePtr response)
83
1196
    : status_(status), response_(std::move(response)) {}
84

            
85
1192
BasicOcspResponse::BasicOcspResponse(ResponseData data) : data_(data) {}
86

            
87
ResponseData::ResponseData(std::vector<SingleResponse> single_responses)
88
1192
    : single_responses_(std::move(single_responses)) {}
89

            
90
SingleResponse::SingleResponse(CertId cert_id, Envoy::SystemTime this_update,
91
                               absl::optional<Envoy::SystemTime> next_update)
92
1193
    : cert_id_(cert_id), this_update_(this_update), next_update_(next_update) {}
93

            
94
1193
CertId::CertId(std::string serial_number) : serial_number_(serial_number) {}
95

            
96
1194
absl::Status validateResponse(std::unique_ptr<OcspResponse>& response) {
97
1194
  if (response->status_ != OcspResponseStatus::Successful) {
98
2
    return absl::InvalidArgumentError("OCSP response was unsuccessful");
99
2
  }
100

            
101
1192
  if (response->response_ == nullptr) {
102
1
    return absl::InvalidArgumentError("OCSP response has no body");
103
1
  }
104

            
105
  // We only permit a 1:1 of certificate to response.
106
1191
  if (response->response_->getNumCerts() != 1) {
107
1
    return absl::InvalidArgumentError("OCSP Response must be for one certificate only");
108
1
  }
109
1190
  return absl::OkStatus();
110
1191
}
111

            
112
absl::StatusOr<std::unique_ptr<OcspResponseWrapperImpl>>
113
1196
OcspResponseWrapperImpl::create(std::vector<uint8_t> der_response, TimeSource& time_source) {
114
1196
  auto response_or_error = readDerEncodedOcspResponse(der_response);
115
1196
  RETURN_IF_NOT_OK(response_or_error.status());
116
1194
  RETURN_IF_NOT_OK(validateResponse(response_or_error.value()));
117
1190
  return std::make_unique<OcspResponseWrapperImpl>(der_response, time_source,
118
1190
                                                   std::move(response_or_error.value()));
119
1194
}
120

            
121
OcspResponseWrapperImpl::OcspResponseWrapperImpl(std::vector<uint8_t> der_response,
122
                                                 TimeSource& time_source,
123
                                                 std::unique_ptr<OcspResponse>&& response)
124
1190
    : raw_bytes_(std::move(der_response)), response_(std::move(response)),
125
1190
      time_source_(time_source) {
126
1190
  auto& this_update = response_->response_->getThisUpdate();
127
1190
  if (time_source_.systemTime() < this_update) {
128
1
    std::string time_format(GENERALIZED_TIME_FORMAT);
129
1
    DateFormatter formatter(time_format);
130
1
    ENVOY_LOG_MISC(warn, "OCSP Response thisUpdate field is set in the future: {}",
131
1
                   formatter.fromTime(this_update));
132
1
  }
133
1190
}
134

            
135
// We use just the serial number to uniquely identify a certificate.
136
// Though different issuers could produce certificates with the same serial
137
// number, this is check is to prevent operator error and a collision in this
138
// case is unlikely.
139
1189
bool OcspResponseWrapperImpl::matchesCertificate(X509& cert) const {
140
1189
  std::string cert_serial_number = CertUtility::getSerialNumberFromCertificate(cert);
141
1189
  std::string resp_cert_serial_number = response_->response_->getCertSerialNumber();
142
1189
  return resp_cert_serial_number == cert_serial_number;
143
1189
}
144

            
145
19
bool OcspResponseWrapperImpl::isExpired() {
146
19
  auto& next_update = response_->response_->getNextUpdate();
147
19
  return next_update == absl::nullopt || next_update < time_source_.systemTime();
148
19
}
149

            
150
2404
uint64_t OcspResponseWrapperImpl::secondsUntilExpiration() const {
151
2404
  auto& next_update = response_->response_->getNextUpdate();
152
2404
  auto now = time_source_.systemTime();
153
2404
  if (!next_update || next_update.value() <= now) {
154
2
    return 0;
155
2
  }
156
2402
  return std::chrono::duration_cast<std::chrono::seconds>(next_update.value() - now).count();
157
2404
}
158

            
159
1
Envoy::SystemTime OcspResponseWrapperImpl::getThisUpdate() const {
160
1
  return response_->response_->getThisUpdate();
161
1
}
162

            
163
1
Envoy::SystemTime OcspResponseWrapperImpl::getNextUpdate() const {
164
1
  auto& next_update = response_->response_->getNextUpdate();
165
1
  if (next_update) {
166
1
    return *next_update;
167
1
  }
168

            
169
  return time_source_.systemTime();
170
1
}
171

            
172
1197
absl::StatusOr<std::unique_ptr<OcspResponse>> Asn1OcspUtility::parseOcspResponse(CBS& cbs) {
173
  // OCSPResponse ::= SEQUENCE {
174
  //    responseStatus         OCSPResponseStatus,
175
  //    responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL
176
  // }
177

            
178
1197
  CBS elem;
179
1197
  if (!CBS_get_asn1(&cbs, &elem, CBS_ASN1_SEQUENCE)) {
180
1
    return absl::InvalidArgumentError("OCSP Response is not a well-formed ASN.1 SEQUENCE");
181
1
  }
182

            
183
1196
  auto status_or_error = Asn1OcspUtility::parseResponseStatus(elem);
184
1196
  RETURN_IF_NOT_OK_REF(status_or_error.status());
185
1196
  auto opt = Asn1Utility::getOptional(elem, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0);
186
1196
  RETURN_IF_NOT_OK_REF(opt.status());
187
1196
  auto maybe_bytes = std::move(opt.value());
188
1196
  ResponsePtr resp = nullptr;
189
1196
  if (maybe_bytes) {
190
1192
    auto resp_or_error = Asn1OcspUtility::parseResponseBytes(maybe_bytes.value());
191
1192
    RETURN_IF_NOT_OK_REF(resp_or_error.status());
192
1192
    resp = std::move(resp_or_error.value());
193
1192
  }
194

            
195
1196
  return std::make_unique<OcspResponse>(status_or_error.value(), std::move(resp));
196
1196
}
197

            
198
1204
absl::StatusOr<OcspResponseStatus> Asn1OcspUtility::parseResponseStatus(CBS& cbs) {
199
  // OCSPResponseStatus ::= ENUMERATED {
200
  //    successful            (0),  -- Response has valid confirmations
201
  //    malformedRequest      (1),  -- Illegal confirmation request
202
  //    internalError         (2),  -- Internal error in issuer
203
  //    tryLater              (3),  -- Try again later
204
  //                                -- (4) is not used
205
  //    sigRequired           (5),  -- Must sign the request
206
  //    unauthorized          (6)   -- Request unauthorized
207
  // }
208
1204
  CBS status;
209
1204
  if (!CBS_get_asn1(&cbs, &status, CBS_ASN1_ENUMERATED)) {
210
1
    return absl::InvalidArgumentError("OCSP ResponseStatus is not a well-formed ASN.1 ENUMERATED");
211
1
  }
212

            
213
1203
  auto status_ordinal = *CBS_data(&status);
214
1203
  switch (status_ordinal) {
215
1194
  case 0:
216
1194
    return OcspResponseStatus::Successful;
217
1
  case 1:
218
1
    return OcspResponseStatus::MalformedRequest;
219
4
  case 2:
220
4
    return OcspResponseStatus::InternalError;
221
1
  case 3:
222
1
    return OcspResponseStatus::TryLater;
223
1
  case 5:
224
1
    return OcspResponseStatus::SigRequired;
225
1
  case 6:
226
1
    return OcspResponseStatus::Unauthorized;
227
1
  default:
228
1
    return absl::InvalidArgumentError(
229
1
        absl::StrCat("Unknown OCSP Response Status variant: ", status_ordinal));
230
1203
  }
231
1203
}
232

            
233
1195
absl::StatusOr<ResponsePtr> Asn1OcspUtility::parseResponseBytes(CBS& cbs) {
234
  // ResponseBytes ::=  SEQUENCE {
235
  //     responseType        RESPONSE.
236
  //                             &id ({ResponseSet}),
237
  //     response            OCTET STRING (CONTAINING RESPONSE.
238
  //                             &Type({ResponseSet}{@responseType}))
239
  // }
240
1195
  CBS elem, response;
241
1195
  if (!CBS_get_asn1(&cbs, &elem, CBS_ASN1_SEQUENCE)) {
242
1
    return absl::InvalidArgumentError("OCSP ResponseBytes is not a well-formed SEQUENCE");
243
1
  }
244

            
245
1194
  auto parse_or_error = Asn1Utility::parseOid(elem);
246
1194
  RETURN_IF_NOT_OK_REF(parse_or_error.status());
247
1194
  auto oid_str = std::move(parse_or_error.value());
248
1194
  if (!CBS_get_asn1(&elem, &response, CBS_ASN1_OCTETSTRING)) {
249
1
    return absl::InvalidArgumentError("Expected ASN.1 OCTETSTRING for response");
250
1
  }
251

            
252
1193
  if (oid_str == BasicOcspResponse::OID) {
253
1192
    return Asn1OcspUtility::parseBasicOcspResponse(response);
254
1192
  }
255
1
  return absl::InvalidArgumentError(absl::StrCat("Unknown OCSP Response type with OID: ", oid_str));
256
1193
}
257

            
258
absl::StatusOr<std::unique_ptr<BasicOcspResponse>>
259
1193
Asn1OcspUtility::parseBasicOcspResponse(CBS& cbs) {
260
  // BasicOCSPResponse       ::= SEQUENCE {
261
  //    tbsResponseData      ResponseData,
262
  //    signatureAlgorithm   AlgorithmIdentifier{SIGNATURE-ALGORITHM,
263
  //                             {`sa-dsaWithSHA1` | `sa-rsaWithSHA1` |
264
  //                                  `sa-rsaWithMD5` | `sa-rsaWithMD2`, ...}},
265
  //    signature            BIT STRING,
266
  //    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
267
  // }
268
1193
  CBS elem;
269
1193
  if (!CBS_get_asn1(&cbs, &elem, CBS_ASN1_SEQUENCE)) {
270
1
    return absl::InvalidArgumentError(
271
1
        "OCSP BasicOCSPResponse is not a wellf-formed ASN.1 SEQUENCE");
272
1
  }
273
1192
  auto response_or_error = Asn1OcspUtility::parseResponseData(elem);
274
1192
  RETURN_IF_NOT_OK_REF(response_or_error.status());
275
  // The `signatureAlgorithm` and `signature` are ignored because OCSP
276
  // responses are expected to be delivered from a reliable source.
277
  // Optional additional certs are ignored.
278

            
279
1192
  return std::make_unique<BasicOcspResponse>(response_or_error.value());
280
1192
}
281

            
282
1195
absl::StatusOr<ResponseData> Asn1OcspUtility::parseResponseData(CBS& cbs) {
283
  // ResponseData ::= SEQUENCE {
284
  //    version              [0] EXPLICIT Version DEFAULT v1,
285
  //    responderID              ResponderID,
286
  //    producedAt               GeneralizedTime,
287
  //    responses                SEQUENCE OF SingleResponse,
288
  //    responseExtensions   [1] EXPLICIT Extensions OPTIONAL
289
  // }
290
1195
  CBS elem;
291
1195
  if (!CBS_get_asn1(&cbs, &elem, CBS_ASN1_SEQUENCE)) {
292
1
    return absl::InvalidArgumentError("OCSP ResponseData is not a well-formed ASN.1 SEQUENCE");
293
1
  }
294

            
295
  // only support v1, the value of v1 is 0x00
296
1194
  auto version_or_error =
297
1194
      Asn1Utility::getOptional(elem, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0);
298
1194
  RETURN_IF_NOT_OK_REF(version_or_error.status());
299
1194
  auto version_cbs = std::move(version_or_error.value());
300
1194
  if (version_cbs.has_value()) {
301
1
    auto version_or_error = Asn1Utility::parseInteger(*version_cbs);
302
1
    RETURN_IF_NOT_OK_REF(version_or_error.status());
303
1
    auto version = std::move(version_or_error.value());
304
1
    if (version != "00") {
305
1
      return absl::InvalidArgumentError(
306
1
          fmt::format("OCSP ResponseData version 0x{} is not supported", version));
307
1
    }
308
1
  }
309

            
310
1193
  auto status = skipResponderId(elem);
311
1193
  RETURN_IF_NOT_OK(status);
312
1192
  RETURN_IF_NOT_OK_REF(Asn1Utility::skip(elem, CBS_ASN1_GENERALIZEDTIME).status());
313
1192
  auto responses_or_error = Asn1Utility::parseSequenceOf<SingleResponse>(
314
1193
      elem, [](CBS& cbs) -> absl::StatusOr<SingleResponse> { return {parseSingleResponse(cbs)}; });
315
1192
  RETURN_IF_NOT_OK_REF(responses_or_error.status());
316
  // Extensions currently ignored.
317

            
318
1192
  return {std::move(responses_or_error.value())};
319
1192
}
320

            
321
1194
absl::StatusOr<SingleResponse> Asn1OcspUtility::parseSingleResponse(CBS& cbs) {
322
  // SingleResponse ::= SEQUENCE {
323
  //    certID                  CertID,
324
  //    certStatus              CertStatus,
325
  //    thisUpdate              GeneralizedTime,
326
  //    nextUpdate          [0] EXPLICIT GeneralizedTime OPTIONAL,
327
  //    singleExtensions    [1] EXPLICIT Extensions OPTIONAL
328
  // }
329
1194
  CBS elem;
330
1194
  if (!CBS_get_asn1(&cbs, &elem, CBS_ASN1_SEQUENCE)) {
331
1
    return absl::InvalidArgumentError("OCSP SingleResponse is not a well-formed ASN.1 SEQUENCE");
332
1
  }
333

            
334
1193
  auto id_or_error = Asn1OcspUtility::parseCertId(elem);
335
1193
  RETURN_IF_NOT_OK_REF(id_or_error.status());
336
1193
  RETURN_IF_NOT_OK(skipCertStatus(elem));
337
1193
  auto this_update_or_error = Asn1Utility::parseGeneralizedTime(elem);
338
1193
  RETURN_IF_NOT_OK_REF(this_update_or_error.status());
339
1193
  auto next_update_or_error = Asn1Utility::parseOptional<Envoy::SystemTime>(
340
1193
      elem, Asn1Utility::parseGeneralizedTime,
341
1193
      CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0);
342
1193
  RETURN_IF_NOT_OK_REF(next_update_or_error.status());
343
  // Extensions currently ignored.
344

            
345
1193
  return SingleResponse{id_or_error.value(), this_update_or_error.value(),
346
1193
                        next_update_or_error.value()};
347
1193
}
348

            
349
1194
absl::StatusOr<CertId> Asn1OcspUtility::parseCertId(CBS& cbs) {
350
  // CertID ::= SEQUENCE {
351
  //    hashAlgorithm       AlgorithmIdentifier,
352
  //    issuerNameHash      OCTET STRING, -- Hash of issuer's `DN`
353
  //    issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
354
  //    serialNumber        CertificateSerialNumber
355
  // }
356
1194
  CBS elem;
357
1194
  if (!CBS_get_asn1(&cbs, &elem, CBS_ASN1_SEQUENCE)) {
358
1
    return absl::InvalidArgumentError("OCSP CertID is not a well-formed ASN.1 SEQUENCE");
359
1
  }
360

            
361
1193
  RETURN_IF_NOT_OK_REF(Asn1Utility::skip(elem, CBS_ASN1_SEQUENCE).status());
362
1193
  RETURN_IF_NOT_OK_REF(Asn1Utility::skip(elem, CBS_ASN1_OCTETSTRING).status());
363
1193
  RETURN_IF_NOT_OK_REF(Asn1Utility::skip(elem, CBS_ASN1_OCTETSTRING).status());
364
1193
  auto serial_number_or_error = Asn1Utility::parseInteger(elem);
365
1193
  RETURN_IF_NOT_OK_REF(serial_number_or_error.status());
366

            
367
1193
  return {serial_number_or_error.value()};
368
1193
}
369

            
370
} // namespace Ocsp
371
} // namespace Tls
372
} // namespace TransportSockets
373
} // namespace Extensions
374
} // namespace Envoy