2 * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include "internal/cryptlib.h"
12 #include <openssl/objects.h>
13 #include <openssl/x509.h>
14 #include <openssl/pem.h>
15 #include <openssl/x509v3.h>
16 #include <openssl/ocsp.h>
17 #include "ocsp_local.h"
20 * Utility functions related to sending OCSP responses and extracting
21 * relevant information from the request.
24 int OCSP_request_onereq_count(OCSP_REQUEST
*req
)
26 return sk_OCSP_ONEREQ_num(req
->tbsRequest
.requestList
);
29 OCSP_ONEREQ
*OCSP_request_onereq_get0(OCSP_REQUEST
*req
, int i
)
31 return sk_OCSP_ONEREQ_value(req
->tbsRequest
.requestList
, i
);
34 OCSP_CERTID
*OCSP_onereq_get0_id(OCSP_ONEREQ
*one
)
39 int OCSP_id_get0_info(ASN1_OCTET_STRING
**piNameHash
, ASN1_OBJECT
**pmd
,
40 ASN1_OCTET_STRING
**pikeyHash
,
41 ASN1_INTEGER
**pserial
, OCSP_CERTID
*cid
)
46 *pmd
= cid
->hashAlgorithm
.algorithm
;
48 *piNameHash
= &cid
->issuerNameHash
;
50 *pikeyHash
= &cid
->issuerKeyHash
;
52 *pserial
= &cid
->serialNumber
;
56 int OCSP_request_is_signed(OCSP_REQUEST
*req
)
58 if (req
->optionalSignature
)
63 /* Create an OCSP response and encode an optional basic response */
64 OCSP_RESPONSE
*OCSP_response_create(int status
, OCSP_BASICRESP
*bs
)
66 OCSP_RESPONSE
*rsp
= NULL
;
68 if ((rsp
= OCSP_RESPONSE_new()) == NULL
)
70 if (!(ASN1_ENUMERATED_set(rsp
->responseStatus
, status
)))
74 if ((rsp
->responseBytes
= OCSP_RESPBYTES_new()) == NULL
)
76 rsp
->responseBytes
->responseType
= OBJ_nid2obj(NID_id_pkix_OCSP_basic
);
78 (bs
, ASN1_ITEM_rptr(OCSP_BASICRESP
), &rsp
->responseBytes
->response
))
82 OCSP_RESPONSE_free(rsp
);
86 OCSP_SINGLERESP
*OCSP_basic_add1_status(OCSP_BASICRESP
*rsp
,
88 int status
, int reason
,
93 OCSP_SINGLERESP
*single
= NULL
;
97 if (rsp
->tbsResponseData
.responses
== NULL
98 && (rsp
->tbsResponseData
.responses
99 = sk_OCSP_SINGLERESP_new_null()) == NULL
)
102 if ((single
= OCSP_SINGLERESP_new()) == NULL
)
105 if (!ASN1_TIME_to_generalizedtime(thisupd
, &single
->thisUpdate
))
108 !ASN1_TIME_to_generalizedtime(nextupd
, &single
->nextUpdate
))
111 OCSP_CERTID_free(single
->certId
);
113 if ((single
->certId
= OCSP_CERTID_dup(cid
)) == NULL
)
116 cs
= single
->certStatus
;
117 switch (cs
->type
= status
) {
118 case V_OCSP_CERTSTATUS_REVOKED
:
120 OCSPerr(OCSP_F_OCSP_BASIC_ADD1_STATUS
, OCSP_R_NO_REVOKED_TIME
);
123 if ((cs
->value
.revoked
= ri
= OCSP_REVOKEDINFO_new()) == NULL
)
125 if (!ASN1_TIME_to_generalizedtime(revtime
, &ri
->revocationTime
))
127 if (reason
!= OCSP_REVOKED_STATUS_NOSTATUS
) {
128 if ((ri
->revocationReason
= ASN1_ENUMERATED_new()) == NULL
)
130 if (!(ASN1_ENUMERATED_set(ri
->revocationReason
, reason
)))
135 case V_OCSP_CERTSTATUS_GOOD
:
136 if ((cs
->value
.good
= ASN1_NULL_new()) == NULL
)
140 case V_OCSP_CERTSTATUS_UNKNOWN
:
141 if ((cs
->value
.unknown
= ASN1_NULL_new()) == NULL
)
149 if (!(sk_OCSP_SINGLERESP_push(rsp
->tbsResponseData
.responses
, single
)))
153 OCSP_SINGLERESP_free(single
);
157 /* Add a certificate to an OCSP request */
159 int OCSP_basic_add1_cert(OCSP_BASICRESP
*resp
, X509
*cert
)
161 if (resp
->certs
== NULL
162 && (resp
->certs
= sk_X509_new_null()) == NULL
)
165 if (!sk_X509_push(resp
->certs
, cert
))
172 * Sign an OCSP response using the parameters contained in the digest context,
173 * set the responderID to the subject name in the signer's certificate, and
174 * include one or more optional certificates in the response.
177 int OCSP_basic_sign_ctx(OCSP_BASICRESP
*brsp
,
178 X509
*signer
, EVP_MD_CTX
*ctx
,
179 STACK_OF(X509
) *certs
, unsigned long flags
)
185 if (ctx
== NULL
|| EVP_MD_CTX_pkey_ctx(ctx
) == NULL
) {
186 OCSPerr(OCSP_F_OCSP_BASIC_SIGN_CTX
, OCSP_R_NO_SIGNER_KEY
);
190 pkey
= EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx
));
191 if (pkey
== NULL
|| !X509_check_private_key(signer
, pkey
)) {
192 OCSPerr(OCSP_F_OCSP_BASIC_SIGN_CTX
,
193 OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE
);
197 if (!(flags
& OCSP_NOCERTS
)) {
198 if (!OCSP_basic_add1_cert(brsp
, signer
))
200 for (i
= 0; i
< sk_X509_num(certs
); i
++) {
201 X509
*tmpcert
= sk_X509_value(certs
, i
);
202 if (!OCSP_basic_add1_cert(brsp
, tmpcert
))
207 rid
= &brsp
->tbsResponseData
.responderId
;
208 if (flags
& OCSP_RESPID_KEY
) {
209 if (!OCSP_RESPID_set_by_key(rid
, signer
))
211 } else if (!OCSP_RESPID_set_by_name(rid
, signer
)) {
215 if (!(flags
& OCSP_NOTIME
) &&
216 !X509_gmtime_adj(brsp
->tbsResponseData
.producedAt
, 0))
220 * Right now, I think that not doing double hashing is the right thing.
224 if (!OCSP_BASICRESP_sign_ctx(brsp
, ctx
, 0))
232 int OCSP_basic_sign(OCSP_BASICRESP
*brsp
,
233 X509
*signer
, EVP_PKEY
*key
, const EVP_MD
*dgst
,
234 STACK_OF(X509
) *certs
, unsigned long flags
)
236 EVP_MD_CTX
*ctx
= EVP_MD_CTX_new();
237 EVP_PKEY_CTX
*pkctx
= NULL
;
243 if (!EVP_DigestSignInit(ctx
, &pkctx
, dgst
, NULL
, key
)) {
244 EVP_MD_CTX_free(ctx
);
247 i
= OCSP_basic_sign_ctx(brsp
, signer
, ctx
, certs
, flags
);
248 EVP_MD_CTX_free(ctx
);
252 int OCSP_RESPID_set_by_name(OCSP_RESPID
*respid
, X509
*cert
)
254 if (!X509_NAME_set(&respid
->value
.byName
, X509_get_subject_name(cert
)))
257 respid
->type
= V_OCSP_RESPID_NAME
;
262 int OCSP_RESPID_set_by_key(OCSP_RESPID
*respid
, X509
*cert
)
264 ASN1_OCTET_STRING
*byKey
= NULL
;
265 unsigned char md
[SHA_DIGEST_LENGTH
];
267 /* RFC2560 requires SHA1 */
268 if (!X509_pubkey_digest(cert
, EVP_sha1(), md
, NULL
))
271 byKey
= ASN1_OCTET_STRING_new();
275 if (!(ASN1_OCTET_STRING_set(byKey
, md
, SHA_DIGEST_LENGTH
))) {
276 ASN1_OCTET_STRING_free(byKey
);
280 respid
->type
= V_OCSP_RESPID_KEY
;
281 respid
->value
.byKey
= byKey
;
286 int OCSP_RESPID_match(OCSP_RESPID
*respid
, X509
*cert
)
288 if (respid
->type
== V_OCSP_RESPID_KEY
) {
289 unsigned char md
[SHA_DIGEST_LENGTH
];
291 if (respid
->value
.byKey
== NULL
)
294 /* RFC2560 requires SHA1 */
295 if (!X509_pubkey_digest(cert
, EVP_sha1(), md
, NULL
))
298 return (ASN1_STRING_length(respid
->value
.byKey
) == SHA_DIGEST_LENGTH
)
299 && (memcmp(ASN1_STRING_get0_data(respid
->value
.byKey
), md
,
300 SHA_DIGEST_LENGTH
) == 0);
301 } else if (respid
->type
== V_OCSP_RESPID_NAME
) {
302 if (respid
->value
.byName
== NULL
)
305 return X509_NAME_cmp(respid
->value
.byName
,
306 X509_get_subject_name(cert
)) == 0;