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:181
#define EINFO_EACCES
Definition errno.h:300

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:591

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:626
#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:226
#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:972
int asn1_prepend_raw(struct asn1_builder *builder, const void *data, size_t len)
Prepend raw data to ASN.1 builder.
Definition asn1.c:949
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:169
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:231
int asn1_wrap(struct asn1_builder *builder, unsigned int type)
Wrap ASN.1 builder.
Definition asn1.c:999
#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:522
#define DBGC2_HDA(...)
Definition compiler.h:523
#define DBGC(...)
Definition compiler.h:505
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:219
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:230
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:224
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 len;
220 int rc;
221
222 /* Sanity check */
223 if ( ! responder->uri.len ) {
224 DBGC ( ocsp, "OCSP %p \"%s\" has no OCSP URI\n",
225 ocsp, x509_name ( ocsp->cert ) );
226 rc = -ENOTTY;
227 goto err_no_uri;
228 }
229
230 /* Calculate base64-encoded request length */
231 base64_len = ( base64_encoded_len ( ocsp->request.builder.len )
232 + 1 /* NUL */ );
233
234 /* Allocate and construct the base64-encoded request */
235 base64 = malloc ( base64_len );
236 if ( ! base64 ) {
237 rc = -ENOMEM;
238 goto err_alloc_base64;
239 }
241 base64, base64_len );
242
243 /* Calculate URI-encoded base64-encoded request length */
244 uri_len = ( uri_encode ( URI_PATH, base64, ( base64_len - 1 /* NUL */ ),
245 NULL, 0 ) + 1 /* NUL */ );
246
247 /* Allocate and construct the URI string */
248 len = ( responder->uri.len + 1 /* possible "/" */ + uri_len );
249 ocsp->uri_string = zalloc ( len );
250 if ( ! ocsp->uri_string ) {
251 rc = -ENOMEM;
252 goto err_alloc_uri;
253 }
254 memcpy ( ocsp->uri_string, responder->uri.data, responder->uri.len );
255 sep = &ocsp->uri_string[ responder->uri.len - 1 ];
256 if ( *sep != '/' )
257 *(++sep) = '/';
258 uri_encode ( URI_PATH, base64, base64_len, ( sep + 1 ), uri_len );
259 DBGC2 ( ocsp, "OCSP %p \"%s\" URI is %s\n",
260 ocsp, x509_name ( ocsp->cert ), ocsp->uri_string );
261
262 /* Success */
263 rc = 0;
264
265 err_alloc_uri:
266 free ( base64 );
267 err_alloc_base64:
268 err_no_uri:
269 return rc;
270}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
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:535
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
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 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 280 of file ocsp.c.

282 {
283 int rc;
284
285 /* Sanity checks */
286 assert ( cert != NULL );
287 assert ( issuer != NULL );
288 assert ( issuer->root != NULL );
289
290 /* Allocate and initialise check */
291 *ocsp = zalloc ( sizeof ( **ocsp ) );
292 if ( ! *ocsp ) {
293 rc = -ENOMEM;
294 goto err_alloc;
295 }
296 ref_init ( &(*ocsp)->refcnt, ocsp_free );
297 (*ocsp)->cert = x509_get ( cert );
298 (*ocsp)->issuer = x509_get ( issuer );
299
300 /* Build request */
301 if ( ( rc = ocsp_request ( *ocsp ) ) != 0 )
302 goto err_request;
303
304 /* Build URI string */
305 if ( ( rc = ocsp_uri_string ( *ocsp ) ) != 0 )
306 goto err_uri_string;
307
308 return 0;
309
310 err_uri_string:
311 err_request:
312 ocsp_put ( *ocsp );
313 err_alloc:
314 *ocsp = NULL;
315 return rc;
316}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
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 325 of file ocsp.c.

