iPXE
ocsp.c File Reference

Online Certificate Status Protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ipxe/asn1.h>
#include <ipxe/x509.h>
#include <ipxe/sha1.h>
#include <ipxe/base64.h>
#include <ipxe/uri.h>
#include <ipxe/ocsp.h>
#include <config/crypto.h>

Go to the source code of this file.

Macros

#define EACCES_CERT_STATUS   __einfo_error ( EINFO_EACCES_CERT_STATUS )
#define EINFO_EACCES_CERT_STATUS
#define EACCES_CERT_MISMATCH   __einfo_error ( EINFO_EACCES_CERT_MISMATCH )
#define EINFO_EACCES_CERT_MISMATCH
#define EACCES_NON_OCSP_SIGNING   __einfo_error ( EINFO_EACCES_NON_OCSP_SIGNING )
#define EINFO_EACCES_NON_OCSP_SIGNING
#define EACCES_STALE   __einfo_error ( EINFO_EACCES_STALE )
#define EINFO_EACCES_STALE
#define EACCES_NO_RESPONDER   __einfo_error ( EINFO_EACCES_NO_RESPONDER )
#define EINFO_EACCES_NO_RESPONDER
#define ENOTSUP_RESPONSE_TYPE   __einfo_error ( EINFO_ENOTSUP_RESPONSE_TYPE )
#define EINFO_ENOTSUP_RESPONSE_TYPE
#define ENOTSUP_RESPONDER_ID   __einfo_error ( EINFO_ENOTSUP_RESPONDER_ID )
#define EINFO_ENOTSUP_RESPONDER_ID
#define EPROTO_MALFORMED_REQUEST   __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST )
#define EINFO_EPROTO_MALFORMED_REQUEST
#define EPROTO_INTERNAL_ERROR   __einfo_error ( EINFO_EPROTO_INTERNAL_ERROR )
#define EINFO_EPROTO_INTERNAL_ERROR
#define EPROTO_TRY_LATER   __einfo_error ( EINFO_EPROTO_TRY_LATER )
#define EINFO_EPROTO_TRY_LATER
#define EPROTO_SIG_REQUIRED   __einfo_error ( EINFO_EPROTO_SIG_REQUIRED )
#define EINFO_EPROTO_SIG_REQUIRED
#define EPROTO_UNAUTHORIZED   __einfo_error ( EINFO_EPROTO_UNAUTHORIZED )
#define EINFO_EPROTO_UNAUTHORIZED
#define EPROTO_STATUS(status)
#define ocsp_digest_algorithm   sha1_algorithm
 OCSP digest algorithm.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FILE_SECBOOT (PERMITTED)
static void ocsp_free (struct refcnt *refcnt)
 Free OCSP check.
static int ocsp_request (struct ocsp_check *ocsp)
 Build OCSP request.
static int ocsp_uri_string (struct ocsp_check *ocsp)
 Build OCSP URI string.
int ocsp_check (struct x509_certificate *cert, struct x509_certificate *issuer, struct ocsp_check **ocsp)
 Create OCSP check.
static int ocsp_parse_response_status (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP response status.
static int ocsp_parse_response_type (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP response type.
static int ocsp_compare_responder_name (struct ocsp_check *ocsp, struct x509_certificate *cert)
 Compare responder's certificate name.
static int ocsp_compare_responder_key_hash (struct ocsp_check *ocsp, struct x509_certificate *cert)
 Compare responder's certificate public key hash.
static int ocsp_parse_responder_id (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP responder ID.
static int ocsp_parse_cert_id (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP certificate ID.
static int ocsp_parse_responses (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP responses.
static int ocsp_parse_tbs_response_data (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP response data.
static int ocsp_parse_certs (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP certificates.
static int ocsp_parse_basic_response (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP basic response.
static int ocsp_parse_response_bytes (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP response bytes.
static int ocsp_parse_response (struct ocsp_check *ocsp, const struct asn1_cursor *raw)
 Parse OCSP response.
int ocsp_response (struct ocsp_check *ocsp, const void *data, size_t len)
 Receive OCSP response.
static int ocsp_check_signature (struct ocsp_check *ocsp, struct x509_certificate *signer)
 Check OCSP response signature.
int ocsp_validate (struct ocsp_check *ocsp, time_t time)
 Validate OCSP response.

Variables

static const uint8_t ocsp_algorithm_id []
 OCSP digest algorithm identifier.
static const uint8_t oid_basic_response_type [] = { ASN1_OID_OCSP_BASIC }
 OCSP basic response type.
static struct asn1_cursor oid_basic_response_type_cursor
 OCSP basic response type cursor.

Detailed Description

Online Certificate Status Protocol.

Definition in file ocsp.c.

Macro Definition Documentation

◆ EACCES_CERT_STATUS

#define EACCES_CERT_STATUS   __einfo_error ( EINFO_EACCES_CERT_STATUS )

Definition at line 43 of file ocsp.c.

43#define EACCES_CERT_STATUS \
44 __einfo_error ( EINFO_EACCES_CERT_STATUS )

Referenced by ocsp_parse_responses().

◆ EINFO_EACCES_CERT_STATUS

#define EINFO_EACCES_CERT_STATUS
Value:
"Certificate status not good" )
#define __einfo_uniqify(einfo_base, uniq, desc)
Declare disambiguated error.
Definition errno.h:224
#define EINFO_EACCES
Definition errno.h:343

Definition at line 45 of file ocsp.c.

45#define EINFO_EACCES_CERT_STATUS \
46 __einfo_uniqify ( EINFO_EACCES, 0x01, \
47 "Certificate status not good" )

◆ EACCES_CERT_MISMATCH

#define EACCES_CERT_MISMATCH   __einfo_error ( EINFO_EACCES_CERT_MISMATCH )

Definition at line 48 of file ocsp.c.

48#define EACCES_CERT_MISMATCH \
49 __einfo_error ( EINFO_EACCES_CERT_MISMATCH )

Referenced by ocsp_parse_cert_id().

◆ EINFO_EACCES_CERT_MISMATCH

#define EINFO_EACCES_CERT_MISMATCH
Value:
"Certificate ID mismatch" )

Definition at line 50 of file ocsp.c.

50#define EINFO_EACCES_CERT_MISMATCH \
51 __einfo_uniqify ( EINFO_EACCES, 0x02, \
52 "Certificate ID mismatch" )

◆ EACCES_NON_OCSP_SIGNING

#define EACCES_NON_OCSP_SIGNING   __einfo_error ( EINFO_EACCES_NON_OCSP_SIGNING )

Definition at line 53 of file ocsp.c.

53#define EACCES_NON_OCSP_SIGNING \
54 __einfo_error ( EINFO_EACCES_NON_OCSP_SIGNING )

Referenced by ocsp_validate().

◆ EINFO_EACCES_NON_OCSP_SIGNING

#define EINFO_EACCES_NON_OCSP_SIGNING
Value:
"Not an OCSP signing certificate" )

Definition at line 55 of file ocsp.c.

55#define EINFO_EACCES_NON_OCSP_SIGNING \
56 __einfo_uniqify ( EINFO_EACCES, 0x03, \
57 "Not an OCSP signing certificate" )

◆ EACCES_STALE

#define EACCES_STALE   __einfo_error ( EINFO_EACCES_STALE )

Definition at line 58 of file ocsp.c.

58#define EACCES_STALE \
59 __einfo_error ( EINFO_EACCES_STALE )

Referenced by ocsp_validate().

◆ EINFO_EACCES_STALE

#define EINFO_EACCES_STALE
Value:
"Stale (or premature) OCSP repsonse" )

Definition at line 60 of file ocsp.c.

60#define EINFO_EACCES_STALE \
61 __einfo_uniqify ( EINFO_EACCES, 0x04, \
62 "Stale (or premature) OCSP repsonse" )

◆ EACCES_NO_RESPONDER

#define EACCES_NO_RESPONDER   __einfo_error ( EINFO_EACCES_NO_RESPONDER )

Definition at line 63 of file ocsp.c.

63#define EACCES_NO_RESPONDER \
64 __einfo_error ( EINFO_EACCES_NO_RESPONDER )

Referenced by ocsp_parse_certs().

◆ EINFO_EACCES_NO_RESPONDER

#define EINFO_EACCES_NO_RESPONDER
Value:
"Missing OCSP responder certificate" )

Definition at line 65 of file ocsp.c.

65#define EINFO_EACCES_NO_RESPONDER \
66 __einfo_uniqify ( EINFO_EACCES, 0x05, \
67 "Missing OCSP responder certificate" )

◆ ENOTSUP_RESPONSE_TYPE

#define ENOTSUP_RESPONSE_TYPE   __einfo_error ( EINFO_ENOTSUP_RESPONSE_TYPE )

Definition at line 68 of file ocsp.c.

68#define ENOTSUP_RESPONSE_TYPE \
69 __einfo_error ( EINFO_ENOTSUP_RESPONSE_TYPE )

Referenced by ocsp_parse_response_type().

◆ EINFO_ENOTSUP_RESPONSE_TYPE

#define EINFO_ENOTSUP_RESPONSE_TYPE
Value:
"Unsupported OCSP response type" )
#define EINFO_ENOTSUP
Definition errno.h:634

Definition at line 70 of file ocsp.c.

70#define EINFO_ENOTSUP_RESPONSE_TYPE \
71 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \
72 "Unsupported OCSP response type" )

◆ ENOTSUP_RESPONDER_ID

#define ENOTSUP_RESPONDER_ID   __einfo_error ( EINFO_ENOTSUP_RESPONDER_ID )

Definition at line 73 of file ocsp.c.

73#define ENOTSUP_RESPONDER_ID \
74 __einfo_error ( EINFO_ENOTSUP_RESPONDER_ID )

Referenced by ocsp_parse_responder_id().

◆ EINFO_ENOTSUP_RESPONDER_ID

#define EINFO_ENOTSUP_RESPONDER_ID
Value:
"Unsupported OCSP responder ID" )

Definition at line 75 of file ocsp.c.

75#define EINFO_ENOTSUP_RESPONDER_ID \
76 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \
77 "Unsupported OCSP responder ID" )

