1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright Nokia 2007-2019 4e1051a39Sopenharmony_ci * Copyright Siemens AG 2015-2019 5e1051a39Sopenharmony_ci * 6e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 7e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 8e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 9e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 10e1051a39Sopenharmony_ci */ 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include "cmp_local.h" 13e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 14e1051a39Sopenharmony_ci#include "e_os.h" /* ossl_sleep() */ 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci/* explicit #includes not strictly needed since implied by the above: */ 17e1051a39Sopenharmony_ci#include <openssl/bio.h> 18e1051a39Sopenharmony_ci#include <openssl/cmp.h> 19e1051a39Sopenharmony_ci#include <openssl/err.h> 20e1051a39Sopenharmony_ci#include <openssl/evp.h> 21e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 22e1051a39Sopenharmony_ci#include <openssl/cmp_util.h> 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci#define IS_CREP(t) ((t) == OSSL_CMP_PKIBODY_IP || (t) == OSSL_CMP_PKIBODY_CP \ 25e1051a39Sopenharmony_ci || (t) == OSSL_CMP_PKIBODY_KUP) 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ci/*- 28e1051a39Sopenharmony_ci * Evaluate whether there's an exception (violating the standard) configured for 29e1051a39Sopenharmony_ci * handling negative responses without protection or with invalid protection. 30e1051a39Sopenharmony_ci * Returns 1 on acceptance, 0 on rejection, or -1 on (internal) error. 31e1051a39Sopenharmony_ci */ 32e1051a39Sopenharmony_cistatic int unprotected_exception(const OSSL_CMP_CTX *ctx, 33e1051a39Sopenharmony_ci const OSSL_CMP_MSG *rep, 34e1051a39Sopenharmony_ci int invalid_protection, 35e1051a39Sopenharmony_ci int expected_type /* ignored here */) 36e1051a39Sopenharmony_ci{ 37e1051a39Sopenharmony_ci int rcvd_type = OSSL_CMP_MSG_get_bodytype(rep /* may be NULL */); 38e1051a39Sopenharmony_ci const char *msg_type = NULL; 39e1051a39Sopenharmony_ci 40e1051a39Sopenharmony_ci if (!ossl_assert(ctx != NULL && rep != NULL)) 41e1051a39Sopenharmony_ci return -1; 42e1051a39Sopenharmony_ci 43e1051a39Sopenharmony_ci if (!ctx->unprotectedErrors) 44e1051a39Sopenharmony_ci return 0; 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_ci switch (rcvd_type) { 47e1051a39Sopenharmony_ci case OSSL_CMP_PKIBODY_ERROR: 48e1051a39Sopenharmony_ci msg_type = "error response"; 49e1051a39Sopenharmony_ci break; 50e1051a39Sopenharmony_ci case OSSL_CMP_PKIBODY_RP: 51e1051a39Sopenharmony_ci { 52e1051a39Sopenharmony_ci OSSL_CMP_PKISI *si = 53e1051a39Sopenharmony_ci ossl_cmp_revrepcontent_get_pkisi(rep->body->value.rp, 54e1051a39Sopenharmony_ci OSSL_CMP_REVREQSID); 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci if (si == NULL) 57e1051a39Sopenharmony_ci return -1; 58e1051a39Sopenharmony_ci if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_rejection) 59e1051a39Sopenharmony_ci msg_type = "revocation response message with rejection status"; 60e1051a39Sopenharmony_ci break; 61e1051a39Sopenharmony_ci } 62e1051a39Sopenharmony_ci case OSSL_CMP_PKIBODY_PKICONF: 63e1051a39Sopenharmony_ci msg_type = "PKI Confirmation message"; 64e1051a39Sopenharmony_ci break; 65e1051a39Sopenharmony_ci default: 66e1051a39Sopenharmony_ci if (IS_CREP(rcvd_type)) { 67e1051a39Sopenharmony_ci int any_rid = OSSL_CMP_CERTREQID_NONE; 68e1051a39Sopenharmony_ci OSSL_CMP_CERTREPMESSAGE *crepmsg = rep->body->value.ip; 69e1051a39Sopenharmony_ci OSSL_CMP_CERTRESPONSE *crep = 70e1051a39Sopenharmony_ci ossl_cmp_certrepmessage_get0_certresponse(crepmsg, any_rid); 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_ci if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) 73e1051a39Sopenharmony_ci return -1; 74e1051a39Sopenharmony_ci if (crep == NULL) 75e1051a39Sopenharmony_ci return -1; 76e1051a39Sopenharmony_ci if (ossl_cmp_pkisi_get_status(crep->status) 77e1051a39Sopenharmony_ci == OSSL_CMP_PKISTATUS_rejection) 78e1051a39Sopenharmony_ci msg_type = "CertRepMessage with rejection status"; 79e1051a39Sopenharmony_ci } 80e1051a39Sopenharmony_ci } 81e1051a39Sopenharmony_ci if (msg_type == NULL) 82e1051a39Sopenharmony_ci return 0; 83e1051a39Sopenharmony_ci ossl_cmp_log2(WARN, ctx, "ignoring %s protection of %s", 84e1051a39Sopenharmony_ci invalid_protection ? "invalid" : "missing", msg_type); 85e1051a39Sopenharmony_ci return 1; 86e1051a39Sopenharmony_ci} 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci/* Save error info from PKIStatusInfo field of a certresponse into ctx */ 89e1051a39Sopenharmony_cistatic int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si) 90e1051a39Sopenharmony_ci{ 91e1051a39Sopenharmony_ci int i; 92e1051a39Sopenharmony_ci OSSL_CMP_PKIFREETEXT *ss; 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci if (!ossl_assert(ctx != NULL && si != NULL)) 95e1051a39Sopenharmony_ci return 0; 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci ctx->status = ossl_cmp_pkisi_get_status(si); 98e1051a39Sopenharmony_ci if (ctx->status < OSSL_CMP_PKISTATUS_accepted) 99e1051a39Sopenharmony_ci return 0; 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci ctx->failInfoCode = ossl_cmp_pkisi_get_pkifailureinfo(si); 102e1051a39Sopenharmony_ci 103e1051a39Sopenharmony_ci if (!ossl_cmp_ctx_set0_statusString(ctx, sk_ASN1_UTF8STRING_new_null()) 104e1051a39Sopenharmony_ci || (ctx->statusString == NULL)) 105e1051a39Sopenharmony_ci return 0; 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci ss = si->statusString; /* may be NULL */ 108e1051a39Sopenharmony_ci for (i = 0; i < sk_ASN1_UTF8STRING_num(ss); i++) { 109e1051a39Sopenharmony_ci ASN1_UTF8STRING *str = sk_ASN1_UTF8STRING_value(ss, i); 110e1051a39Sopenharmony_ci ASN1_UTF8STRING *dup = ASN1_STRING_dup(str); 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci if (dup == NULL || !sk_ASN1_UTF8STRING_push(ctx->statusString, dup)) { 113e1051a39Sopenharmony_ci ASN1_UTF8STRING_free(dup); 114e1051a39Sopenharmony_ci return 0; 115e1051a39Sopenharmony_ci } 116e1051a39Sopenharmony_ci } 117e1051a39Sopenharmony_ci return 1; 118e1051a39Sopenharmony_ci} 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci/*- 121e1051a39Sopenharmony_ci * Perform the generic aspects of sending a request and receiving a response. 122e1051a39Sopenharmony_ci * Returns 1 on success and provides the received PKIMESSAGE in *rep. 123e1051a39Sopenharmony_ci * Returns 0 on error. 124e1051a39Sopenharmony_ci * Regardless of success, caller is responsible for freeing *rep (unless NULL). 125e1051a39Sopenharmony_ci */ 126e1051a39Sopenharmony_cistatic int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, 127e1051a39Sopenharmony_ci OSSL_CMP_MSG **rep, int expected_type) 128e1051a39Sopenharmony_ci{ 129e1051a39Sopenharmony_ci int begin_transaction = 130e1051a39Sopenharmony_ci expected_type != OSSL_CMP_PKIBODY_POLLREP 131e1051a39Sopenharmony_ci && expected_type != OSSL_CMP_PKIBODY_PKICONF; 132e1051a39Sopenharmony_ci const char *req_type_str = 133e1051a39Sopenharmony_ci ossl_cmp_bodytype_to_string(OSSL_CMP_MSG_get_bodytype(req)); 134e1051a39Sopenharmony_ci const char *expected_type_str = ossl_cmp_bodytype_to_string(expected_type); 135e1051a39Sopenharmony_ci int bak_msg_timeout = ctx->msg_timeout; 136e1051a39Sopenharmony_ci int bt; 137e1051a39Sopenharmony_ci time_t now = time(NULL); 138e1051a39Sopenharmony_ci int time_left; 139e1051a39Sopenharmony_ci OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb; 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_ci if (transfer_cb == NULL) 142e1051a39Sopenharmony_ci transfer_cb = OSSL_CMP_MSG_http_perform; 143e1051a39Sopenharmony_ci *rep = NULL; 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci if (ctx->total_timeout != 0 /* not waiting indefinitely */) { 146e1051a39Sopenharmony_ci if (begin_transaction) 147e1051a39Sopenharmony_ci ctx->end_time = now + ctx->total_timeout; 148e1051a39Sopenharmony_ci if (now >= ctx->end_time) { 149e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT); 150e1051a39Sopenharmony_ci return 0; 151e1051a39Sopenharmony_ci } 152e1051a39Sopenharmony_ci if (!ossl_assert(ctx->end_time - now < INT_MAX)) { 153e1051a39Sopenharmony_ci /* actually cannot happen due to assignment in initial_certreq() */ 154e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS); 155e1051a39Sopenharmony_ci return 0; 156e1051a39Sopenharmony_ci } 157e1051a39Sopenharmony_ci time_left = (int)(ctx->end_time - now); 158e1051a39Sopenharmony_ci if (ctx->msg_timeout == 0 || time_left < ctx->msg_timeout) 159e1051a39Sopenharmony_ci ctx->msg_timeout = time_left; 160e1051a39Sopenharmony_ci } 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci /* should print error queue since transfer_cb may call ERR_clear_error() */ 163e1051a39Sopenharmony_ci OSSL_CMP_CTX_print_errors(ctx); 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str); 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ci *rep = (*transfer_cb)(ctx, req); 168e1051a39Sopenharmony_ci ctx->msg_timeout = bak_msg_timeout; 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci if (*rep == NULL) { 171e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_CMP, 172e1051a39Sopenharmony_ci ctx->total_timeout != 0 && time(NULL) >= ctx->end_time ? 173e1051a39Sopenharmony_ci CMP_R_TOTAL_TIMEOUT : CMP_R_TRANSFER_ERROR, 174e1051a39Sopenharmony_ci "request sent: %s, expected response: %s", 175e1051a39Sopenharmony_ci req_type_str, expected_type_str); 176e1051a39Sopenharmony_ci return 0; 177e1051a39Sopenharmony_ci } 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci bt = OSSL_CMP_MSG_get_bodytype(*rep); 180e1051a39Sopenharmony_ci /* 181e1051a39Sopenharmony_ci * The body type in the 'bt' variable is not yet verified. 182e1051a39Sopenharmony_ci * Still we use this preliminary value already for a progress report because 183e1051a39Sopenharmony_ci * the following msg verification may also produce log entries and may fail. 184e1051a39Sopenharmony_ci */ 185e1051a39Sopenharmony_ci ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt)); 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci /* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */ 188e1051a39Sopenharmony_ci if (bt != OSSL_CMP_PKIBODY_POLLREP && bt != OSSL_CMP_PKIBODY_PKICONF 189e1051a39Sopenharmony_ci && !ossl_cmp_ctx_set1_extraCertsIn(ctx, (*rep)->extraCerts)) 190e1051a39Sopenharmony_ci return 0; 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ci if (!ossl_cmp_msg_check_update(ctx, *rep, unprotected_exception, 193e1051a39Sopenharmony_ci expected_type)) 194e1051a39Sopenharmony_ci return 0; 195e1051a39Sopenharmony_ci 196e1051a39Sopenharmony_ci if (bt == expected_type 197e1051a39Sopenharmony_ci /* as an answer to polling, there could be IP/CP/KUP: */ 198e1051a39Sopenharmony_ci || (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP)) 199e1051a39Sopenharmony_ci return 1; 200e1051a39Sopenharmony_ci 201e1051a39Sopenharmony_ci /* received message type is not one of the expected ones (e.g., error) */ 202e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, bt == OSSL_CMP_PKIBODY_ERROR ? CMP_R_RECEIVED_ERROR : 203e1051a39Sopenharmony_ci CMP_R_UNEXPECTED_PKIBODY); /* in next line for mkerr.pl */ 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ci if (bt != OSSL_CMP_PKIBODY_ERROR) { 206e1051a39Sopenharmony_ci ERR_add_error_data(3, "message type is '", 207e1051a39Sopenharmony_ci ossl_cmp_bodytype_to_string(bt), "'"); 208e1051a39Sopenharmony_ci } else { 209e1051a39Sopenharmony_ci OSSL_CMP_ERRORMSGCONTENT *emc = (*rep)->body->value.error; 210e1051a39Sopenharmony_ci OSSL_CMP_PKISI *si = emc->pKIStatusInfo; 211e1051a39Sopenharmony_ci char buf[OSSL_CMP_PKISI_BUFLEN]; 212e1051a39Sopenharmony_ci 213e1051a39Sopenharmony_ci if (save_statusInfo(ctx, si) 214e1051a39Sopenharmony_ci && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, 215e1051a39Sopenharmony_ci sizeof(buf)) != NULL) 216e1051a39Sopenharmony_ci ERR_add_error_data(1, buf); 217e1051a39Sopenharmony_ci if (emc->errorCode != NULL 218e1051a39Sopenharmony_ci && BIO_snprintf(buf, sizeof(buf), "; errorCode: %08lX", 219e1051a39Sopenharmony_ci ASN1_INTEGER_get(emc->errorCode)) > 0) 220e1051a39Sopenharmony_ci ERR_add_error_data(1, buf); 221e1051a39Sopenharmony_ci if (emc->errorDetails != NULL) { 222e1051a39Sopenharmony_ci char *text = ossl_sk_ASN1_UTF8STRING2text(emc->errorDetails, ", ", 223e1051a39Sopenharmony_ci OSSL_CMP_PKISI_BUFLEN - 1); 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_ci if (text != NULL && *text != '\0') 226e1051a39Sopenharmony_ci ERR_add_error_data(2, "; errorDetails: ", text); 227e1051a39Sopenharmony_ci OPENSSL_free(text); 228e1051a39Sopenharmony_ci } 229e1051a39Sopenharmony_ci if (ctx->status != OSSL_CMP_PKISTATUS_rejection) { 230e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS); 231e1051a39Sopenharmony_ci if (ctx->status == OSSL_CMP_PKISTATUS_waiting) 232e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_rejection; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci return 0; 236e1051a39Sopenharmony_ci} 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_ci/*- 239e1051a39Sopenharmony_ci * When a 'waiting' PKIStatus has been received, this function is used to 240e1051a39Sopenharmony_ci * poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup. 241e1051a39Sopenharmony_ci * On receiving a pollRep, which includes a checkAfter value, it return this 242e1051a39Sopenharmony_ci * value if sleep == 0, else it sleeps as long as indicated and retries. 243e1051a39Sopenharmony_ci * 244e1051a39Sopenharmony_ci * A transaction timeout is enabled if ctx->total_timeout is != 0. 245e1051a39Sopenharmony_ci * In this case polling will continue until the timeout is reached and then 246e1051a39Sopenharmony_ci * polling is done a last time even if this is before the "checkAfter" time. 247e1051a39Sopenharmony_ci * 248e1051a39Sopenharmony_ci * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value. 249e1051a39Sopenharmony_ci * Returns 1 on success and provides the received PKIMESSAGE in *rep. 250e1051a39Sopenharmony_ci * In this case the caller is responsible for freeing *rep. 251e1051a39Sopenharmony_ci * Returns 0 on error (which includes the case that timeout has been reached). 252e1051a39Sopenharmony_ci */ 253e1051a39Sopenharmony_cistatic int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, 254e1051a39Sopenharmony_ci OSSL_CMP_MSG **rep, int *checkAfter) 255e1051a39Sopenharmony_ci{ 256e1051a39Sopenharmony_ci OSSL_CMP_MSG *preq = NULL; 257e1051a39Sopenharmony_ci OSSL_CMP_MSG *prep = NULL; 258e1051a39Sopenharmony_ci 259e1051a39Sopenharmony_ci ossl_cmp_info(ctx, 260e1051a39Sopenharmony_ci "received 'waiting' PKIStatus, starting to poll for response"); 261e1051a39Sopenharmony_ci *rep = NULL; 262e1051a39Sopenharmony_ci for (;;) { 263e1051a39Sopenharmony_ci if ((preq = ossl_cmp_pollReq_new(ctx, rid)) == NULL) 264e1051a39Sopenharmony_ci goto err; 265e1051a39Sopenharmony_ci 266e1051a39Sopenharmony_ci if (!send_receive_check(ctx, preq, &prep, OSSL_CMP_PKIBODY_POLLREP)) 267e1051a39Sopenharmony_ci goto err; 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci /* handle potential pollRep */ 270e1051a39Sopenharmony_ci if (OSSL_CMP_MSG_get_bodytype(prep) == OSSL_CMP_PKIBODY_POLLREP) { 271e1051a39Sopenharmony_ci OSSL_CMP_POLLREPCONTENT *prc = prep->body->value.pollRep; 272e1051a39Sopenharmony_ci OSSL_CMP_POLLREP *pollRep = NULL; 273e1051a39Sopenharmony_ci int64_t check_after; 274e1051a39Sopenharmony_ci char str[OSSL_CMP_PKISI_BUFLEN]; 275e1051a39Sopenharmony_ci int len; 276e1051a39Sopenharmony_ci 277e1051a39Sopenharmony_ci if (sk_OSSL_CMP_POLLREP_num(prc) > 1) { 278e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED); 279e1051a39Sopenharmony_ci goto err; 280e1051a39Sopenharmony_ci } 281e1051a39Sopenharmony_ci pollRep = ossl_cmp_pollrepcontent_get0_pollrep(prc, rid); 282e1051a39Sopenharmony_ci if (pollRep == NULL) 283e1051a39Sopenharmony_ci goto err; 284e1051a39Sopenharmony_ci 285e1051a39Sopenharmony_ci if (!ASN1_INTEGER_get_int64(&check_after, pollRep->checkAfter)) { 286e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_BAD_CHECKAFTER_IN_POLLREP); 287e1051a39Sopenharmony_ci goto err; 288e1051a39Sopenharmony_ci } 289e1051a39Sopenharmony_ci if (check_after < 0 || (uint64_t)check_after 290e1051a39Sopenharmony_ci > (sleep ? ULONG_MAX / 1000 : INT_MAX)) { 291e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_CHECKAFTER_OUT_OF_RANGE); 292e1051a39Sopenharmony_ci if (BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN, "value = %jd", 293e1051a39Sopenharmony_ci check_after) >= 0) 294e1051a39Sopenharmony_ci ERR_add_error_data(1, str); 295e1051a39Sopenharmony_ci goto err; 296e1051a39Sopenharmony_ci } 297e1051a39Sopenharmony_ci 298e1051a39Sopenharmony_ci if (pollRep->reason == NULL 299e1051a39Sopenharmony_ci || (len = BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN, 300e1051a39Sopenharmony_ci " with reason = '")) < 0) { 301e1051a39Sopenharmony_ci *str = '\0'; 302e1051a39Sopenharmony_ci } else { 303e1051a39Sopenharmony_ci char *text = ossl_sk_ASN1_UTF8STRING2text(pollRep->reason, ", ", 304e1051a39Sopenharmony_ci sizeof(str) - len - 2); 305e1051a39Sopenharmony_ci 306e1051a39Sopenharmony_ci if (text == NULL 307e1051a39Sopenharmony_ci || BIO_snprintf(str + len, sizeof(str) - len, 308e1051a39Sopenharmony_ci "%s'", text) < 0) 309e1051a39Sopenharmony_ci *str = '\0'; 310e1051a39Sopenharmony_ci OPENSSL_free(text); 311e1051a39Sopenharmony_ci } 312e1051a39Sopenharmony_ci ossl_cmp_log2(INFO, ctx, 313e1051a39Sopenharmony_ci "received polling response%s; checkAfter = %ld seconds", 314e1051a39Sopenharmony_ci str, check_after); 315e1051a39Sopenharmony_ci 316e1051a39Sopenharmony_ci if (ctx->total_timeout != 0) { /* timeout is not infinite */ 317e1051a39Sopenharmony_ci const int exp = 5; /* expected max time per msg round trip */ 318e1051a39Sopenharmony_ci int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL)); 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci if (time_left <= 0) { 321e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT); 322e1051a39Sopenharmony_ci goto err; 323e1051a39Sopenharmony_ci } 324e1051a39Sopenharmony_ci if (time_left < check_after) 325e1051a39Sopenharmony_ci check_after = time_left; 326e1051a39Sopenharmony_ci /* poll one last time just when timeout was reached */ 327e1051a39Sopenharmony_ci } 328e1051a39Sopenharmony_ci 329e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(preq); 330e1051a39Sopenharmony_ci preq = NULL; 331e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(prep); 332e1051a39Sopenharmony_ci prep = NULL; 333e1051a39Sopenharmony_ci if (sleep) { 334e1051a39Sopenharmony_ci ossl_sleep((unsigned long)(1000 * check_after)); 335e1051a39Sopenharmony_ci } else { 336e1051a39Sopenharmony_ci if (checkAfter != NULL) 337e1051a39Sopenharmony_ci *checkAfter = (int)check_after; 338e1051a39Sopenharmony_ci return -1; /* exits the loop */ 339e1051a39Sopenharmony_ci } 340e1051a39Sopenharmony_ci } else { 341e1051a39Sopenharmony_ci ossl_cmp_info(ctx, "received ip/cp/kup after polling"); 342e1051a39Sopenharmony_ci /* any other body type has been rejected by send_receive_check() */ 343e1051a39Sopenharmony_ci break; 344e1051a39Sopenharmony_ci } 345e1051a39Sopenharmony_ci } 346e1051a39Sopenharmony_ci if (prep == NULL) 347e1051a39Sopenharmony_ci goto err; 348e1051a39Sopenharmony_ci 349e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(preq); 350e1051a39Sopenharmony_ci *rep = prep; 351e1051a39Sopenharmony_ci 352e1051a39Sopenharmony_ci return 1; 353e1051a39Sopenharmony_ci err: 354e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(preq); 355e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(prep); 356e1051a39Sopenharmony_ci return 0; 357e1051a39Sopenharmony_ci} 358e1051a39Sopenharmony_ci 359e1051a39Sopenharmony_ci/* 360e1051a39Sopenharmony_ci * Send certConf for IR, CR or KUR sequences and check response, 361e1051a39Sopenharmony_ci * not modifying ctx->status during the certConf exchange 362e1051a39Sopenharmony_ci */ 363e1051a39Sopenharmony_ciint ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId, 364e1051a39Sopenharmony_ci int fail_info, const char *txt) 365e1051a39Sopenharmony_ci{ 366e1051a39Sopenharmony_ci OSSL_CMP_MSG *certConf; 367e1051a39Sopenharmony_ci OSSL_CMP_MSG *PKIconf = NULL; 368e1051a39Sopenharmony_ci int res = 0; 369e1051a39Sopenharmony_ci 370e1051a39Sopenharmony_ci /* OSSL_CMP_certConf_new() also checks if all necessary options are set */ 371e1051a39Sopenharmony_ci certConf = ossl_cmp_certConf_new(ctx, certReqId, fail_info, txt); 372e1051a39Sopenharmony_ci if (certConf == NULL) 373e1051a39Sopenharmony_ci goto err; 374e1051a39Sopenharmony_ci 375e1051a39Sopenharmony_ci res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF); 376e1051a39Sopenharmony_ci 377e1051a39Sopenharmony_ci err: 378e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(certConf); 379e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(PKIconf); 380e1051a39Sopenharmony_ci return res; 381e1051a39Sopenharmony_ci} 382e1051a39Sopenharmony_ci 383e1051a39Sopenharmony_ci/* Send given error and check response */ 384e1051a39Sopenharmony_ciint ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info, 385e1051a39Sopenharmony_ci const char *txt, int errorCode, const char *details) 386e1051a39Sopenharmony_ci{ 387e1051a39Sopenharmony_ci OSSL_CMP_MSG *error = NULL; 388e1051a39Sopenharmony_ci OSSL_CMP_PKISI *si = NULL; 389e1051a39Sopenharmony_ci OSSL_CMP_MSG *PKIconf = NULL; 390e1051a39Sopenharmony_ci int res = 0; 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci /* not overwriting ctx->status on error exchange */ 393e1051a39Sopenharmony_ci if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt)) == NULL) 394e1051a39Sopenharmony_ci goto err; 395e1051a39Sopenharmony_ci /* ossl_cmp_error_new() also checks if all necessary options are set */ 396e1051a39Sopenharmony_ci if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL) 397e1051a39Sopenharmony_ci goto err; 398e1051a39Sopenharmony_ci 399e1051a39Sopenharmony_ci res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF); 400e1051a39Sopenharmony_ci 401e1051a39Sopenharmony_ci err: 402e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(error); 403e1051a39Sopenharmony_ci OSSL_CMP_PKISI_free(si); 404e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(PKIconf); 405e1051a39Sopenharmony_ci return res; 406e1051a39Sopenharmony_ci} 407e1051a39Sopenharmony_ci 408e1051a39Sopenharmony_ci/*- 409e1051a39Sopenharmony_ci * Retrieve a copy of the certificate, if any, from the given CertResponse. 410e1051a39Sopenharmony_ci * Take into account PKIStatusInfo of CertResponse in ctx, report it on error. 411e1051a39Sopenharmony_ci * Returns NULL if not found or on error. 412e1051a39Sopenharmony_ci */ 413e1051a39Sopenharmony_cistatic X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype, 414e1051a39Sopenharmony_ci OSSL_CMP_CERTRESPONSE *crep) 415e1051a39Sopenharmony_ci{ 416e1051a39Sopenharmony_ci char buf[OSSL_CMP_PKISI_BUFLEN]; 417e1051a39Sopenharmony_ci X509 *crt = NULL; 418e1051a39Sopenharmony_ci 419e1051a39Sopenharmony_ci if (!ossl_assert(ctx != NULL && crep != NULL)) 420e1051a39Sopenharmony_ci return NULL; 421e1051a39Sopenharmony_ci 422e1051a39Sopenharmony_ci switch (ossl_cmp_pkisi_get_status(crep->status)) { 423e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_waiting: 424e1051a39Sopenharmony_ci ossl_cmp_err(ctx, 425e1051a39Sopenharmony_ci "received \"waiting\" status for cert when actually aiming to extract cert"); 426e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_ENCOUNTERED_WAITING); 427e1051a39Sopenharmony_ci goto err; 428e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_grantedWithMods: 429e1051a39Sopenharmony_ci ossl_cmp_warn(ctx, "received \"grantedWithMods\" for certificate"); 430e1051a39Sopenharmony_ci break; 431e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_accepted: 432e1051a39Sopenharmony_ci break; 433e1051a39Sopenharmony_ci /* get all information in case of a rejection before going to error */ 434e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_rejection: 435e1051a39Sopenharmony_ci ossl_cmp_err(ctx, "received \"rejection\" status rather than cert"); 436e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_REJECTED_BY_SERVER); 437e1051a39Sopenharmony_ci goto err; 438e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_revocationWarning: 439e1051a39Sopenharmony_ci ossl_cmp_warn(ctx, 440e1051a39Sopenharmony_ci "received \"revocationWarning\" - a revocation of the cert is imminent"); 441e1051a39Sopenharmony_ci break; 442e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_revocationNotification: 443e1051a39Sopenharmony_ci ossl_cmp_warn(ctx, 444e1051a39Sopenharmony_ci "received \"revocationNotification\" - a revocation of the cert has occurred"); 445e1051a39Sopenharmony_ci break; 446e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_keyUpdateWarning: 447e1051a39Sopenharmony_ci if (bodytype != OSSL_CMP_PKIBODY_KUR) { 448e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_ENCOUNTERED_KEYUPDATEWARNING); 449e1051a39Sopenharmony_ci goto err; 450e1051a39Sopenharmony_ci } 451e1051a39Sopenharmony_ci break; 452e1051a39Sopenharmony_ci default: 453e1051a39Sopenharmony_ci ossl_cmp_log1(ERROR, ctx, 454e1051a39Sopenharmony_ci "received unsupported PKIStatus %d for certificate", 455e1051a39Sopenharmony_ci ctx->status); 456e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS); 457e1051a39Sopenharmony_ci goto err; 458e1051a39Sopenharmony_ci } 459e1051a39Sopenharmony_ci crt = ossl_cmp_certresponse_get1_cert(ctx, crep); 460e1051a39Sopenharmony_ci if (crt == NULL) /* according to PKIStatus, we can expect a cert */ 461e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND); 462e1051a39Sopenharmony_ci 463e1051a39Sopenharmony_ci return crt; 464e1051a39Sopenharmony_ci 465e1051a39Sopenharmony_ci err: 466e1051a39Sopenharmony_ci if (OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL) 467e1051a39Sopenharmony_ci ERR_add_error_data(1, buf); 468e1051a39Sopenharmony_ci return NULL; 469e1051a39Sopenharmony_ci} 470e1051a39Sopenharmony_ci 471e1051a39Sopenharmony_ci/*- 472e1051a39Sopenharmony_ci * Callback fn validating that the new certificate can be verified, using 473e1051a39Sopenharmony_ci * ctx->certConf_cb_arg, which has been initialized using opt_out_trusted, and 474e1051a39Sopenharmony_ci * ctx->untrusted, which at this point already contains msg->extraCerts. 475e1051a39Sopenharmony_ci * Returns 0 on acceptance, else a bit field reflecting PKIFailureInfo. 476e1051a39Sopenharmony_ci * Quoting from RFC 4210 section 5.1. Overall PKI Message: 477e1051a39Sopenharmony_ci * The extraCerts field can contain certificates that may be useful to 478e1051a39Sopenharmony_ci * the recipient. For example, this can be used by a CA or RA to 479e1051a39Sopenharmony_ci * present an end entity with certificates that it needs to verify its 480e1051a39Sopenharmony_ci * own new certificate (if, for example, the CA that issued the end 481e1051a39Sopenharmony_ci * entity's certificate is not a root CA for the end entity). Note that 482e1051a39Sopenharmony_ci * this field does not necessarily contain a certification path; the 483e1051a39Sopenharmony_ci * recipient may have to sort, select from, or otherwise process the 484e1051a39Sopenharmony_ci * extra certificates in order to use them. 485e1051a39Sopenharmony_ci * Note: While often handy, there is no hard requirement by CMP that 486e1051a39Sopenharmony_ci * an EE must be able to validate the certificates it gets enrolled. 487e1051a39Sopenharmony_ci */ 488e1051a39Sopenharmony_ciint OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, 489e1051a39Sopenharmony_ci const char **text) 490e1051a39Sopenharmony_ci{ 491e1051a39Sopenharmony_ci X509_STORE *out_trusted = OSSL_CMP_CTX_get_certConf_cb_arg(ctx); 492e1051a39Sopenharmony_ci STACK_OF(X509) *chain = NULL; 493e1051a39Sopenharmony_ci (void)text; /* make (artificial) use of var to prevent compiler warning */ 494e1051a39Sopenharmony_ci 495e1051a39Sopenharmony_ci if (fail_info != 0) /* accept any error flagged by CMP core library */ 496e1051a39Sopenharmony_ci return fail_info; 497e1051a39Sopenharmony_ci 498e1051a39Sopenharmony_ci if (out_trusted == NULL) { 499e1051a39Sopenharmony_ci ossl_cmp_debug(ctx, "trying to build chain for newly enrolled cert"); 500e1051a39Sopenharmony_ci chain = X509_build_chain(cert, ctx->untrusted, out_trusted, 501e1051a39Sopenharmony_ci 0, ctx->libctx, ctx->propq); 502e1051a39Sopenharmony_ci } else { 503e1051a39Sopenharmony_ci X509_STORE_CTX *csc = X509_STORE_CTX_new_ex(ctx->libctx, ctx->propq); 504e1051a39Sopenharmony_ci 505e1051a39Sopenharmony_ci ossl_cmp_debug(ctx, "validating newly enrolled cert"); 506e1051a39Sopenharmony_ci if (csc == NULL) 507e1051a39Sopenharmony_ci goto err; 508e1051a39Sopenharmony_ci if (!X509_STORE_CTX_init(csc, out_trusted, cert, ctx->untrusted)) 509e1051a39Sopenharmony_ci goto err; 510e1051a39Sopenharmony_ci /* disable any cert status/revocation checking etc. */ 511e1051a39Sopenharmony_ci X509_VERIFY_PARAM_clear_flags(X509_STORE_CTX_get0_param(csc), 512e1051a39Sopenharmony_ci ~(X509_V_FLAG_USE_CHECK_TIME 513e1051a39Sopenharmony_ci | X509_V_FLAG_NO_CHECK_TIME 514e1051a39Sopenharmony_ci | X509_V_FLAG_PARTIAL_CHAIN 515e1051a39Sopenharmony_ci | X509_V_FLAG_POLICY_CHECK)); 516e1051a39Sopenharmony_ci if (X509_verify_cert(csc) <= 0) 517e1051a39Sopenharmony_ci goto err; 518e1051a39Sopenharmony_ci 519e1051a39Sopenharmony_ci if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc), 520e1051a39Sopenharmony_ci X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP 521e1051a39Sopenharmony_ci | X509_ADD_FLAG_NO_SS)) { 522e1051a39Sopenharmony_ci sk_X509_free(chain); 523e1051a39Sopenharmony_ci chain = NULL; 524e1051a39Sopenharmony_ci } 525e1051a39Sopenharmony_ci err: 526e1051a39Sopenharmony_ci X509_STORE_CTX_free(csc); 527e1051a39Sopenharmony_ci } 528e1051a39Sopenharmony_ci 529e1051a39Sopenharmony_ci if (sk_X509_num(chain) > 0) 530e1051a39Sopenharmony_ci X509_free(sk_X509_shift(chain)); /* remove leaf (EE) cert */ 531e1051a39Sopenharmony_ci if (out_trusted != NULL) { 532e1051a39Sopenharmony_ci if (chain == NULL) { 533e1051a39Sopenharmony_ci ossl_cmp_err(ctx, "failed to validate newly enrolled cert"); 534e1051a39Sopenharmony_ci fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData; 535e1051a39Sopenharmony_ci } else { 536e1051a39Sopenharmony_ci ossl_cmp_debug(ctx, 537e1051a39Sopenharmony_ci "success validating newly enrolled cert"); 538e1051a39Sopenharmony_ci } 539e1051a39Sopenharmony_ci } else if (chain == NULL) { 540e1051a39Sopenharmony_ci ossl_cmp_warn(ctx, "could not build approximate chain for newly enrolled cert, resorting to received extraCerts"); 541e1051a39Sopenharmony_ci chain = OSSL_CMP_CTX_get1_extraCertsIn(ctx); 542e1051a39Sopenharmony_ci } else { 543e1051a39Sopenharmony_ci ossl_cmp_debug(ctx, 544e1051a39Sopenharmony_ci "success building approximate chain for newly enrolled cert"); 545e1051a39Sopenharmony_ci } 546e1051a39Sopenharmony_ci (void)ossl_cmp_ctx_set1_newChain(ctx, chain); 547e1051a39Sopenharmony_ci sk_X509_pop_free(chain, X509_free); 548e1051a39Sopenharmony_ci 549e1051a39Sopenharmony_ci return fail_info; 550e1051a39Sopenharmony_ci} 551e1051a39Sopenharmony_ci 552e1051a39Sopenharmony_ci/*- 553e1051a39Sopenharmony_ci * Perform the generic handling of certificate responses for IR/CR/KUR/P10CR. 554e1051a39Sopenharmony_ci * |rid| must be OSSL_CMP_CERTREQID_NONE if not available, namely for p10cr 555e1051a39Sopenharmony_ci * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value. 556e1051a39Sopenharmony_ci * Returns 1 on success and provides the received PKIMESSAGE in *resp. 557e1051a39Sopenharmony_ci * Returns 0 on error (which includes the case that timeout has been reached). 558e1051a39Sopenharmony_ci * Regardless of success, caller is responsible for freeing *resp (unless NULL). 559e1051a39Sopenharmony_ci */ 560e1051a39Sopenharmony_cistatic int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, 561e1051a39Sopenharmony_ci OSSL_CMP_MSG **resp, int *checkAfter, 562e1051a39Sopenharmony_ci int req_type, int expected_type) 563e1051a39Sopenharmony_ci{ 564e1051a39Sopenharmony_ci EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx); 565e1051a39Sopenharmony_ci int fail_info = 0; /* no failure */ 566e1051a39Sopenharmony_ci const char *txt = NULL; 567e1051a39Sopenharmony_ci OSSL_CMP_CERTREPMESSAGE *crepmsg; 568e1051a39Sopenharmony_ci OSSL_CMP_CERTRESPONSE *crep; 569e1051a39Sopenharmony_ci OSSL_CMP_certConf_cb_t cb; 570e1051a39Sopenharmony_ci X509 *cert; 571e1051a39Sopenharmony_ci char *subj = NULL; 572e1051a39Sopenharmony_ci int ret = 1; 573e1051a39Sopenharmony_ci 574e1051a39Sopenharmony_ci if (!ossl_assert(ctx != NULL)) 575e1051a39Sopenharmony_ci return 0; 576e1051a39Sopenharmony_ci 577e1051a39Sopenharmony_ci retry: 578e1051a39Sopenharmony_ci crepmsg = (*resp)->body->value.ip; /* same for cp and kup */ 579e1051a39Sopenharmony_ci if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) { 580e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED); 581e1051a39Sopenharmony_ci return 0; 582e1051a39Sopenharmony_ci } 583e1051a39Sopenharmony_ci crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid); 584e1051a39Sopenharmony_ci if (crep == NULL) 585e1051a39Sopenharmony_ci return 0; 586e1051a39Sopenharmony_ci if (!save_statusInfo(ctx, crep->status)) 587e1051a39Sopenharmony_ci return 0; 588e1051a39Sopenharmony_ci if (rid == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */ 589e1051a39Sopenharmony_ci rid = ossl_cmp_asn1_get_int(crep->certReqId); 590e1051a39Sopenharmony_ci if (rid != OSSL_CMP_CERTREQID_NONE) { 591e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); 592e1051a39Sopenharmony_ci return 0; 593e1051a39Sopenharmony_ci } 594e1051a39Sopenharmony_ci } 595e1051a39Sopenharmony_ci 596e1051a39Sopenharmony_ci if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) { 597e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(*resp); 598e1051a39Sopenharmony_ci *resp = NULL; 599e1051a39Sopenharmony_ci if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) { 600e1051a39Sopenharmony_ci if (ret == -1) /* at this point implies sleep == 0 */ 601e1051a39Sopenharmony_ci return ret; /* waiting */ 602e1051a39Sopenharmony_ci goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */ 603e1051a39Sopenharmony_ci } else { 604e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED); 605e1051a39Sopenharmony_ci return 0; 606e1051a39Sopenharmony_ci } 607e1051a39Sopenharmony_ci } 608e1051a39Sopenharmony_ci 609e1051a39Sopenharmony_ci cert = get1_cert_status(ctx, (*resp)->body->type, crep); 610e1051a39Sopenharmony_ci if (cert == NULL) { 611e1051a39Sopenharmony_ci ERR_add_error_data(1, "; cannot extract certificate from response"); 612e1051a39Sopenharmony_ci return 0; 613e1051a39Sopenharmony_ci } 614e1051a39Sopenharmony_ci if (!ossl_cmp_ctx_set0_newCert(ctx, cert)) 615e1051a39Sopenharmony_ci return 0; 616e1051a39Sopenharmony_ci 617e1051a39Sopenharmony_ci /* 618e1051a39Sopenharmony_ci * if the CMP server returned certificates in the caPubs field, copy them 619e1051a39Sopenharmony_ci * to the context so that they can be retrieved if necessary 620e1051a39Sopenharmony_ci */ 621e1051a39Sopenharmony_ci if (crepmsg->caPubs != NULL 622e1051a39Sopenharmony_ci && !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs)) 623e1051a39Sopenharmony_ci return 0; 624e1051a39Sopenharmony_ci 625e1051a39Sopenharmony_ci subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); 626e1051a39Sopenharmony_ci if (rkey != NULL 627e1051a39Sopenharmony_ci /* X509_check_private_key() also works if rkey is just public key */ 628e1051a39Sopenharmony_ci && !(X509_check_private_key(ctx->newCert, rkey))) { 629e1051a39Sopenharmony_ci fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData; 630e1051a39Sopenharmony_ci txt = "public key in new certificate does not match our enrollment key"; 631e1051a39Sopenharmony_ci /*- 632e1051a39Sopenharmony_ci * not calling (void)ossl_cmp_exchange_error(ctx, 633e1051a39Sopenharmony_ci * OSSL_CMP_PKISTATUS_rejection, fail_info, txt) 634e1051a39Sopenharmony_ci * not throwing CMP_R_CERTIFICATE_NOT_ACCEPTED with txt 635e1051a39Sopenharmony_ci * not returning 0 636e1051a39Sopenharmony_ci * since we better leave this for the certConf_cb to decide 637e1051a39Sopenharmony_ci */ 638e1051a39Sopenharmony_ci } 639e1051a39Sopenharmony_ci 640e1051a39Sopenharmony_ci /* 641e1051a39Sopenharmony_ci * Execute the certification checking callback function, 642e1051a39Sopenharmony_ci * which can determine whether to accept a newly enrolled certificate. 643e1051a39Sopenharmony_ci * It may overrule the pre-decision reflected in 'fail_info' and '*txt'. 644e1051a39Sopenharmony_ci */ 645e1051a39Sopenharmony_ci cb = ctx->certConf_cb != NULL ? ctx->certConf_cb : OSSL_CMP_certConf_cb; 646e1051a39Sopenharmony_ci if ((fail_info = cb(ctx, ctx->newCert, fail_info, &txt)) != 0 647e1051a39Sopenharmony_ci && txt == NULL) 648e1051a39Sopenharmony_ci txt = "CMP client did not accept it"; 649e1051a39Sopenharmony_ci if (fail_info != 0) /* immediately log error before any certConf exchange */ 650e1051a39Sopenharmony_ci ossl_cmp_log1(ERROR, ctx, 651e1051a39Sopenharmony_ci "rejecting newly enrolled cert with subject: %s", subj); 652e1051a39Sopenharmony_ci if (!ctx->disableConfirm 653e1051a39Sopenharmony_ci && !ossl_cmp_hdr_has_implicitConfirm((*resp)->header)) { 654e1051a39Sopenharmony_ci if (!ossl_cmp_exchange_certConf(ctx, rid, fail_info, txt)) 655e1051a39Sopenharmony_ci ret = 0; 656e1051a39Sopenharmony_ci } 657e1051a39Sopenharmony_ci 658e1051a39Sopenharmony_ci /* not throwing failure earlier as transfer_cb may call ERR_clear_error() */ 659e1051a39Sopenharmony_ci if (fail_info != 0) { 660e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_ACCEPTED, 661e1051a39Sopenharmony_ci "rejecting newly enrolled cert with subject: %s; %s", 662e1051a39Sopenharmony_ci subj, txt); 663e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_rejection; 664e1051a39Sopenharmony_ci ret = 0; 665e1051a39Sopenharmony_ci } 666e1051a39Sopenharmony_ci OPENSSL_free(subj); 667e1051a39Sopenharmony_ci return ret; 668e1051a39Sopenharmony_ci} 669e1051a39Sopenharmony_ci 670e1051a39Sopenharmony_cistatic int initial_certreq(OSSL_CMP_CTX *ctx, 671e1051a39Sopenharmony_ci int req_type, const OSSL_CRMF_MSG *crm, 672e1051a39Sopenharmony_ci OSSL_CMP_MSG **p_rep, int rep_type) 673e1051a39Sopenharmony_ci{ 674e1051a39Sopenharmony_ci OSSL_CMP_MSG *req; 675e1051a39Sopenharmony_ci int res; 676e1051a39Sopenharmony_ci 677e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_request; 678e1051a39Sopenharmony_ci if (!ossl_cmp_ctx_set0_newCert(ctx, NULL)) 679e1051a39Sopenharmony_ci return 0; 680e1051a39Sopenharmony_ci 681e1051a39Sopenharmony_ci /* also checks if all necessary options are set */ 682e1051a39Sopenharmony_ci if ((req = ossl_cmp_certreq_new(ctx, req_type, crm)) == NULL) 683e1051a39Sopenharmony_ci return 0; 684e1051a39Sopenharmony_ci 685e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_trans; 686e1051a39Sopenharmony_ci res = send_receive_check(ctx, req, p_rep, rep_type); 687e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(req); 688e1051a39Sopenharmony_ci return res; 689e1051a39Sopenharmony_ci} 690e1051a39Sopenharmony_ci 691e1051a39Sopenharmony_ciint OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, 692e1051a39Sopenharmony_ci const OSSL_CRMF_MSG *crm, int *checkAfter) 693e1051a39Sopenharmony_ci{ 694e1051a39Sopenharmony_ci OSSL_CMP_MSG *rep = NULL; 695e1051a39Sopenharmony_ci int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR; 696e1051a39Sopenharmony_ci int rid = is_p10 ? OSSL_CMP_CERTREQID_NONE : OSSL_CMP_CERTREQID; 697e1051a39Sopenharmony_ci int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1; 698e1051a39Sopenharmony_ci int res = 0; 699e1051a39Sopenharmony_ci 700e1051a39Sopenharmony_ci if (ctx == NULL) { 701e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 702e1051a39Sopenharmony_ci return 0; 703e1051a39Sopenharmony_ci } 704e1051a39Sopenharmony_ci 705e1051a39Sopenharmony_ci if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */ 706e1051a39Sopenharmony_ci if (!initial_certreq(ctx, req_type, crm, &rep, rep_type)) 707e1051a39Sopenharmony_ci goto err; 708e1051a39Sopenharmony_ci } else { 709e1051a39Sopenharmony_ci if (req_type < 0) 710e1051a39Sopenharmony_ci return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection, 711e1051a39Sopenharmony_ci 0, "polling aborted", 712e1051a39Sopenharmony_ci 0 /* errorCode */, "by application"); 713e1051a39Sopenharmony_ci res = poll_for_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter); 714e1051a39Sopenharmony_ci if (res <= 0) /* waiting or error */ 715e1051a39Sopenharmony_ci return res; 716e1051a39Sopenharmony_ci } 717e1051a39Sopenharmony_ci res = cert_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter, 718e1051a39Sopenharmony_ci req_type, rep_type); 719e1051a39Sopenharmony_ci 720e1051a39Sopenharmony_ci err: 721e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(rep); 722e1051a39Sopenharmony_ci return res; 723e1051a39Sopenharmony_ci} 724e1051a39Sopenharmony_ci 725e1051a39Sopenharmony_ci/*- 726e1051a39Sopenharmony_ci * Do the full sequence CR/IR/KUR/P10CR, CP/IP/KUP/CP, 727e1051a39Sopenharmony_ci * certConf, PKIconf, and polling if required. 728e1051a39Sopenharmony_ci * Will sleep as long as indicated by the server (according to checkAfter). 729e1051a39Sopenharmony_ci * All enrollment options need to be present in the context. 730e1051a39Sopenharmony_ci * Returns pointer to received certificate, or NULL if none was received. 731e1051a39Sopenharmony_ci */ 732e1051a39Sopenharmony_ciX509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type, 733e1051a39Sopenharmony_ci const OSSL_CRMF_MSG *crm) 734e1051a39Sopenharmony_ci{ 735e1051a39Sopenharmony_ci 736e1051a39Sopenharmony_ci OSSL_CMP_MSG *rep = NULL; 737e1051a39Sopenharmony_ci int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR; 738e1051a39Sopenharmony_ci int rid = is_p10 ? OSSL_CMP_CERTREQID_NONE : OSSL_CMP_CERTREQID; 739e1051a39Sopenharmony_ci int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1; 740e1051a39Sopenharmony_ci X509 *result = NULL; 741e1051a39Sopenharmony_ci 742e1051a39Sopenharmony_ci if (ctx == NULL) { 743e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 744e1051a39Sopenharmony_ci return NULL; 745e1051a39Sopenharmony_ci } 746e1051a39Sopenharmony_ci 747e1051a39Sopenharmony_ci if (!initial_certreq(ctx, req_type, crm, &rep, rep_type)) 748e1051a39Sopenharmony_ci goto err; 749e1051a39Sopenharmony_ci 750e1051a39Sopenharmony_ci if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type) 751e1051a39Sopenharmony_ci <= 0) 752e1051a39Sopenharmony_ci goto err; 753e1051a39Sopenharmony_ci 754e1051a39Sopenharmony_ci result = ctx->newCert; 755e1051a39Sopenharmony_ci err: 756e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(rep); 757e1051a39Sopenharmony_ci return result; 758e1051a39Sopenharmony_ci} 759e1051a39Sopenharmony_ci 760e1051a39Sopenharmony_ciint OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx) 761e1051a39Sopenharmony_ci{ 762e1051a39Sopenharmony_ci OSSL_CMP_MSG *rr = NULL; 763e1051a39Sopenharmony_ci OSSL_CMP_MSG *rp = NULL; 764e1051a39Sopenharmony_ci const int num_RevDetails = 1; 765e1051a39Sopenharmony_ci const int rsid = OSSL_CMP_REVREQSID; 766e1051a39Sopenharmony_ci OSSL_CMP_REVREPCONTENT *rrep = NULL; 767e1051a39Sopenharmony_ci OSSL_CMP_PKISI *si = NULL; 768e1051a39Sopenharmony_ci char buf[OSSL_CMP_PKISI_BUFLEN]; 769e1051a39Sopenharmony_ci int ret = 0; 770e1051a39Sopenharmony_ci 771e1051a39Sopenharmony_ci if (ctx == NULL) { 772e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS); 773e1051a39Sopenharmony_ci return 0; 774e1051a39Sopenharmony_ci } 775e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_request; 776e1051a39Sopenharmony_ci if (ctx->oldCert == NULL && ctx->p10CSR == NULL) { 777e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT); 778e1051a39Sopenharmony_ci return 0; 779e1051a39Sopenharmony_ci } 780e1051a39Sopenharmony_ci 781e1051a39Sopenharmony_ci /* OSSL_CMP_rr_new() also checks if all necessary options are set */ 782e1051a39Sopenharmony_ci if ((rr = ossl_cmp_rr_new(ctx)) == NULL) 783e1051a39Sopenharmony_ci goto end; 784e1051a39Sopenharmony_ci 785e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_trans; 786e1051a39Sopenharmony_ci if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP)) 787e1051a39Sopenharmony_ci goto end; 788e1051a39Sopenharmony_ci 789e1051a39Sopenharmony_ci rrep = rp->body->value.rp; 790e1051a39Sopenharmony_ci#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 791e1051a39Sopenharmony_ci if (sk_OSSL_CMP_PKISI_num(rrep->status) != num_RevDetails) { 792e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT); 793e1051a39Sopenharmony_ci goto end; 794e1051a39Sopenharmony_ci } 795e1051a39Sopenharmony_ci#else 796e1051a39Sopenharmony_ci if (sk_OSSL_CMP_PKISI_num(rrep->status) < 1) { 797e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT); 798e1051a39Sopenharmony_ci goto end; 799e1051a39Sopenharmony_ci } 800e1051a39Sopenharmony_ci#endif 801e1051a39Sopenharmony_ci 802e1051a39Sopenharmony_ci /* evaluate PKIStatus field */ 803e1051a39Sopenharmony_ci si = ossl_cmp_revrepcontent_get_pkisi(rrep, rsid); 804e1051a39Sopenharmony_ci if (!save_statusInfo(ctx, si)) 805e1051a39Sopenharmony_ci goto err; 806e1051a39Sopenharmony_ci switch (ossl_cmp_pkisi_get_status(si)) { 807e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_accepted: 808e1051a39Sopenharmony_ci ossl_cmp_info(ctx, "revocation accepted (PKIStatus=accepted)"); 809e1051a39Sopenharmony_ci ret = 1; 810e1051a39Sopenharmony_ci break; 811e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_grantedWithMods: 812e1051a39Sopenharmony_ci ossl_cmp_info(ctx, "revocation accepted (PKIStatus=grantedWithMods)"); 813e1051a39Sopenharmony_ci ret = 1; 814e1051a39Sopenharmony_ci break; 815e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_rejection: 816e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_REJECTED_BY_SERVER); 817e1051a39Sopenharmony_ci goto err; 818e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_revocationWarning: 819e1051a39Sopenharmony_ci ossl_cmp_info(ctx, "revocation accepted (PKIStatus=revocationWarning)"); 820e1051a39Sopenharmony_ci ret = 1; 821e1051a39Sopenharmony_ci break; 822e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_revocationNotification: 823e1051a39Sopenharmony_ci /* interpretation as warning or error depends on CA */ 824e1051a39Sopenharmony_ci ossl_cmp_warn(ctx, 825e1051a39Sopenharmony_ci "revocation accepted (PKIStatus=revocationNotification)"); 826e1051a39Sopenharmony_ci ret = 1; 827e1051a39Sopenharmony_ci break; 828e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_waiting: 829e1051a39Sopenharmony_ci case OSSL_CMP_PKISTATUS_keyUpdateWarning: 830e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS); 831e1051a39Sopenharmony_ci goto err; 832e1051a39Sopenharmony_ci default: 833e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS); 834e1051a39Sopenharmony_ci goto err; 835e1051a39Sopenharmony_ci } 836e1051a39Sopenharmony_ci 837e1051a39Sopenharmony_ci /* check any present CertId in optional revCerts field */ 838e1051a39Sopenharmony_ci if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) >= 1) { 839e1051a39Sopenharmony_ci OSSL_CRMF_CERTID *cid; 840e1051a39Sopenharmony_ci OSSL_CRMF_CERTTEMPLATE *tmpl = 841e1051a39Sopenharmony_ci sk_OSSL_CMP_REVDETAILS_value(rr->body->value.rr, rsid)->certDetails; 842e1051a39Sopenharmony_ci const X509_NAME *issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl); 843e1051a39Sopenharmony_ci const ASN1_INTEGER *serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl); 844e1051a39Sopenharmony_ci 845e1051a39Sopenharmony_ci if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) != num_RevDetails) { 846e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT); 847e1051a39Sopenharmony_ci ret = 0; 848e1051a39Sopenharmony_ci goto err; 849e1051a39Sopenharmony_ci } 850e1051a39Sopenharmony_ci if ((cid = ossl_cmp_revrepcontent_get_CertId(rrep, rsid)) == NULL) { 851e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CERTID); 852e1051a39Sopenharmony_ci ret = 0; 853e1051a39Sopenharmony_ci goto err; 854e1051a39Sopenharmony_ci } 855e1051a39Sopenharmony_ci if (X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) { 856e1051a39Sopenharmony_ci#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 857e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID_IN_RP); 858e1051a39Sopenharmony_ci ret = 0; 859e1051a39Sopenharmony_ci goto err; 860e1051a39Sopenharmony_ci#endif 861e1051a39Sopenharmony_ci } 862e1051a39Sopenharmony_ci if (ASN1_INTEGER_cmp(serial, 863e1051a39Sopenharmony_ci OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) { 864e1051a39Sopenharmony_ci#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 865e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_SERIAL_IN_RP); 866e1051a39Sopenharmony_ci ret = 0; 867e1051a39Sopenharmony_ci goto err; 868e1051a39Sopenharmony_ci#endif 869e1051a39Sopenharmony_ci } 870e1051a39Sopenharmony_ci } 871e1051a39Sopenharmony_ci 872e1051a39Sopenharmony_ci /* check number of any optionally present crls */ 873e1051a39Sopenharmony_ci if (rrep->crls != NULL && sk_X509_CRL_num(rrep->crls) != num_RevDetails) { 874e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT); 875e1051a39Sopenharmony_ci ret = 0; 876e1051a39Sopenharmony_ci goto err; 877e1051a39Sopenharmony_ci } 878e1051a39Sopenharmony_ci 879e1051a39Sopenharmony_ci err: 880e1051a39Sopenharmony_ci if (ret == 0 881e1051a39Sopenharmony_ci && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL) 882e1051a39Sopenharmony_ci ERR_add_error_data(1, buf); 883e1051a39Sopenharmony_ci 884e1051a39Sopenharmony_ci end: 885e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(rr); 886e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(rp); 887e1051a39Sopenharmony_ci return ret; 888e1051a39Sopenharmony_ci} 889e1051a39Sopenharmony_ci 890e1051a39Sopenharmony_ciSTACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx) 891e1051a39Sopenharmony_ci{ 892e1051a39Sopenharmony_ci OSSL_CMP_MSG *genm; 893e1051a39Sopenharmony_ci OSSL_CMP_MSG *genp = NULL; 894e1051a39Sopenharmony_ci STACK_OF(OSSL_CMP_ITAV) *itavs = NULL; 895e1051a39Sopenharmony_ci 896e1051a39Sopenharmony_ci if (ctx == NULL) { 897e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS); 898e1051a39Sopenharmony_ci return NULL; 899e1051a39Sopenharmony_ci } 900e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_request; 901e1051a39Sopenharmony_ci 902e1051a39Sopenharmony_ci if ((genm = ossl_cmp_genm_new(ctx)) == NULL) 903e1051a39Sopenharmony_ci goto err; 904e1051a39Sopenharmony_ci 905e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_trans; 906e1051a39Sopenharmony_ci if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP)) 907e1051a39Sopenharmony_ci goto err; 908e1051a39Sopenharmony_ci ctx->status = OSSL_CMP_PKISTATUS_accepted; 909e1051a39Sopenharmony_ci 910e1051a39Sopenharmony_ci itavs = genp->body->value.genp; 911e1051a39Sopenharmony_ci if (itavs == NULL) 912e1051a39Sopenharmony_ci itavs = sk_OSSL_CMP_ITAV_new_null(); 913e1051a39Sopenharmony_ci /* received stack of itavs not to be freed with the genp */ 914e1051a39Sopenharmony_ci genp->body->value.genp = NULL; 915e1051a39Sopenharmony_ci 916e1051a39Sopenharmony_ci err: 917e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(genm); 918e1051a39Sopenharmony_ci OSSL_CMP_MSG_free(genp); 919e1051a39Sopenharmony_ci 920e1051a39Sopenharmony_ci return itavs; /* NULL indicates error case */ 921e1051a39Sopenharmony_ci} 922