326 {
327 struct asn1_cursor cursor;
329 int rc;
330
331 /* Enter responseStatus */
332 memcpy ( &cursor, raw, sizeof ( cursor ) );
333 if ( ( rc = asn1_enter ( &cursor, ASN1_ENUMERATED ) ) != 0 ) {
334 DBGC ( ocsp, "OCSP %p \"%s\" could not locate responseStatus: "
335 "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
336 return rc;
337 }
338
339 /* Extract response status */
340 if ( cursor.len != sizeof ( status ) ) {
341 DBGC ( ocsp, "OCSP %p \"%s\" invalid status:\n",
342 ocsp, x509_name ( ocsp->cert ) );
343 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
344 return -EINVAL;
345 }
346 memcpy ( &status, cursor.data, sizeof ( status ) );
347
348 /* Check response status */
350 DBGC ( ocsp, "OCSP %p \"%s\" response status %d\n",
351 ocsp, x509_name ( ocsp->cert ), status );
352 return EPROTO_STATUS ( status );
353 }
354
355 return 0;
356}
__be32 raw[7]
Definition CIB_PRM.h:0
#define ASN1_ENUMERATED
ASN.1 enumeration.
Definition asn1.h:78
#define DBGC_HDA(...)
Definition compiler.h:506
#define EINVAL
Invalid argument.
Definition errno.h:429
#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 365 of file ocsp.c.

366 {
367 struct asn1_cursor cursor;
368
369 /* Enter responseType */
370 memcpy ( &cursor, raw, sizeof ( cursor ) );
371 asn1_enter ( &cursor, ASN1_OID );
372
373 /* Check responseType is "basic" */
374 if ( asn1_compare ( &oid_basic_response_type_cursor, &cursor ) != 0 ) {
375 DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n",
376 ocsp, x509_name ( ocsp->cert ) );
377 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
378 return -ENOTSUP_RESPONSE_TYPE;
379 }
380
381 return 0;
382}
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:458
#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 391 of file ocsp.c.

392 {
393 struct ocsp_responder *responder = &ocsp->response.responder;
394
395 /* Compare responder ID with certificate's subject */
396 return asn1_compare ( &responder->id, &cert->subject.raw );
397}
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 406 of file ocsp.c.

407 {
408 struct ocsp_responder *responder = &ocsp->response.responder;
409 struct asn1_cursor key_hash;
412 int difference;
413
414 /* Enter responder key hash */
415 memcpy ( &key_hash, &responder->id, sizeof ( key_hash ) );
416 asn1_enter ( &key_hash, ASN1_OCTET_STRING );
417
418 /* Sanity check */
419 difference = ( sizeof ( digest ) - key_hash.len );
420 if ( difference )
421 return difference;
422
423 /* Generate SHA1 hash of certificate's public key */
427 cert->subject.public_key.value.len );
428 digest_final ( &sha1_algorithm, ctx, digest );
429
430 /* Compare responder key hash with hash of certificate's public key */
431 return memcmp ( digest, key_hash.data, sizeof ( digest ) );
432}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
#define SHA1_DIGEST_SIZE
Definition Tpm20.h:26
struct digest_algorithm sha1_algorithm
SHA-1 algorithm.
Definition sha1.c:258
#define SHA1_CTX_SIZE
SHA-1 context size.
Definition sha1.h:67
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 441 of file ocsp.c.

442 {
443 struct ocsp_responder *responder = &ocsp->response.responder;
444 struct asn1_cursor *responder_id = &responder->id;
445 unsigned int type;
446
447 /* Enter responder ID */
448 memcpy ( responder_id, raw, sizeof ( *responder_id ) );
449 type = asn1_type ( responder_id );
450 asn1_enter_any ( responder_id );
451
452 /* Identify responder ID type */
453 switch ( type ) {
454 case ASN1_EXPLICIT_TAG ( 1 ) :
455 DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by name\n",
456 ocsp, x509_name ( ocsp->cert ) );
458 return 0;
459 case ASN1_EXPLICIT_TAG ( 2 ) :
460 DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by key "
461 "hash\n", ocsp, x509_name ( ocsp->cert ) );
463 return 0;
464 default:
465 DBGC ( ocsp, "OCSP %p \"%s\" unsupported responder ID type "
466 "%d\n", ocsp, x509_name ( ocsp->cert ), type );
467 return -ENOTSUP_RESPONDER_ID;
468 }
469}
int asn1_enter_any(struct asn1_cursor *cursor)
Enter ASN.1 object of any type.
Definition asn1.c:280
#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:479
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:406
static int ocsp_compare_responder_name(struct ocsp_check *ocsp, struct x509_certificate *cert)
Compare responder's certificate name.
Definition ocsp.c:391
#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 478 of file ocsp.c.