◆ EPROTO_MALFORMED_REQUEST

#define EPROTO_MALFORMED_REQUEST   __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST )

Definition at line 78 of file ocsp.c.

78#define EPROTO_MALFORMED_REQUEST \
79 __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST )

◆ EINFO_EPROTO_MALFORMED_REQUEST

#define EINFO_EPROTO_MALFORMED_REQUEST
Value:
"Illegal confirmation request" )
#define EINFO_EPROTO
Definition errno.h:669
#define OCSP_STATUS_MALFORMED_REQUEST
Definition ocsp.h:34

Definition at line 80 of file ocsp.c.

80#define EINFO_EPROTO_MALFORMED_REQUEST \
81 __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_MALFORMED_REQUEST, \
82 "Illegal confirmation request" )

◆ EPROTO_INTERNAL_ERROR

#define EPROTO_INTERNAL_ERROR   __einfo_error ( EINFO_EPROTO_INTERNAL_ERROR )

Definition at line 83 of file ocsp.c.

83#define EPROTO_INTERNAL_ERROR \
84 __einfo_error ( EINFO_EPROTO_INTERNAL_ERROR )

◆ EINFO_EPROTO_INTERNAL_ERROR

#define EINFO_EPROTO_INTERNAL_ERROR
Value:
"Internal error in issuer" )
#define OCSP_STATUS_INTERNAL_ERROR
Definition ocsp.h:35

Definition at line 85 of file ocsp.c.

85#define EINFO_EPROTO_INTERNAL_ERROR \
86 __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_INTERNAL_ERROR, \
87 "Internal error in issuer" )

◆ EPROTO_TRY_LATER

#define EPROTO_TRY_LATER   __einfo_error ( EINFO_EPROTO_TRY_LATER )

Definition at line 88 of file ocsp.c.

88#define EPROTO_TRY_LATER \
89 __einfo_error ( EINFO_EPROTO_TRY_LATER )

◆ EINFO_EPROTO_TRY_LATER

#define EINFO_EPROTO_TRY_LATER
Value:
"Try again later" )
#define OCSP_STATUS_TRY_LATER
Definition ocsp.h:36

Definition at line 90 of file ocsp.c.

90#define EINFO_EPROTO_TRY_LATER \
91 __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_TRY_LATER, \
92 "Try again later" )

◆ EPROTO_SIG_REQUIRED

#define EPROTO_SIG_REQUIRED   __einfo_error ( EINFO_EPROTO_SIG_REQUIRED )

Definition at line 93 of file ocsp.c.

93#define EPROTO_SIG_REQUIRED \
94 __einfo_error ( EINFO_EPROTO_SIG_REQUIRED )

◆ EINFO_EPROTO_SIG_REQUIRED

#define EINFO_EPROTO_SIG_REQUIRED
Value:
"Must sign the request" )
#define OCSP_STATUS_SIG_REQUIRED
Definition ocsp.h:37

Definition at line 95 of file ocsp.c.

95#define EINFO_EPROTO_SIG_REQUIRED \
96 __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_SIG_REQUIRED, \
97 "Must sign the request" )

◆ EPROTO_UNAUTHORIZED

#define EPROTO_UNAUTHORIZED   __einfo_error ( EINFO_EPROTO_UNAUTHORIZED )

Definition at line 98 of file ocsp.c.

98#define EPROTO_UNAUTHORIZED \
99 __einfo_error ( EINFO_EPROTO_UNAUTHORIZED )

◆ EINFO_EPROTO_UNAUTHORIZED

#define EINFO_EPROTO_UNAUTHORIZED
Value:
"Request unauthorized" )
#define OCSP_STATUS_UNAUTHORIZED
Definition ocsp.h:38

Definition at line 100 of file ocsp.c.

100#define EINFO_EPROTO_UNAUTHORIZED \
101 __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_UNAUTHORIZED, \
102 "Request unauthorized" )

◆ EPROTO_STATUS

#define EPROTO_STATUS ( status)
Value:
uint8_t status
Status.
Definition ena.h:5
#define EUNIQ(einfo_base, uniq,...)
Disambiguate a base error based on non-constant information.
Definition errno.h:269
#define EPROTO_TRY_LATER
Definition ocsp.c:88
#define EPROTO_SIG_REQUIRED
Definition ocsp.c:93
#define EPROTO_UNAUTHORIZED
Definition ocsp.c:98
#define EPROTO_MALFORMED_REQUEST
Definition ocsp.c:78
#define EPROTO_INTERNAL_ERROR
Definition ocsp.c:83

Definition at line 103 of file ocsp.c.

103#define EPROTO_STATUS( status ) \
104 EUNIQ ( EINFO_EPROTO, (status), EPROTO_MALFORMED_REQUEST, \
105 EPROTO_INTERNAL_ERROR, EPROTO_TRY_LATER, \
106 EPROTO_SIG_REQUIRED, EPROTO_UNAUTHORIZED )

Referenced by ocsp_parse_response_status().

◆ ocsp_digest_algorithm

#define ocsp_digest_algorithm   sha1_algorithm

OCSP digest algorithm.

Definition at line 109 of file ocsp.c.

Referenced by ocsp_request().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ ocsp_free()

void ocsp_free ( struct refcnt * refcnt)
static

Free OCSP check.

Parameters
refcntReference count

Definition at line 127 of file ocsp.c.

