1/* 2 * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 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 8 */ 9 10#include <stdio.h> 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" 18 19/* 20 * Utility functions related to sending OCSP responses and extracting 21 * relevant information from the request. 22 */ 23int OCSP_request_onereq_count(OCSP_REQUEST *req) 24{ 25 return sk_OCSP_ONEREQ_num(req->tbsRequest.requestList); 26} 27 28OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i) 29{ 30 return sk_OCSP_ONEREQ_value(req->tbsRequest.requestList, i); 31} 32 33OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one) 34{ 35 return one->reqCert; 36} 37 38int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, 39 ASN1_OCTET_STRING **pikeyHash, 40 ASN1_INTEGER **pserial, OCSP_CERTID *cid) 41{ 42 if (!cid) 43 return 0; 44 if (pmd) 45 *pmd = cid->hashAlgorithm.algorithm; 46 if (piNameHash) 47 *piNameHash = &cid->issuerNameHash; 48 if (pikeyHash) 49 *pikeyHash = &cid->issuerKeyHash; 50 if (pserial) 51 *pserial = &cid->serialNumber; 52 return 1; 53} 54 55int OCSP_request_is_signed(OCSP_REQUEST *req) 56{ 57 if (req->optionalSignature) 58 return 1; 59 return 0; 60} 61 62/* Create an OCSP response and encode an optional basic response */ 63OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs) 64{ 65 OCSP_RESPONSE *rsp = NULL; 66 67 if ((rsp = OCSP_RESPONSE_new()) == NULL) 68 goto err; 69 if (!(ASN1_ENUMERATED_set(rsp->responseStatus, status))) 70 goto err; 71 if (!bs) 72 return rsp; 73 if ((rsp->responseBytes = OCSP_RESPBYTES_new()) == NULL) 74 goto err; 75 rsp->responseBytes->responseType = OBJ_nid2obj(NID_id_pkix_OCSP_basic); 76 if (!ASN1_item_pack 77 (bs, ASN1_ITEM_rptr(OCSP_BASICRESP), &rsp->responseBytes->response)) 78 goto err; 79 return rsp; 80 err: 81 OCSP_RESPONSE_free(rsp); 82 return NULL; 83} 84 85OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp, 86 OCSP_CERTID *cid, 87 int status, int reason, 88 ASN1_TIME *revtime, 89 ASN1_TIME *thisupd, 90 ASN1_TIME *nextupd) 91{ 92 OCSP_SINGLERESP *single = NULL; 93 OCSP_CERTSTATUS *cs; 94 OCSP_REVOKEDINFO *ri; 95 96 if (rsp->tbsResponseData.responses == NULL 97 && (rsp->tbsResponseData.responses 98 = sk_OCSP_SINGLERESP_new_null()) == NULL) 99 goto err; 100 101 if ((single = OCSP_SINGLERESP_new()) == NULL) 102 goto err; 103 104 if (!ASN1_TIME_to_generalizedtime(thisupd, &single->thisUpdate)) 105 goto err; 106 if (nextupd && 107 !ASN1_TIME_to_generalizedtime(nextupd, &single->nextUpdate)) 108 goto err; 109 110 OCSP_CERTID_free(single->certId); 111 112 if ((single->certId = OCSP_CERTID_dup(cid)) == NULL) 113 goto err; 114 115 cs = single->certStatus; 116 switch (cs->type = status) { 117 case V_OCSP_CERTSTATUS_REVOKED: 118 if (!revtime) { 119 ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_REVOKED_TIME); 120 goto err; 121 } 122 if ((cs->value.revoked = ri = OCSP_REVOKEDINFO_new()) == NULL) 123 goto err; 124 if (!ASN1_TIME_to_generalizedtime(revtime, &ri->revocationTime)) 125 goto err; 126 if (reason != OCSP_REVOKED_STATUS_NOSTATUS) { 127 if ((ri->revocationReason = ASN1_ENUMERATED_new()) == NULL) 128 goto err; 129 if (!(ASN1_ENUMERATED_set(ri->revocationReason, reason))) 130 goto err; 131 } 132 break; 133 134 case V_OCSP_CERTSTATUS_GOOD: 135 if ((cs->value.good = ASN1_NULL_new()) == NULL) 136 goto err; 137 break; 138 139 case V_OCSP_CERTSTATUS_UNKNOWN: 140 if ((cs->value.unknown = ASN1_NULL_new()) == NULL) 141 goto err; 142 break; 143 144 default: 145 goto err; 146 147 } 148 if (!(sk_OCSP_SINGLERESP_push(rsp->tbsResponseData.responses, single))) 149 goto err; 150 return single; 151 err: 152 OCSP_SINGLERESP_free(single); 153 return NULL; 154} 155 156/* Add a certificate to an OCSP request */ 157int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert) 158{ 159 return ossl_x509_add_cert_new(&resp->certs, cert, X509_ADD_FLAG_UP_REF); 160} 161 162/* 163 * Sign an OCSP response using the parameters contained in the digest context, 164 * set the responderID to the subject name in the signer's certificate, and 165 * include one or more optional certificates in the response. 166 */ 167int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp, 168 X509 *signer, EVP_MD_CTX *ctx, 169 STACK_OF(X509) *certs, unsigned long flags) 170{ 171 OCSP_RESPID *rid; 172 EVP_PKEY *pkey; 173 174 if (ctx == NULL || EVP_MD_CTX_get_pkey_ctx(ctx) == NULL) { 175 ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_SIGNER_KEY); 176 goto err; 177 } 178 179 pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx)); 180 if (pkey == NULL || !X509_check_private_key(signer, pkey)) { 181 ERR_raise(ERR_LIB_OCSP, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); 182 goto err; 183 } 184 185 if (!(flags & OCSP_NOCERTS)) { 186 if (!OCSP_basic_add1_cert(brsp, signer) 187 || !X509_add_certs(brsp->certs, certs, X509_ADD_FLAG_UP_REF)) 188 goto err; 189 } 190 191 rid = &brsp->tbsResponseData.responderId; 192 if (flags & OCSP_RESPID_KEY) { 193 if (!OCSP_RESPID_set_by_key(rid, signer)) 194 goto err; 195 } else if (!OCSP_RESPID_set_by_name(rid, signer)) { 196 goto err; 197 } 198 199 if (!(flags & OCSP_NOTIME) && 200 !X509_gmtime_adj(brsp->tbsResponseData.producedAt, 0)) 201 goto err; 202 203 /* 204 * Right now, I think that not doing double hashing is the right thing. 205 * -- Richard Levitte 206 */ 207 if (!OCSP_BASICRESP_sign_ctx(brsp, ctx, 0)) 208 goto err; 209 210 return 1; 211 err: 212 return 0; 213} 214 215int OCSP_basic_sign(OCSP_BASICRESP *brsp, 216 X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, 217 STACK_OF(X509) *certs, unsigned long flags) 218{ 219 EVP_MD_CTX *ctx = EVP_MD_CTX_new(); 220 EVP_PKEY_CTX *pkctx = NULL; 221 int i; 222 223 if (ctx == NULL) 224 return 0; 225 226 if (!EVP_DigestSignInit_ex(ctx, &pkctx, EVP_MD_get0_name(dgst), 227 signer->libctx, signer->propq, key, NULL)) { 228 EVP_MD_CTX_free(ctx); 229 return 0; 230 } 231 i = OCSP_basic_sign_ctx(brsp, signer, ctx, certs, flags); 232 EVP_MD_CTX_free(ctx); 233 return i; 234} 235 236int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert) 237{ 238 if (!X509_NAME_set(&respid->value.byName, X509_get_subject_name(cert))) 239 return 0; 240 241 respid->type = V_OCSP_RESPID_NAME; 242 243 return 1; 244} 245 246int OCSP_RESPID_set_by_key_ex(OCSP_RESPID *respid, X509 *cert, 247 OSSL_LIB_CTX *libctx, const char *propq) 248{ 249 ASN1_OCTET_STRING *byKey = NULL; 250 unsigned char md[SHA_DIGEST_LENGTH]; 251 EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq); 252 int ret = 0; 253 254 if (sha1 == NULL) 255 return 0; 256 257 /* RFC2560 requires SHA1 */ 258 if (!X509_pubkey_digest(cert, sha1, md, NULL)) 259 goto err; 260 261 byKey = ASN1_OCTET_STRING_new(); 262 if (byKey == NULL) 263 goto err; 264 265 if (!(ASN1_OCTET_STRING_set(byKey, md, SHA_DIGEST_LENGTH))) { 266 ASN1_OCTET_STRING_free(byKey); 267 goto err; 268 } 269 270 respid->type = V_OCSP_RESPID_KEY; 271 respid->value.byKey = byKey; 272 273 ret = 1; 274 err: 275 EVP_MD_free(sha1); 276 return ret; 277} 278 279int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert) 280{ 281 if (cert == NULL) 282 return 0; 283 return OCSP_RESPID_set_by_key_ex(respid, cert, cert->libctx, cert->propq); 284} 285 286int OCSP_RESPID_match_ex(OCSP_RESPID *respid, X509 *cert, OSSL_LIB_CTX *libctx, 287 const char *propq) 288{ 289 EVP_MD *sha1 = NULL; 290 int ret = 0; 291 292 if (respid->type == V_OCSP_RESPID_KEY) { 293 unsigned char md[SHA_DIGEST_LENGTH]; 294 295 sha1 = EVP_MD_fetch(libctx, "SHA1", propq); 296 if (sha1 == NULL) 297 goto err; 298 299 if (respid->value.byKey == NULL) 300 goto err; 301 302 /* RFC2560 requires SHA1 */ 303 if (!X509_pubkey_digest(cert, sha1, md, NULL)) 304 goto err; 305 306 ret = (ASN1_STRING_length(respid->value.byKey) == SHA_DIGEST_LENGTH) 307 && (memcmp(ASN1_STRING_get0_data(respid->value.byKey), md, 308 SHA_DIGEST_LENGTH) == 0); 309 } else if (respid->type == V_OCSP_RESPID_NAME) { 310 if (respid->value.byName == NULL) 311 return 0; 312 313 return X509_NAME_cmp(respid->value.byName, 314 X509_get_subject_name(cert)) == 0; 315 } 316 317 err: 318 EVP_MD_free(sha1); 319 return ret; 320} 321 322int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert) 323{ 324 if (cert == NULL) 325 return 0; 326 return OCSP_RESPID_match_ex(respid, cert, cert->libctx, cert->propq); 327} 328