479 {
480 static struct asn1_cursor algorithm = {
481 .data = ocsp_algorithm_id,
482 .len = sizeof ( ocsp_algorithm_id ),
483 };
484 struct asn1_cursor cert_id;
485 struct asn1_cursor cursor;
486 int rc;
487
488 /* Enter cert ID */
489 memcpy ( &cert_id, raw, sizeof ( cert_id ) );
490 asn1_enter ( &cert_id, ASN1_SEQUENCE );
491
492 /* Check certID algorithm (but not parameters) */
493 memcpy ( &cursor, &cert_id, sizeof ( cursor ) );
494 if ( ( rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ),
495 asn1_shrink ( &cursor, ASN1_OID ),
496 asn1_shrink ( &algorithm, ASN1_OID ) ) ) != 0 ) {
497 DBGC ( ocsp, "OCSP %p \"%s\" certID missing algorithm:\n",
498 ocsp, x509_name ( ocsp->cert ) );
499 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
500 return -EACCES_CERT_MISMATCH;
501 }
502 if ( asn1_compare ( &cursor, &algorithm ) != 0 ) {
503 DBGC ( ocsp, "OCSP %p \"%s\" certID wrong algorithm:\n",
504 ocsp, x509_name ( ocsp->cert ) );
505 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
506 return -EACCES_CERT_MISMATCH;
507 }
508
509 /* Check remaining certID fields */
510 asn1_skip ( &cert_id, ASN1_SEQUENCE );
511 if ( asn1_compare ( &cert_id, &ocsp->request.cert_id_tail ) != 0 ) {
512 DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n",
513 ocsp, x509_name ( ocsp->cert ) );
514 DBGC_HDA ( ocsp, 0, ocsp->request.cert_id_tail.data,
515 ocsp->request.cert_id_tail.len );
516 DBGC_HDA ( ocsp, 0, cert_id.data, cert_id.len );
517 return -EACCES_CERT_MISMATCH;
518 }
519
520 return 0;
521}
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition asn1.c:254
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 530 of file ocsp.c.

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