127 {
128 struct ocsp_check *ocsp =
130
131 x509_put ( ocsp->cert );
132 x509_put ( ocsp->issuer );
133 free ( ocsp->uri_string );
134 free ( ocsp->request.builder.data );
135 free ( ocsp->response.data );
136 x509_put ( ocsp->response.signer );
137 free ( ocsp );
138}
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
void * data
Data.
Definition asn1.h:36
An OCSP check.
Definition ocsp.h:86
char * uri_string
URI string.
Definition ocsp.h:94
struct ocsp_response response
Response.
Definition ocsp.h:98
struct ocsp_request request
Request.
Definition ocsp.h:96
struct x509_certificate * issuer
Issuing certificate.
Definition ocsp.h:92
struct x509_certificate * cert
Certificate being checked.
Definition ocsp.h:90
struct asn1_builder builder
Request builder.
Definition ocsp.h:45
struct x509_certificate * signer
Signing certificate.
Definition ocsp.h:82
void * data
Raw response.
Definition ocsp.h:68
A reference counter.
Definition refcnt.h:27
static void x509_put(struct x509_certificate *cert)
Drop reference to X.509 certificate.
Definition x509.h:278

References ocsp_request::builder, ocsp_check::cert, container_of, asn1_builder::data, ocsp_response::data, free, ocsp_check::issuer, ocsp_check::request, ocsp_check::response, ocsp_response::signer, ocsp_check::uri_string, and x509_put().

Referenced by ocsp_check().

◆ ocsp_request()

int ocsp_request ( struct ocsp_check * ocsp)
static

Build OCSP request.

Parameters
ocspOCSP check
Return values
rcReturn status code

Definition at line 146 of file ocsp.c.

