The function mbedtls_x509_ocsp_response_verify_info() was added, which
is similar to mbedtls_x509_crt_verify_info() but for OCSP responses
instead of certificates. To avoid code duplication, both of these
functions actually call a new function mbedtls_x509_verify_info() in
x509.h with their specific flags and strings in an array of struct
mbedtls_x509_info_string.
Modify the x509_crt.c and pkparse.c slightly so that the certificate
parsing (and mbedtls_x509_crt) keeps a pointer to the raw DER structure
containing the SubjectPublicKeyInfo. This improves the efficiency of
the OCSP response verification because we have to take the hash of the
certificate's key.
The function follows RFC 6960 and uses either the responder's name or
the responder's hash of their key as available in the OCSP response to
locate the correct issuer certificate.
To avoid code duplication, some functionality from x509_crt.c module
was moved to x509.c and made public in x509.h.
Add the main OCSP response verification function
mbedtls_x509_ocsp_verify_response() to the header file x509_ocsp.h and
a simple definition to x509_ocsp.c. At this stage, the verification
function only checks the response status and the timestamp and sets the
verification flags accordingly.
Also, new verification errors and flags are added as macros. These
values will be used in subsequent commits.
Rename the following functions in x509_ocsp.h and x509_ocsp.c to fit
the calling convention in other X.509 components (e.g CRL and CRT):
* mbedtls_x509_ocsp_parse_response -> mbedtls_x509_ocsp_response_parse
* mbedtls_x509_ocsp_parse_response_file -> mbedtls_x509_ocsp_response_parse_file
Add missing dependency checks to check_config.h and documentation to
config.h. Note that SHA-1 is required for OCSP as RFC 6960 Section
4.4.2 specifies that the ResponderID byKey is the SHA-1 hash of the
responder's public key. That is, without SHA-1 we might not be able to
tell who signed the OCSP response.
The new MBEDTLS_X509_OCSP_PARSE_C is a feature macro that can be
controlled from the config.h file to enable/disable the OCSP X509
feature at compile time.
Relocate the new OCSP and CRL X509 related errors to x509.h as the
error message generation scripts cannot handle these anywhere else.
Also, update the error.c file with the new human-readable strings
for the OCSP and CRL errors.
Strictly speaking, the CRLReason is a concept imported from the CRL
profile defined in RFC 5280 Section 5.3.1. However, this is a CRL
extension that is not implemented in mbed TLS. Therefore, this patch
introduces the relevant macros with revocation reasons and error return
codes in x509_crt.h. Also the function x509_ocsp_get_crl_reason() to
parse the CRLReason. If necessary, this code can later be migrated to
x509_crl.c.
The CRL reason ASN1. structure is specified in RFC 5280 Section 5.3.1
as follows:
CRLReason ::= ENUMERATED {
unspecified (0),
keyCompromise (1),
cACompromise (2),
affiliationChanged (3),
superseded (4),
cessationOfOperation (5),
certificateHold (6),
-- value 7 is not used
removeFromCRL (8),
privilegeWithdrawn (9),
aACompromise (10) }
Populate the function x509_ocsp_get_cert_status() with code that parses
the following ASN.1 structure:
CertStatus ::= CHOICE {
good [0] IMPLICIT NULL,
revoked [1] IMPLICIT RevokedInfo,
unknown [2] IMPLICIT UnknownInfo }
x509_ocsp_get_cert_status() parses the top level CHOICE and IMPLICIT
components. In the case of status good and unknown, their value is both
expected to be NULL because according to RFC 6960 Section 4.2:
UnknownInfo ::= NULL
Therefore, no further parsing is needed here. In the case of status
revoked, the parsing of Revoked info is delegated to a helper function.
Populate the function x509_ocsp_get_responses() that parses the
SEQUENCE OF tag in a BasicOCSPResponse. The function also calls its
helper function x509_ocsp_get_single_response() for each of the
SingleResponse(s) contained. Note that for each SingleResponse,
x509_ocsp_get_responses() must allocate a new internal struct
mbedtls_x509_ocsp_single_response where the parsed data will be
stored.
This change also populates the mbedtls_x509_ocsp_single_response
with the necessary values as specified by RFC 6960 Section 4.1.1.
Populate the function x509_ocsp_get_responder_id() with code that
parses the following X.509 structure:
ResponderID ::= CHOICE {
byName [1] Name,
byKey [2] KeyHash }
KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
(excluding the tag and length fields)
Note that here the name is parsed by the helper function
mbedtls_x509_get_name() and the KeyHash's bounds are checked but we
do not ensure that the hash is of the correct length.
Populate the function x509_ocsp_get_response_data() with code that
parses the following ASN.1 structure:
ResponseData ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1,
responderID ResponderID,
producedAt GeneralizedTime,
responses SEQUENCE OF SingleResponse,
responseExtensions [1] EXPLICIT Extensions OPTIONAL }
x509_ocsp_get_response_data() will parse the top-level SEQUENCE and the
two EXPLICIT tags. It delegates the parsing of the individual
subcomponents to x509_ocsp_get_version(), x509_ocsp_get_responder_id(),
x509_ocsp_get_generalized_time(), x509_ocsp_get_responses() and
x509_ocsp_get_extensions().
Populate the function x509_ocsp_get_response() that parses the top
level components of the following ASN.1 structure:
BasicOCSPResponse ::= SEQUENCE {
tbsResponseData ResponseData,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING,
certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
The top-level components correspond to the main SEQUENCE and the
EXPLICIT tag.
The added code removed the SEQUENCE component from the following ASN.1
structure:
ResponseBytes ::= SEQUENCE {
responseType OBJECT IDENTIFIER,
response OCTET STRING }
The parsing for responseType and response is delegated to
x509_ocsp_get_response_type() and x509_ocsp_get_response() respectively.
Populate the function x509_ocsp_get_response_status() that parses the
OCSPResponseStatus:
OCSPResponseStatus ::= ENUMERATED {
successful (0), -- Response has valid confirmations
malformedRequest (1), -- Illegal confirmation request
internalError (2), -- Internal error in issuer
tryLater (3), -- Try again later
-- (4) is not used
sigRequired (5), -- Must sign the request
unauthorized (6) -- Request unauthorized
}
The function writes the value into the resp_status field of the
mbedtls_x509_ocsp_response struct.
Add parsing for the OCSPResponse top level components:
OCSPResponse ::= SEQUENCE {
responseStatus OCSPResponseStatus,
responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
The added code does the following:
1. Parse the top level SEQUENCE
2. Call x509_ocsp_get_response_status() which will parse the
responseStatus in the future
3. If there is any data left in the buffer, parses the EXPLICIT
tag and calls x509_ocsp_get_response_bytes() which will parse
the responseBytes in the future
At this stage, the main framework for the code is being set up. The idea
is that each function will parse the top level components of the ASN1
objects and hand over the parsing of each of the individual
sub-components to other functions. Also, note that each function its
responsible for checking that:
1. At the begining, there is enough space in the buffer p to parse
whatever is being processed before end.
2. Prior to returning, the length specified in the ASN1 encoding
matches the number of bytes consumed from the buffer p.
3. The lengths of any intermediate sub-components (such as EXPLICIT
tags) parsed matches the number of bytes consumed by the called
functions x509_ocsp_get_*().
OCSP by itself is a protocol between an OCSP responder and a client.
The protocol messages are encoded in X.509 format, so I have created
the place-holder files x509_ocsp.c and x509_ocsp.h that will contain
the X.509 parser and verification for OCSP messages.
As noted in #557, several functions use 'index' resp. 'time'
as parameter names in their declaration and/or definition, causing name
conflicts with the functions in the C standard library of the same
name some compilers warn about.
This commit renames the arguments accordingly.
Allow forcing 64-bit integer type for bignum operations. Also introduce
the macro MBEDTLS_TYPE_UDBL to allow configuration of the double length
integer in unknown compilers.
Rename the macro MBEDTLS_PLATFORM_SETUP_ALT to
MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT to make the name more descriptive
as this macro enables/disables both functions.