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