146 {
147 struct digest_algorithm *digest = &ocsp_digest_algorithm;
148 struct asn1_builder *builder = &ocsp->request.builder;
149 struct asn1_cursor *cert_id_tail = &ocsp->request.cert_id_tail;
150 uint8_t digest_ctx[digest->ctxsize];
151 uint8_t name_digest[digest->digestsize];
152 uint8_t pubkey_digest[digest->digestsize];
153 int rc;
154
155 /* Generate digests */
156 digest_init ( digest, digest_ctx );
157 digest_update ( digest, digest_ctx, ocsp->cert->issuer.raw.data,
158 ocsp->cert->issuer.raw.len );
159 digest_final ( digest, digest_ctx, name_digest );
160 digest_init ( digest, digest_ctx );
161 digest_update ( digest, digest_ctx,
164 digest_final ( digest, digest_ctx, pubkey_digest );
165
166 /* Construct request */
167 if ( ( rc = ( asn1_prepend_raw ( builder, ocsp->cert->serial.raw.data,
168 ocsp->cert->serial.raw.len ),
170 pubkey_digest, sizeof ( pubkey_digest ) ),
172 name_digest, sizeof ( name_digest ) ),
173 asn1_prepend ( builder, ASN1_SEQUENCE,
175 sizeof ( ocsp_algorithm_id ) ),
176 asn1_wrap ( builder, ASN1_SEQUENCE ),
177 asn1_wrap ( builder, ASN1_SEQUENCE ),
178 asn1_wrap ( builder, ASN1_SEQUENCE ),
179 asn1_wrap ( builder, ASN1_SEQUENCE ),
180 asn1_wrap ( builder, ASN1_SEQUENCE ) ) ) != 0 ) {
181 DBGC ( ocsp, "OCSP %p \"%s\" could not build request: %s\n",
182 ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
183 return rc;
184 }
185 DBGC2 ( ocsp, "OCSP %p \"%s\" request is:\n",
186 ocsp, x509_name ( ocsp->cert ) );
187 DBGC2_HDA ( ocsp, 0, builder->data, builder->len );
188
189 /* Parse certificate ID for comparison with response */
190 cert_id_tail->data = builder->data;
191 cert_id_tail->len = builder->len;
192 if ( ( rc = ( asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
193 asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
194 asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
195 asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
196 asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
197 asn1_skip ( cert_id_tail, ASN1_SEQUENCE ) ) ) != 0 ) {
198 DBGC ( ocsp, "OCSP %p \"%s\" could not locate certID: %s\n",
199 ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
200 return rc;
201 }
202
203 return 0;
204}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned char uint8_t
Definition stdint.h:10
int asn1_prepend(struct asn1_builder *builder, unsigned int type, const void *data, size_t len)
Prepend data to ASN.1 builder.
Definition asn1.c:1042
int asn1_prepend_raw(struct asn1_builder *builder, const void *data, size_t len)
Prepend raw data to ASN.1 builder.
Definition asn1.c:1019
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:241
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:303
int asn1_wrap(struct asn1_builder *builder, unsigned int type)
Wrap ASN.1 builder.
Definition asn1.c:1069
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:90
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition asn1.h:69
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:294
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:305
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:299
static const uint8_t ocsp_algorithm_id[]
OCSP digest algorithm identifier.
Definition ocsp.c:112
#define ocsp_digest_algorithm
OCSP digest algorithm.
Definition ocsp.c:109
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An ASN.1 object builder.
Definition asn1.h:29
size_t len
Length of data.
Definition asn1.h:38
An ASN.1 object cursor.
Definition asn1.h:21
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
size_t ctxsize
Context size.
Definition crypto.h:23
struct asn1_cursor cert_id_tail
Certificate ID (excluding hashAlgorithm).
Definition ocsp.h:47
struct x509_serial serial
Serial number.
Definition x509.h:235
struct x509_subject subject
Subject.
Definition x509.h:245
struct x509_issuer issuer
Issuer.
Definition x509.h:241
struct asn1_cursor raw
Raw issuer.
Definition x509.h:32
struct asn1_cursor value
Public key value.
Definition x509.h:56
struct asn1_cursor raw
Raw serial number.
Definition x509.h:26
struct x509_public_key public_key
Public key information.
Definition x509.h:66
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition x509.c:147

References asn1_enter(), ASN1_OCTET_STRING, asn1_prepend(), asn1_prepend_raw(), ASN1_SEQUENCE, asn1_skip(), asn1_wrap(), ocsp_request::builder, ocsp_check::cert, ocsp_request::cert_id_tail, digest_algorithm::ctxsize, asn1_builder::data, asn1_cursor::data, DBGC, DBGC2, DBGC2_HDA, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, ocsp_check::issuer, x509_certificate::issuer, asn1_builder::len, asn1_cursor::len, ocsp_algorithm_id, ocsp_digest_algorithm, x509_subject::public_key, x509_issuer::raw, x509_serial::raw, rc, ocsp_check::request, x509_certificate::serial, strerror(), x509_certificate::subject, x509_public_key::value, and x509_name().

◆ ocsp_uri_string()

int ocsp_uri_string ( struct ocsp_check * ocsp)
static

Build OCSP URI string.

Parameters
ocspOCSP check
Return values
rcReturn status code

Definition at line 212 of file ocsp.c.

212 {
213 struct x509_ocsp_responder *responder =
215 char *base64;
216 char *sep;
217 size_t base64_len;
218 size_t uri_len;
219 size_t check_len;
220 size_t len;
221 int rc;
222
223 /* Sanity check */
224 if ( ! responder->uri.len ) {
225 DBGC ( ocsp, "OCSP %p \"%s\" has no OCSP URI\n",
226 ocsp, x509_name ( ocsp->cert ) );
227 rc = -ENOTTY;
228 goto err_no_uri;
229 }
230
231 /* Calculate base64-encoded request length */
232 base64_len = base64_encoded_len ( ocsp->request.builder.len );
233
234 /* Allocate and construct the base64-encoded request */
235 base64 = malloc ( base64_len + 1 /* NUL */ );
236 if ( ! base64 ) {
237 rc = -ENOMEM;
238 goto err_alloc_base64;
239 }
240 check_len = base64_encode ( ocsp->request.builder.data,
241 ocsp->request.builder.len,
242 base64, ( base64_len + 1 /* NUL */ ) );
243 assert ( check_len == base64_len );
244
245 /* Calculate URI-encoded base64-encoded request length */
246 uri_len = uri_encode ( URI_PATH, base64, base64_len, NULL, 0 );
247
248 /* Allocate and construct the URI string */
249 len = ( responder->uri.len + 1 /* possible "/" */ + uri_len );
250 ocsp->uri_string = zalloc ( len + 1 /* NUL */ );
251 if ( ! ocsp->uri_string ) {
252 rc = -ENOMEM;
253 goto err_alloc_uri;
254 }
255 memcpy ( ocsp->uri_string, responder->uri.data, responder->uri.len );
256 sep = &ocsp->uri_string[ responder->uri.len - 1 ];
257 if ( *sep != '/' )
258 *(++sep) = '/';
259 check_len = uri_encode ( URI_PATH, base64, base64_len,
260 ( sep + 1 /* "/" */ ),
261 ( uri_len + 1 /* NUL */ ) );
262 assert ( check_len == uri_len );
263 DBGC2 ( ocsp, "OCSP %p \"%s\" URI is %s\n",
264 ocsp, x509_name ( ocsp->cert ), ocsp->uri_string );
265
266 /* Success */
267 rc = 0;
268
269 err_alloc_uri:
270 free ( base64 );
271 err_alloc_base64:
272 err_no_uri:
273 return rc;
274}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
size_t base64_encode(const void *raw, size_t raw_len, char *data, size_t len)
Base64-encode data.
Definition base64.c:52
static const char base64[64+1]
Definition base64.c:40
static size_t base64_encoded_len(size_t raw_len)
Calculate length of base64-encoded data.
Definition base64.h:22
ring len
Length.
Definition dwmac.h:226
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:677
struct x509_ocsp_responder ocsp
OCSP responder.
Definition x509.h:140
struct x509_extensions extensions
Extensions.
Definition x509.h:249
struct x509_authority_info_access auth_info
Authority information access.
Definition x509.h:165
X.509 certificate OCSP responder.
Definition x509.h:130
struct asn1_cursor uri
URI.
Definition x509.h:132
size_t uri_encode(unsigned int field, const void *raw, size_t raw_len, char *buf, ssize_t len)
Encode URI field.
Definition uri.c:201
@ URI_PATH
Definition uri.h:119

References assert, x509_extensions::auth_info, base64, base64_encode(), base64_encoded_len(), ocsp_request::builder, ocsp_check::cert, asn1_builder::data, asn1_cursor::data, DBGC, DBGC2, ENOMEM, ENOTTY, x509_certificate::extensions, free, asn1_builder::len, asn1_cursor::len, len, malloc(), memcpy(), NULL, x509_authority_info_access::ocsp, rc, ocsp_check::request, x509_ocsp_responder::uri, uri_encode(), URI_PATH, ocsp_check::uri_string, x509_name(), and zalloc().

Referenced by ocsp_check().

◆ ocsp_check()

int ocsp_check ( struct x509_certificate * cert,
struct x509_certificate * issuer,
struct ocsp_check ** ocsp )

Create OCSP check.

Parameters
certCertificate to check
issuerIssuing certificate
Return values
ocspOCSP check
rcReturn status code

Definition at line 284 of file ocsp.c.

286 {
287 int rc;
288
289 /* Sanity checks */
290 assert ( cert != NULL );
291 assert ( issuer != NULL );
292 assert ( issuer->root != NULL );
293
294 /* Allocate and initialise check */
295 *ocsp = zalloc ( sizeof ( **ocsp ) );
296 if ( ! *ocsp ) {
297 rc = -ENOMEM;
298 goto err_alloc;
299 }
300 ref_init ( &(*ocsp)->refcnt, ocsp_free );
301 (*ocsp)->cert = x509_get ( cert );
302 (*ocsp)->issuer = x509_get ( issuer );
303
304 /* Build request */
305 if ( ( rc = ocsp_request ( *ocsp ) ) != 0 )
306 goto err_request;
307
308 /* Build URI string */
309 if ( ( rc = ocsp_uri_string ( *ocsp ) ) != 0 )
310 goto err_uri_string;
311
312 return 0;
313
314 err_uri_string:
315 err_request:
316 ocsp_put ( *ocsp );
317 err_alloc:
318 *ocsp = NULL;
319 return rc;
320}
static void ocsp_free(struct refcnt *refcnt)
Free OCSP check.
Definition ocsp.c:127
static int ocsp_uri_string(struct ocsp_check *ocsp)
Build OCSP URI string.
Definition ocsp.c:212
static void ocsp_put(struct ocsp_check *ocsp)
Drop reference to OCSP check.
Definition ocsp.h:119
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
An OCSP request.
Definition ocsp.h:43
struct x509_root * root
Root against which certificate has been validated (if any).
Definition x509.h:226
static struct x509_certificate * x509_get(struct x509_certificate *cert)
Get reference to X.509 certificate.
Definition x509.h:267

References assert, ENOMEM, NULL, ocsp_free(), ocsp_put(), ocsp_uri_string(), rc, ref_init, x509_certificate::root, x509_get(), and zalloc().

◆ ocsp_parse_response_status()

int ocsp_parse_response_status ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP response status.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 329 of file ocsp.c.

330 {
331 struct asn1_cursor cursor;
333 int rc;
334
335 /* Enter responseStatus */
336 memcpy ( &cursor, raw, sizeof ( cursor ) );
337 if ( ( rc = asn1_enter ( &cursor, ASN1_ENUMERATED ) ) != 0 ) {
338 DBGC ( ocsp, "OCSP %p \"%s\" could not locate responseStatus: "
339 "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
340 return rc;
341 }
342
343 /* Extract response status */
344 if ( cursor.len != sizeof ( status ) ) {
345 DBGC ( ocsp, "OCSP %p \"%s\" invalid status:\n",
346 ocsp, x509_name ( ocsp->cert ) );
347 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
348 return -EINVAL;
349 }
350 memcpy ( &status, cursor.data, sizeof ( status ) );
351
352 /* Check response status */
354 DBGC ( ocsp, "OCSP %p \"%s\" response status %d\n",
355 ocsp, x509_name ( ocsp->cert ), status );
356 return EPROTO_STATUS ( status );
357 }
358
359 return 0;
360}
__be32 raw[7]
Definition CIB_PRM.h:0
#define ASN1_ENUMERATED
ASN.1 enumeration.
Definition asn1.h:78
#define DBGC_HDA(...)
Definition compiler.h:531
#define EINVAL
Invalid argument.
Definition errno.h:472
#define EPROTO_STATUS(status)
Definition ocsp.c:103
#define OCSP_STATUS_SUCCESSFUL
Definition ocsp.h:33

References asn1_enter(), ASN1_ENUMERATED, ocsp_check::cert, asn1_cursor::data, DBGC, DBGC_HDA, EINVAL, EPROTO_STATUS, asn1_cursor::len, memcpy(), OCSP_STATUS_SUCCESSFUL, raw, rc, status, strerror(), and x509_name().

Referenced by ocsp_parse_response().

◆ ocsp_parse_response_type()

int ocsp_parse_response_type ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP response type.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 369 of file ocsp.c.

370 {
371 struct asn1_cursor cursor;
372
373 /* Enter responseType */
374 memcpy ( &cursor, raw, sizeof ( cursor ) );
375 asn1_enter ( &cursor, ASN1_OID );
376
377 /* Check responseType is "basic" */
378 if ( asn1_compare ( &oid_basic_response_type_cursor, &cursor ) != 0 ) {
379 DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n",
380 ocsp, x509_name ( ocsp->cert ) );
381 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
382 return -ENOTSUP_RESPONSE_TYPE;
383 }
384
385 return 0;
386}
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:528
#define ASN1_OID
ASN.1 object identifier.
Definition asn1.h:75
static struct asn1_cursor oid_basic_response_type_cursor
OCSP basic response type cursor.
Definition ocsp.c:119
#define ENOTSUP_RESPONSE_TYPE
Definition ocsp.c:68

References asn1_compare(), asn1_enter(), ASN1_OID, ocsp_check::cert, asn1_cursor::data, DBGC, DBGC_HDA, ENOTSUP_RESPONSE_TYPE, asn1_cursor::len, memcpy(), oid_basic_response_type_cursor, raw, and x509_name().

Referenced by ocsp_parse_response_bytes().

◆ ocsp_compare_responder_name()

int ocsp_compare_responder_name ( struct ocsp_check * ocsp,
struct x509_certificate * cert )
static

Compare responder's certificate name.