604 {
605 struct ocsp_response *response = &ocsp->response;
606 struct asn1_cursor cursor;
607 int rc;
608
609 /* Record raw tbsResponseData */
610 memcpy ( &cursor, raw, sizeof ( cursor ) );
611 asn1_shrink_any ( &cursor );
612 memcpy ( &response->tbs, &cursor, sizeof ( response->tbs ) );
613
614 /* Enter tbsResponseData */
615 asn1_enter ( &cursor, ASN1_SEQUENCE );
616
617 /* Skip version, if present */
618 asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
619
620 /* Parse responderID */
621 if ( ( rc = ocsp_parse_responder_id ( ocsp, &cursor ) ) != 0 )
622 return rc;
623 asn1_skip_any ( &cursor );
624
625 /* Skip producedAt */
626 asn1_skip_any ( &cursor );
627
628 /* Parse responses */
629 if ( ( rc = ocsp_parse_responses ( ocsp, &cursor ) ) != 0 )
630 return rc;
631
632 return 0;
633}
int asn1_shrink_any(struct asn1_cursor *cursor)
Shrink ASN.1 object of any type.
Definition asn1.c:300
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition asn1.c:202
static int ocsp_parse_responder_id(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP responder ID.
Definition ocsp.c:441
static int ocsp_parse_responses(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP responses.
Definition ocsp.c:530
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 642 of file ocsp.c.

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

702 {
703 struct ocsp_response *response = &ocsp->response;
704 struct asn1_algorithm **algorithm = &response->algorithm;
705 struct asn1_cursor *signature = &response->signature;
706 struct asn1_cursor cursor;
707 int rc;
708
709 /* Enter BasicOCSPResponse */
710 memcpy ( &cursor, raw, sizeof ( cursor ) );
711 asn1_enter ( &cursor, ASN1_SEQUENCE );
712
713 /* Parse tbsResponseData */
714 if ( ( rc = ocsp_parse_tbs_response_data ( ocsp, &cursor ) ) != 0 )
715 return rc;
716 asn1_skip_any ( &cursor );
717
718 /* Parse signatureAlgorithm */
719 if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
720 DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature "
721 "algorithm: %s\n",
722 ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
723 return rc;
724 }
725 DBGC2 ( ocsp, "OCSP %p \"%s\" signature algorithm is %s\n",
726 ocsp, x509_name ( ocsp->cert ), (*algorithm)->name );
727 asn1_skip_any ( &cursor );
728
729 /* Parse signature */
730 memcpy ( signature, &cursor, sizeof ( *signature ) );
731 if ( ( rc = asn1_enter_bits ( signature, NULL ) ) != 0 ) {
732 DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature: %s\n",
733 ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
734 return rc;
735 }
736 asn1_skip_any ( &cursor );
737
738 /* Parse certs, if present */
739 if ( ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) &&
740 ( ( rc = ocsp_parse_certs ( ocsp, &cursor ) ) != 0 ) )
741 return rc;
742
743 return 0;
744}
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:311
int asn1_signature_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified signature algorithm.
Definition asn1.c:624
static int ocsp_parse_certs(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP certificates.
Definition ocsp.c:642
static int ocsp_parse_tbs_response_data(struct ocsp_check *ocsp, const struct asn1_cursor *raw)
Parse OCSP response data.
Definition ocsp.c:603
An ASN.1 OID-identified algorithm.
Definition asn1.h:408
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 753 of file ocsp.c.

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

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 785 of file ocsp.c.

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

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 814 of file ocsp.c.

814 {
815 struct ocsp_response *response = &ocsp->response;
816 struct asn1_cursor cursor;
817 int rc;
818
819 /* Duplicate data */
820 x509_put ( response->signer );
821 response->signer = NULL;
822 free ( response->data );
823 response->data = malloc ( len );
824 if ( ! response->data )
825 return -ENOMEM;
826 memcpy ( response->data, data, len );
827 cursor.data = response->data;
828 cursor.len = len;
829
830 /* Parse response */
831 if ( ( rc = ocsp_parse_response ( ocsp, &cursor ) ) != 0 )
832 return rc;
833
834 return 0;
835}
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:785

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 844 of file ocsp.c.

845 {
846 struct ocsp_response *response = &ocsp->response;
847 struct digest_algorithm *digest = response->algorithm->digest;
848 struct pubkey_algorithm *pubkey = response->algorithm->pubkey;
849 struct asn1_cursor *key = &signer->subject.public_key.raw;
850 uint8_t digest_ctx[ digest->ctxsize ];
851 uint8_t digest_out[ digest->digestsize ];
852 int rc;
853
854 /* Generate digest */
855 digest_init ( digest, digest_ctx );
856 digest_update ( digest, digest_ctx, response->tbs.data,
857 response->tbs.len );
858 digest_final ( digest, digest_ctx, digest_out );
859
860 /* Verify digest */
861 if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
862 &response->signature ) ) != 0 ) {
863 DBGC ( ocsp, "OCSP %p \"%s\" signature verification failed: "
864 "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
865 return rc;
866 }
867
868 DBGC2 ( ocsp, "OCSP %p \"%s\" signature is correct\n",
869 ocsp, x509_name ( ocsp->cert ) );
870 return 0;
871}
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
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:308
struct digest_algorithm * digest
Digest algorithm (if applicable)
Definition asn1.h:416
struct pubkey_algorithm * pubkey
Public-key algorithm (if applicable)
Definition asn1.h:414
A public key algorithm.
Definition crypto.h:122
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 880 of file ocsp.c.

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

◆ 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:402
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().