Parameters
ocspOCSP check
certCertificate
Return values
differenceDifference as returned by memcmp()

Definition at line 395 of file ocsp.c.

396 {
397 struct ocsp_responder *responder = &ocsp->response.responder;
398
399 /* Compare responder ID with certificate's subject */
400 return asn1_compare ( &responder->id, &cert->subject.raw );
401}
An OCSP responder.
Definition ocsp.h:51
struct asn1_cursor id
Responder ID.
Definition ocsp.h:62
struct ocsp_responder responder
Responder.
Definition ocsp.h:72
struct asn1_cursor raw
Raw subject.
Definition x509.h:62

References asn1_compare(), ocsp_responder::id, x509_subject::raw, ocsp_response::responder, ocsp_check::response, and x509_certificate::subject.

Referenced by ocsp_parse_responder_id().

◆ ocsp_compare_responder_key_hash()

int ocsp_compare_responder_key_hash ( struct ocsp_check * ocsp,
struct x509_certificate * cert )
static

Compare responder's certificate public key hash.

Parameters
ocspOCSP check
certCertificate
Return values
differenceDifference as returned by memcmp()

Definition at line 410 of file ocsp.c.

411 {
412 struct ocsp_responder *responder = &ocsp->response.responder;
413 struct asn1_cursor key_hash;
416 int difference;
417
418 /* Enter responder key hash */
419 memcpy ( &key_hash, &responder->id, sizeof ( key_hash ) );
420 asn1_enter ( &key_hash, ASN1_OCTET_STRING );
421
422 /* Sanity check */
423 difference = ( sizeof ( digest ) - key_hash.len );
424 if ( difference )
425 return difference;
426
427 /* Generate SHA1 hash of certificate's public key */
431 cert->subject.public_key.value.len );
432 digest_final ( &sha1_algorithm, ctx, digest );
433
434 /* Compare responder key hash with hash of certificate's public key */
435 return memcmp ( digest, key_hash.data, sizeof ( digest ) );
436}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
#define SHA1_DIGEST_SIZE
Definition Tpm20.h:25
struct digest_algorithm sha1_algorithm
#define SHA1_CTX_SIZE
SHA-1 context size.
Definition sha1.h:51
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115

References asn1_enter(), ASN1_OCTET_STRING, ctx, asn1_cursor::data, digest_final(), digest_init(), digest_update(), ocsp_responder::id, asn1_cursor::len, memcmp(), memcpy(), x509_subject::public_key, ocsp_response::responder, ocsp_check::response, sha1_algorithm, SHA1_CTX_SIZE, SHA1_DIGEST_SIZE, x509_certificate::subject, and x509_public_key::value.

Referenced by ocsp_parse_responder_id().

◆ ocsp_parse_responder_id()

int ocsp_parse_responder_id ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP responder ID.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 445 of file ocsp.c.

446 {
447 struct ocsp_responder *responder = &ocsp->response.responder;
448 struct asn1_cursor *responder_id = &responder->id;
449 unsigned int type;
450
451 /* Enter responder ID */
452 memcpy ( responder_id, raw, sizeof ( *responder_id ) );
453 type = asn1_type ( responder_id );
454 asn1_enter_any ( responder_id );
455
456 /* Identify responder ID type */
457 switch ( type ) {
458 case ASN1_EXPLICIT_TAG ( 1 ) :
459 DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by name\n",
460 ocsp, x509_name ( ocsp->cert ) );
462 return 0;
463 case ASN1_EXPLICIT_TAG ( 2 ) :
464 DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by key "
465 "hash\n", ocsp, x509_name ( ocsp->cert ) );
467 return 0;
468 default:
469 DBGC ( ocsp, "OCSP %p \"%s\" unsupported responder ID type "
470 "%d\n", ocsp, x509_name ( ocsp->cert ), type );
471 return -ENOTSUP_RESPONDER_ID;
472 }
473}
int asn1_enter_any(struct asn1_cursor *cursor)
Enter ASN.1 object of any type.
Definition asn1.c:352
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition asn1.h:99
static unsigned int asn1_type(const struct asn1_cursor *cursor)
Extract ASN.1 type.
Definition asn1.h:486
uint32_t type
Operating system type.
Definition ena.h:1
static int ocsp_compare_responder_key_hash(struct ocsp_check *ocsp, struct x509_certificate *cert)
Compare responder's certificate public key hash.
Definition ocsp.c:410
static int ocsp_compare_responder_name(struct ocsp_check *ocsp, struct x509_certificate *cert)
Compare responder's certificate name.
Definition ocsp.c:395
#define ENOTSUP_RESPONDER_ID
Definition ocsp.c:73
int(* compare)(struct ocsp_check *ocsp, struct x509_certificate *cert)
Check if certificate is the responder's certificate.
Definition ocsp.h:59

References asn1_enter_any(), ASN1_EXPLICIT_TAG, asn1_type(), ocsp_check::cert, ocsp_responder::compare, DBGC, DBGC2, ENOTSUP_RESPONDER_ID, ocsp_responder::id, memcpy(), ocsp_compare_responder_key_hash(), ocsp_compare_responder_name(), raw, ocsp_response::responder, ocsp_check::response, type, and x509_name().

Referenced by ocsp_parse_tbs_response_data().

◆ ocsp_parse_cert_id()

int ocsp_parse_cert_id ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP certificate ID.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 482 of file ocsp.c.

483 {
484 struct asn1_cursor algorithm = {
485 .data = ocsp_algorithm_id,
486 .len = sizeof ( ocsp_algorithm_id ),
487 };
488 struct asn1_cursor cert_id;
489 struct asn1_cursor cursor;
490 int rc;
491
492 /* Enter cert ID */
493 memcpy ( &cert_id, raw, sizeof ( cert_id ) );
494 asn1_enter ( &cert_id, ASN1_SEQUENCE );
495
496 /* Check certID algorithm (but not parameters) */
497 memcpy ( &cursor, &cert_id, sizeof ( cursor ) );
498 if ( ( rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ),
499 asn1_shrink ( &cursor, ASN1_OID ),
500 asn1_shrink ( &algorithm, ASN1_OID ) ) ) != 0 ) {
501 DBGC ( ocsp, "OCSP %p \"%s\" certID missing algorithm:\n",
502 ocsp, x509_name ( ocsp->cert ) );
503 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
504 return -EACCES_CERT_MISMATCH;
505 }
506 if ( asn1_compare ( &cursor, &algorithm ) != 0 ) {
507 DBGC ( ocsp, "OCSP %p \"%s\" certID wrong algorithm:\n",
508 ocsp, x509_name ( ocsp->cert ) );
509 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
510 return -EACCES_CERT_MISMATCH;
511 }
512
513 /* Check remaining certID fields */
514 asn1_skip ( &cert_id, ASN1_SEQUENCE );
515 if ( asn1_compare ( &cert_id, &ocsp->request.cert_id_tail ) != 0 ) {
516 DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n",
517 ocsp, x509_name ( ocsp->cert ) );
518 DBGC_HDA ( ocsp, 0, ocsp->request.cert_id_tail.data,
519 ocsp->request.cert_id_tail.len );
520 DBGC_HDA ( ocsp, 0, cert_id.data, cert_id.len );
521 return -EACCES_CERT_MISMATCH;
522 }
523
524 return 0;
525}
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition asn1.c:326
u16 algorithm
Authentication algorithm (Open System or Shared Key).
Definition ieee80211.h:1
#define EACCES_CERT_MISMATCH
Definition ocsp.c:48

References algorithm, asn1_compare(), asn1_enter(), ASN1_OID, ASN1_SEQUENCE, asn1_shrink(), asn1_skip(), ocsp_check::cert, ocsp_request::cert_id_tail, asn1_cursor::data, DBGC, DBGC_HDA, EACCES_CERT_MISMATCH, asn1_cursor::len, memcpy(), ocsp_algorithm_id, raw, rc, ocsp_check::request, and x509_name().

Referenced by ocsp_parse_responses().

◆ ocsp_parse_responses()

int ocsp_parse_responses ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP responses.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 534 of file ocsp.c.

535 {
536 struct ocsp_response *response = &ocsp->response;
537 struct asn1_cursor cursor;
538 int rc;
539
540 /* Enter responses */
541 memcpy ( &cursor, raw, sizeof ( cursor ) );
542 asn1_enter ( &cursor, ASN1_SEQUENCE );
543
544 /* Enter first singleResponse */
545 asn1_enter ( &cursor, ASN1_SEQUENCE );
546
547 /* Parse certID */
548 if ( ( rc = ocsp_parse_cert_id ( ocsp, &cursor ) ) != 0 )
549 return rc;
550 asn1_skip_any ( &cursor );
551
552 /* Check certStatus */
553 if ( asn1_type ( &cursor ) != ASN1_IMPLICIT_TAG ( 0 ) ) {
554 DBGC ( ocsp, "OCSP %p \"%s\" non-good certStatus:\n",
555 ocsp, x509_name ( ocsp->cert ) );
556 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
557 return -EACCES_CERT_STATUS;
558 }
559 asn1_skip_any ( &cursor );
560
561 /* Parse thisUpdate */
562 if ( ( rc = asn1_generalized_time ( &cursor,
563 &response->this_update ) ) != 0 ) {
564 DBGC ( ocsp, "OCSP %p \"%s\" could not parse thisUpdate: %s\n",
565 ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
566 return rc;
567 }
568 DBGC2 ( ocsp, "OCSP %p \"%s\" this update was at time %lld\n",
569 ocsp, x509_name ( ocsp->cert ), response->this_update );
570 asn1_skip_any ( &cursor );
571
572 /* Parse nextUpdate, if present */
573 if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
574 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
575 if ( ( rc = asn1_generalized_time ( &cursor,
576 &response->next_update ) ) != 0 ) {
577 DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
578 "nextUpdate: %s\n", ocsp,
579 x509_name ( ocsp->cert ), strerror ( rc ) );
580 return rc;
581 }
582 DBGC2 ( ocsp, "OCSP %p \"%s\" next update is at time %lld\n",
583 ocsp, x509_name ( ocsp->cert ), response->next_update );
584 } else {
585 /* If no nextUpdate is present, this indicates that
586 * "newer revocation information is available all the
587 * time". Actually, this indicates that there is no
588 * point to performing the OCSP check, since an
589 * attacker could replay the response at any future
590 * time and it would still be valid.
591 */
592 DBGC ( ocsp, "OCSP %p \"%s\" responder is a moron\n",
593 ocsp, x509_name ( ocsp->cert ) );
594 response->next_update = time ( NULL );
595 }
596
597 return 0;
598}
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:362
int asn1_generalized_time(const struct asn1_cursor *cursor, time_t *time)
Parse ASN.1 GeneralizedTime.
Definition asn1.c:847
#define ASN1_IMPLICIT_TAG(number)
ASN.1 implicit tag.
Definition asn1.h:96
#define EACCES_CERT_STATUS
Definition ocsp.c:43
static int ocsp_parse_cert_id(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP certificate ID.
Definition ocsp.c:482
An OCSP response.
Definition ocsp.h:66
time_t next_update
Time at which newer status information will be available.
Definition ocsp.h:76
time_t this_update
Time at which status is known to be correct.
Definition ocsp.h:74

References asn1_enter(), ASN1_EXPLICIT_TAG, asn1_generalized_time(), ASN1_IMPLICIT_TAG, ASN1_SEQUENCE, asn1_skip_any(), asn1_type(), ocsp_check::cert, asn1_cursor::data, DBGC, DBGC2, DBGC_HDA, EACCES_CERT_STATUS, asn1_cursor::len, memcpy(), ocsp_response::next_update, NULL, ocsp_parse_cert_id(), raw, rc, ocsp_check::response, strerror(), ocsp_response::this_update, and x509_name().

Referenced by ocsp_parse_tbs_response_data().

◆ ocsp_parse_tbs_response_data()

int ocsp_parse_tbs_response_data ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP response data.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 607 of file ocsp.c.

608 {
609 struct ocsp_response *response = &ocsp->response;
610 struct asn1_cursor cursor;
611 int rc;
612
613 /* Record raw tbsResponseData */
614 memcpy ( &cursor, raw, sizeof ( cursor ) );
615 asn1_shrink_any ( &cursor );
616 memcpy ( &response->tbs, &cursor, sizeof ( response->tbs ) );
617
618 /* Enter tbsResponseData */
619 asn1_enter ( &cursor, ASN1_SEQUENCE );
620
621 /* Skip version, if present */
622 asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
623
624 /* Parse responderID */
625 if ( ( rc = ocsp_parse_responder_id ( ocsp, &cursor ) ) != 0 )
626 return rc;
627 asn1_skip_any ( &cursor );
628
629 /* Skip producedAt */
630 asn1_skip_any ( &cursor );
631
632 /* Parse responses */
633 if ( ( rc = ocsp_parse_responses ( ocsp, &cursor ) ) != 0 )
634 return rc;
635
636 return 0;
637}
int asn1_shrink_any(struct asn1_cursor *cursor)
Shrink ASN.1 object of any type.
Definition asn1.c:372
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition asn1.c:274
static int ocsp_parse_responder_id(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP responder ID.
Definition ocsp.c:445
static int ocsp_parse_responses(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP responses.
Definition ocsp.c:534
struct asn1_cursor tbs
Raw tbsResponseData.
Definition ocsp.h:70

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_SEQUENCE, asn1_shrink_any(), asn1_skip_any(), asn1_skip_if_exists(), memcpy(), ocsp_parse_responder_id(), ocsp_parse_responses(), raw, rc, ocsp_check::response, and ocsp_response::tbs.

Referenced by ocsp_parse_basic_response().

◆ ocsp_parse_certs()

int ocsp_parse_certs ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP certificates.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 646 of file ocsp.c.

647 {
648 struct ocsp_response *response = &ocsp->response;
649 struct asn1_cursor cursor;
650 struct x509_certificate *cert;
651 int rc;
652
653 /* Enter certs */
654 memcpy ( &cursor, raw, sizeof ( cursor ) );
655 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
656 asn1_enter ( &cursor, ASN1_SEQUENCE );
657
658 /* Parse certificate, if present. The data structure permits
659 * multiple certificates, but the protocol requires that the
660 * OCSP signing certificate must either be the issuer itself,
661 * or must be directly issued by the issuer (see RFC2560
662 * section 4.2.2.2 "Authorized Responders"). We therefore
663 * need to identify only the single certificate matching the
664 * Responder ID.
665 */
666 while ( cursor.len ) {
667
668 /* Parse certificate */
669 if ( ( rc = x509_certificate ( cursor.data, cursor.len,
670 &cert ) ) != 0 ) {
671 DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
672 "certificate: %s\n", ocsp,
673 x509_name ( ocsp->cert ), strerror ( rc ) );
674 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
675 return rc;
676 }
677
678 /* Use if this certificate matches the responder ID */
679 if ( response->responder.compare ( ocsp, cert ) == 0 ) {
680 response->signer = cert;
681 DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by ",
682 ocsp, x509_name ( ocsp->cert ) );
683 DBGC2 ( ocsp, "\"%s\"\n",
684 x509_name ( response->signer ) );
685 return 0;
686 }
687
688 /* Otherwise, discard this certificate */
689 x509_put ( cert );
690 asn1_skip_any ( &cursor );
691 }
692
693 DBGC ( ocsp, "OCSP %p \"%s\" missing responder certificate\n",
694 ocsp, x509_name ( ocsp->cert ) );
695 return -EACCES_NO_RESPONDER;
696}
#define EACCES_NO_RESPONDER
Definition ocsp.c:63
An X.509 certificate.
Definition x509.h:216

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_SEQUENCE, asn1_skip_any(), ocsp_check::cert, ocsp_responder::compare, asn1_cursor::data, DBGC, DBGC2, DBGC_HDA, EACCES_NO_RESPONDER, asn1_cursor::len, memcpy(), raw, rc, ocsp_response::responder, ocsp_check::response, ocsp_response::signer, strerror(), x509_name(), and x509_put().

Referenced by ocsp_parse_basic_response().

◆ ocsp_parse_basic_response()

int ocsp_parse_basic_response ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP basic response.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 705 of file ocsp.c.

706 {
707 struct ocsp_response *response = &ocsp->response;
708 struct asn1_algorithm **algorithm = &response->algorithm;
709 struct asn1_cursor *signature = &response->signature;
710 struct asn1_cursor cursor;
711 int rc;
712
713 /* Enter BasicOCSPResponse */
714 memcpy ( &cursor, raw, sizeof ( cursor ) );
715 asn1_enter ( &cursor, ASN1_SEQUENCE );
716
717 /* Parse tbsResponseData */
718 if ( ( rc = ocsp_parse_tbs_response_data ( ocsp, &cursor ) ) != 0 )
719 return rc;
720 asn1_skip_any ( &cursor );
721
722 /* Parse signatureAlgorithm */
723 if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
724 DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature "
725 "algorithm: %s\n",
726 ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
727 return rc;
728 }
729 DBGC2 ( ocsp, "OCSP %p \"%s\" signature algorithm is %s\n",
730 ocsp, x509_name ( ocsp->cert ), (*algorithm)->name );
731 asn1_skip_any ( &cursor );
732
733 /* Parse signature */
734 memcpy ( signature, &cursor, sizeof ( *signature ) );
735 if ( ( rc = asn1_enter_bits ( signature, NULL ) ) != 0 ) {
736 DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature: %s\n",
737 ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
738 return rc;
739 }
740 asn1_skip_any ( &cursor );
741
742 /* Parse certs, if present */
743 if ( ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) &&
744 ( ( rc = ocsp_parse_certs ( ocsp, &cursor ) ) != 0 ) )
745 return rc;
746
747 return 0;
748}
u8 signature
CPU signature.
Definition CIB_PRM.h:7
int asn1_enter_bits(struct asn1_cursor *cursor, unsigned int *unused)
Enter ASN.1 bit string.
Definition asn1.c:383
int asn1_signature_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified signature algorithm.
Definition asn1.c:694
static int ocsp_parse_certs(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP certificates.
Definition ocsp.c:646
static int ocsp_parse_tbs_response_data(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP response data.
Definition ocsp.c:607
An ASN.1 OID-identified algorithm.
Definition asn1.h:414
struct asn1_algorithm * algorithm
Signature algorithm.
Definition ocsp.h:78
struct asn1_cursor signature
Signature value.
Definition ocsp.h:80

References algorithm, ocsp_response::algorithm, asn1_enter(), asn1_enter_bits(), ASN1_EXPLICIT_TAG, ASN1_SEQUENCE, asn1_signature_algorithm(), asn1_skip_any(), asn1_type(), ocsp_check::cert, DBGC, DBGC2, memcpy(), NULL, ocsp_parse_certs(), ocsp_parse_tbs_response_data(), raw, rc, ocsp_check::response, ocsp_response::signature, signature, strerror(), and x509_name().

Referenced by ocsp_parse_response_bytes().

◆ ocsp_parse_response_bytes()

int ocsp_parse_response_bytes ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP response bytes.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 757 of file ocsp.c.

758 {
759 struct asn1_cursor cursor;
760 int rc;
761
762 /* Enter responseBytes */
763 memcpy ( &cursor, raw, sizeof ( cursor ) );
764 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
765 asn1_enter ( &cursor, ASN1_SEQUENCE );
766
767 /* Parse responseType */
768 if ( ( rc = ocsp_parse_response_type ( ocsp, &cursor ) ) != 0 )
769 return rc;
770 asn1_skip_any ( &cursor );
771
772 /* Enter response */
773 asn1_enter ( &cursor, ASN1_OCTET_STRING );
774
775 /* Parse response */
776 if ( ( rc = ocsp_parse_basic_response ( ocsp, &cursor ) ) != 0 )
777 return rc;
778
779 return 0;
780}
static int ocsp_parse_basic_response(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP basic response.
Definition ocsp.c:705
static int ocsp_parse_response_type(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP response type.
Definition ocsp.c:369

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_OCTET_STRING, ASN1_SEQUENCE, asn1_skip_any(), memcpy(), ocsp_parse_basic_response(), ocsp_parse_response_type(), raw, and rc.

Referenced by ocsp_parse_response().

◆ ocsp_parse_response()

int ocsp_parse_response ( struct ocsp_check * ocsp,
const struct asn1_cursor * raw )
static

Parse OCSP response.

Parameters
ocspOCSP check
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 789 of file ocsp.c.

790 {
791 struct asn1_cursor cursor;
792 int rc;
793
794 /* Enter OCSPResponse */
795 memcpy ( &cursor, raw, sizeof ( cursor ) );
796 asn1_enter ( &cursor, ASN1_SEQUENCE );
797
798 /* Parse responseStatus */
799 if ( ( rc = ocsp_parse_response_status ( ocsp, &cursor ) ) != 0 )
800 return rc;
801 asn1_skip_any ( &cursor );
802
803 /* Parse responseBytes */
804 if ( ( rc = ocsp_parse_response_bytes ( ocsp, &cursor ) ) != 0 )
805 return rc;
806
807 return 0;
808}
static int ocsp_parse_response_status(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP response status.
Definition ocsp.c:329
static int ocsp_parse_response_bytes(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP response bytes.
Definition ocsp.c:757

References asn1_enter(), ASN1_SEQUENCE, asn1_skip_any(), memcpy(), ocsp_parse_response_bytes(), ocsp_parse_response_status(), raw, and rc.

Referenced by ocsp_response().

◆ ocsp_response()

int ocsp_response ( struct ocsp_check * ocsp,
const void * data,
size_t len )

Receive OCSP response.

Parameters
ocspOCSP check
dataResponse data
lenLength of response data
Return values
rcReturn status code

Definition at line 818 of file ocsp.c.

818 {
819 struct ocsp_response *response = &ocsp->response;
820 struct asn1_cursor cursor;
821 int rc;
822
823 /* Duplicate data */
824 x509_put ( response->signer );
825 response->signer = NULL;
826 free ( response->data );
827 response->data = malloc ( len );
828 if ( ! response->data )
829 return -ENOMEM;
830 memcpy ( response->data, data, len );
831 cursor.data = response->data;
832 cursor.len = len;
833
834 /* Parse response */
835 if ( ( rc = ocsp_parse_response ( ocsp, &cursor ) ) != 0 )
836 return rc;
837
838 return 0;
839}
uint8_t data[48]
Additional event data.
Definition ena.h:11
static int ocsp_parse_response(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP response.
Definition ocsp.c:789

References asn1_cursor::data, data, ocsp_response::data, ENOMEM, free, asn1_cursor::len, len, malloc(), memcpy(), NULL, ocsp_parse_response(), rc, ocsp_check::response, ocsp_response::signer, and x509_put().

◆ ocsp_check_signature()

int ocsp_check_signature ( struct ocsp_check * ocsp,
struct x509_certificate * signer )
static

Check OCSP response signature.

Parameters
ocspOCSP check
signerSigning certificate
Return values
rcReturn status code

Definition at line 848 of file ocsp.c.

849 {
850 struct ocsp_response *response = &ocsp->response;
851 struct digest_algorithm *digest = response->algorithm->digest;
852 struct pubkey_algorithm *pubkey = response->algorithm->pubkey;
853 struct asn1_cursor *key = &signer->subject.public_key.raw;
854 uint8_t digest_ctx[ digest->ctxsize ];
855 uint8_t digest_out[ digest->digestsize ];
856 int rc;
857
858 /* Generate digest */
859 digest_init ( digest, digest_ctx );
860 digest_update ( digest, digest_ctx, response->tbs.data,
861 response->tbs.len );
862 digest_final ( digest, digest_ctx, digest_out );
863
864 /* Verify digest */
865 if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
866 &response->signature ) ) != 0 ) {
867 DBGC ( ocsp, "OCSP %p \"%s\" signature verification failed: "
868 "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
869 return rc;
870 }
871
872 DBGC2 ( ocsp, "OCSP %p \"%s\" signature is correct\n",
873 ocsp, x509_name ( ocsp->cert ) );
874 return 0;
875}
union @162305117151260234136356364136041353210355154177 key
static int pubkey_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Definition crypto.h:383
struct digest_algorithm * digest
Digest algorithm (if applicable).
Definition asn1.h:422
struct pubkey_algorithm * pubkey
Public-key algorithm (if applicable).
Definition asn1.h:420
A public key algorithm.
Definition crypto.h:142
struct asn1_cursor raw
Raw public key information.
Definition x509.h:52

References ocsp_response::algorithm, ocsp_check::cert, digest_algorithm::ctxsize, asn1_cursor::data, DBGC, DBGC2, asn1_algorithm::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, key, asn1_cursor::len, asn1_algorithm::pubkey, pubkey_verify(), x509_subject::public_key, x509_public_key::raw, rc, ocsp_check::response, ocsp_response::signature, strerror(), x509_certificate::subject, ocsp_response::tbs, and x509_name().

Referenced by ocsp_validate().

◆ ocsp_validate()

int ocsp_validate ( struct ocsp_check * ocsp,
time_t time )

Validate OCSP response.

Parameters
ocspOCSP check
timeTime at which to validate response
Return values
rcReturn status code

Definition at line 884 of file ocsp.c.

884 {
885 struct ocsp_response *response = &ocsp->response;
886 struct x509_certificate *signer;
887 int rc;
888
889 /* Sanity checks */
890 assert ( response->data != NULL );
891
892 /* The response may include a signer certificate; if this is
893 * not present then the response must have been signed
894 * directly by the issuer.
895 */
896 signer = ( response->signer ? response->signer : ocsp->issuer );
897
898 /* Validate signer, if applicable. If the signer is not the
899 * issuer, then it must be signed directly by the issuer.
900 */
901 if ( signer != ocsp->issuer ) {
902 /* Forcibly invalidate the signer, since we need to
903 * ensure that it was signed by our issuer (and not
904 * some other issuer). This prevents a sub-CA's OCSP
905 * certificate from fraudulently signing OCSP
906 * responses from the parent CA.
907 */
908 x509_invalidate ( signer );
909 if ( ( rc = x509_validate ( signer, ocsp->issuer, time,
910 ocsp->issuer->root ) ) != 0 ) {
911 DBGC ( ocsp, "OCSP %p \"%s\" could not validate ",
912 ocsp, x509_name ( ocsp->cert ) );
913 DBGC ( ocsp, "signer \"%s\": %s\n",
914 x509_name ( signer ), strerror ( rc ) );
915 return rc;
916 }
917
918 /* If signer is not the issuer, then it must have the
919 * extendedKeyUsage id-kp-OCSPSigning.
920 */
921 if ( ! ( signer->extensions.ext_usage.bits &
923 DBGC ( ocsp, "OCSP %p \"%s\" ",
924 ocsp, x509_name ( ocsp->cert ) );
925 DBGC ( ocsp, "signer \"%s\" is not an OCSP-signing "
926 "certificate\n", x509_name ( signer ) );
928 }
929 }
930
931 /* Check OCSP response signature */
932 if ( ( rc = ocsp_check_signature ( ocsp, signer ) ) != 0 )
933 return rc;
934
935 /* Check OCSP response is valid at the specified time
936 * (allowing for some margin of error).
937 */
938 if ( response->this_update > ( time + TIMESTAMP_ERROR_MARGIN ) ) {
939 DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at "
940 "time %lld)\n", ocsp, x509_name ( ocsp->cert ), time );
941 return -EACCES_STALE;
942 }
943 if ( response->next_update < ( time - TIMESTAMP_ERROR_MARGIN ) ) {
944 DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time "
945 "%lld)\n", ocsp, x509_name ( ocsp->cert ), time );
946 return -EACCES_STALE;
947 }
948 DBGC2 ( ocsp, "OCSP %p \"%s\" response is valid (at time %lld)\n",
949 ocsp, x509_name ( ocsp->cert ), time );
950
951 /* Mark certificate as passing OCSP verification */
952 ocsp->cert->extensions.auth_info.ocsp.good = 1;
953
954 /* Validate certificate against issuer */
955 if ( ( rc = x509_validate ( ocsp->cert, ocsp->issuer, time,
956 ocsp->issuer->root ) ) != 0 ) {
957 DBGC ( ocsp, "OCSP %p \"%s\" could not validate certificate: "
958 "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
959 return rc;
960 }
961 DBGC ( ocsp, "OCSP %p \"%s\" successfully validated ",
962 ocsp, x509_name ( ocsp->cert ) );
963 DBGC ( ocsp, "using \"%s\"\n", x509_name ( signer ) );
964
965 return 0;
966}
#define TIMESTAMP_ERROR_MARGIN
Margin of error (in seconds) allowed in signed timestamps.
Definition crypto.h:100
static int ocsp_check_signature(struct ocsp_check *ocsp, struct x509_certificate *signer)
Check OCSP response signature.
Definition ocsp.c:848
#define EACCES_NON_OCSP_SIGNING
Definition ocsp.c:53
#define EACCES_STALE
Definition ocsp.c:58
unsigned int bits
Usage bits.
Definition x509.h:116
struct x509_extended_key_usage ext_usage
Extended key usage.
Definition x509.h:163
int good
OCSP status is good.
Definition x509.h:134
int x509_validate(struct x509_certificate *cert, struct x509_certificate *issuer, time_t time, struct x509_root *root)
Validate X.509 certificate.
Definition x509.c:1366
@ X509_OCSP_SIGNING
Definition x509.h:126
static void x509_invalidate(struct x509_certificate *cert)
Invalidate X.509 certificate.
Definition x509.h:473

References assert, x509_extensions::auth_info, x509_extended_key_usage::bits, ocsp_check::cert, ocsp_response::data, DBGC, DBGC2, EACCES_NON_OCSP_SIGNING, EACCES_STALE, x509_extensions::ext_usage, x509_certificate::extensions, x509_ocsp_responder::good, ocsp_check::issuer, ocsp_response::next_update, NULL, x509_authority_info_access::ocsp, ocsp_check_signature(), rc, ocsp_check::response, x509_certificate::root, ocsp_response::signer, strerror(), ocsp_response::this_update, TIMESTAMP_ERROR_MARGIN, x509_invalidate(), x509_name(), X509_OCSP_SIGNING, and x509_validate().

Referenced by validator_ocsp_validate().

Variable Documentation

◆ ocsp_algorithm_id

const uint8_t ocsp_algorithm_id[]
static
Initial value:
=
#define ASN1_OID_SHA1
ASN.1 OID for id-sha1 (1.3.14.3.2.26).
Definition asn1.h:228
#define OCSP_ALGORITHM_IDENTIFIER(...)
OCSP algorithm identifier.
Definition ocsp.h:28

OCSP digest algorithm identifier.

Definition at line 112 of file ocsp.c.

Referenced by ocsp_parse_cert_id(), and ocsp_request().

◆ oid_basic_response_type

const uint8_t oid_basic_response_type[] = { ASN1_OID_OCSP_BASIC }
static

OCSP basic response type.

Definition at line 116 of file ocsp.c.

#define ASN1_OID_OCSP_BASIC
ASN.1 OID for id-pkix-ocsp-basic ( 1.3.6.1.5.5.7.48.1.1).
Definition asn1.h:388

◆ oid_basic_response_type_cursor

struct asn1_cursor oid_basic_response_type_cursor
static
Initial value:
=
#define ASN1_CURSOR(value)
Define an ASN.1 cursor for a static value.
Definition asn1.h:408
static const uint8_t oid_basic_response_type[]
OCSP basic response type.
Definition ocsp.c:116

OCSP basic response type cursor.

Definition at line 119 of file ocsp.c.

Referenced by ocsp_parse_response_type().