1 /* 2 * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright Siemens AG 2018-2020 4 * 5 * Licensed under the Apache License 2.0 (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or atf 8 * https://www.openssl.org/source/license.html 9 */ 10 11 #include "apps.h" 12 #include "cmp_mock_srv.h" 13 14 #include <openssl/cmp.h> 15 #include <openssl/err.h> 16 #include <openssl/cmperr.h> 17 18 /* the context for the CMP mock server */ 19 typedef struct 20 { 21 X509 *certOut; /* certificate to be returned in cp/ip/kup msg */ 22 STACK_OF(X509) *chainOut; /* chain of certOut to add to extraCerts field */ 23 STACK_OF(X509) *caPubsOut; /* certs to return in caPubs field of ip msg */ 24 OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */ 25 int sendError; /* send error response on given request type */ 26 OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */ 27 int pollCount; /* number of polls before actual cert response */ 28 int curr_pollCount; /* number of polls so far for current request */ 29 int checkAfterTime; /* time the client should wait between polling */ 30 } mock_srv_ctx; 31 32 33 static void mock_srv_ctx_free(mock_srv_ctx *ctx) 34 { 35 if (ctx == NULL) 36 return; 37 38 OSSL_CMP_PKISI_free(ctx->statusOut); 39 X509_free(ctx->certOut); 40 sk_X509_pop_free(ctx->chainOut, X509_free); 41 sk_X509_pop_free(ctx->caPubsOut, X509_free); 42 OSSL_CMP_MSG_free(ctx->certReq); 43 OPENSSL_free(ctx); 44 } 45 46 static mock_srv_ctx *mock_srv_ctx_new(void) 47 { 48 mock_srv_ctx *ctx = OPENSSL_zalloc(sizeof(mock_srv_ctx)); 49 50 if (ctx == NULL) 51 goto err; 52 53 if ((ctx->statusOut = OSSL_CMP_PKISI_new()) == NULL) 54 goto err; 55 56 ctx->sendError = -1; 57 58 /* all other elements are initialized to 0 or NULL, respectively */ 59 return ctx; 60 err: 61 mock_srv_ctx_free(ctx); 62 return NULL; 63 } 64 65 int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert) 66 { 67 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 68 69 if (ctx == NULL) { 70 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 71 return 0; 72 } 73 if (cert == NULL || X509_up_ref(cert)) { 74 X509_free(ctx->certOut); 75 ctx->certOut = cert; 76 return 1; 77 } 78 return 0; 79 } 80 81 int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, 82 STACK_OF(X509) *chain) 83 { 84 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 85 STACK_OF(X509) *chain_copy = NULL; 86 87 if (ctx == NULL) { 88 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 89 return 0; 90 } 91 if (chain != NULL && (chain_copy = X509_chain_up_ref(chain)) == NULL) 92 return 0; 93 sk_X509_pop_free(ctx->chainOut, X509_free); 94 ctx->chainOut = chain_copy; 95 return 1; 96 } 97 98 int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, 99 STACK_OF(X509) *caPubs) 100 { 101 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 102 STACK_OF(X509) *caPubs_copy = NULL; 103 104 if (ctx == NULL) { 105 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 106 return 0; 107 } 108 if (caPubs != NULL && (caPubs_copy = X509_chain_up_ref(caPubs)) == NULL) 109 return 0; 110 sk_X509_pop_free(ctx->caPubsOut, X509_free); 111 ctx->caPubsOut = caPubs_copy; 112 return 1; 113 } 114 115 int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status, 116 int fail_info, const char *text) 117 { 118 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 119 OSSL_CMP_PKISI *si; 120 121 if (ctx == NULL) { 122 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 123 return 0; 124 } 125 if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, text)) == NULL) 126 return 0; 127 OSSL_CMP_PKISI_free(ctx->statusOut); 128 ctx->statusOut = si; 129 return 1; 130 } 131 132 int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype) 133 { 134 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 135 136 if (ctx == NULL) { 137 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 138 return 0; 139 } 140 /* might check bodytype, but this would require exporting all body types */ 141 ctx->sendError = bodytype; 142 return 1; 143 } 144 145 int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count) 146 { 147 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 148 149 if (ctx == NULL) { 150 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 151 return 0; 152 } 153 if (count < 0) { 154 ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ARGS); 155 return 0; 156 } 157 ctx->pollCount = count; 158 return 1; 159 } 160 161 int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec) 162 { 163 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 164 165 if (ctx == NULL) { 166 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 167 return 0; 168 } 169 ctx->checkAfterTime = sec; 170 return 1; 171 } 172 173 static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, 174 const OSSL_CMP_MSG *cert_req, 175 ossl_unused int certReqId, 176 const OSSL_CRMF_MSG *crm, 177 const X509_REQ *p10cr, 178 X509 **certOut, 179 STACK_OF(X509) **chainOut, 180 STACK_OF(X509) **caPubs) 181 { 182 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 183 OSSL_CMP_PKISI *si = NULL; 184 185 if (ctx == NULL || cert_req == NULL 186 || certOut == NULL || chainOut == NULL || caPubs == NULL) { 187 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 188 return NULL; 189 } 190 if (ctx->sendError == 1 191 || ctx->sendError == OSSL_CMP_MSG_get_bodytype(cert_req)) { 192 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 193 return NULL; 194 } 195 196 *certOut = NULL; 197 *chainOut = NULL; 198 *caPubs = NULL; 199 200 if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) { 201 /* start polling */ 202 if (ctx->certReq != NULL) { 203 /* already in polling mode */ 204 ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); 205 return NULL; 206 } 207 if ((ctx->certReq = OSSL_CMP_MSG_dup(cert_req)) == NULL) 208 return NULL; 209 return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL); 210 } 211 if (ctx->curr_pollCount >= ctx->pollCount) 212 /* give final response after polling */ 213 ctx->curr_pollCount = 0; 214 215 if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_KUR 216 && crm != NULL && ctx->certOut != NULL) { 217 const OSSL_CRMF_CERTID *cid = OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm); 218 const X509_NAME *issuer = X509_get_issuer_name(ctx->certOut); 219 const ASN1_INTEGER *serial = X509_get0_serialNumber(ctx->certOut); 220 221 if (cid == NULL) { 222 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CERTID); 223 return NULL; 224 } 225 if (issuer != NULL 226 && X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) { 227 ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID); 228 return NULL; 229 } 230 if (serial != NULL 231 && ASN1_INTEGER_cmp(serial, 232 OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) { 233 ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID); 234 return NULL; 235 } 236 } 237 238 if (ctx->certOut != NULL 239 && (*certOut = X509_dup(ctx->certOut)) == NULL) 240 goto err; 241 if (ctx->chainOut != NULL 242 && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL) 243 goto err; 244 if (ctx->caPubsOut != NULL 245 && (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL) 246 goto err; 247 if (ctx->statusOut != NULL 248 && (si = OSSL_CMP_PKISI_dup(ctx->statusOut)) == NULL) 249 goto err; 250 return si; 251 252 err: 253 X509_free(*certOut); 254 *certOut = NULL; 255 sk_X509_pop_free(*chainOut, X509_free); 256 *chainOut = NULL; 257 sk_X509_pop_free(*caPubs, X509_free); 258 *caPubs = NULL; 259 return NULL; 260 } 261 262 static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, 263 const OSSL_CMP_MSG *rr, 264 const X509_NAME *issuer, 265 const ASN1_INTEGER *serial) 266 { 267 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 268 269 if (ctx == NULL || rr == NULL) { 270 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 271 return NULL; 272 } 273 if (ctx->certOut == NULL || ctx->sendError == 1 274 || ctx->sendError == OSSL_CMP_MSG_get_bodytype(rr)) { 275 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 276 return NULL; 277 } 278 279 /* Allow any RR derived from CSR, which may include subject and serial */ 280 if (issuer == NULL || serial == NULL) 281 return OSSL_CMP_PKISI_dup(ctx->statusOut); 282 283 /* accept revocation only for the certificate we sent in ir/cr/kur */ 284 if (X509_NAME_cmp(issuer, X509_get_issuer_name(ctx->certOut)) != 0 285 || ASN1_INTEGER_cmp(serial, 286 X509_get0_serialNumber(ctx->certOut)) != 0) { 287 ERR_raise_data(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED, 288 "wrong certificate to revoke"); 289 return NULL; 290 } 291 return OSSL_CMP_PKISI_dup(ctx->statusOut); 292 } 293 294 static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx, 295 const OSSL_CMP_MSG *genm, 296 const STACK_OF(OSSL_CMP_ITAV) *in, 297 STACK_OF(OSSL_CMP_ITAV) **out) 298 { 299 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 300 301 if (ctx == NULL || genm == NULL || in == NULL || out == NULL) { 302 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 303 return 0; 304 } 305 if (ctx->sendError == 1 306 || ctx->sendError == OSSL_CMP_MSG_get_bodytype(genm) 307 || sk_OSSL_CMP_ITAV_num(in) > 1) { 308 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 309 return 0; 310 } 311 312 *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup, 313 OSSL_CMP_ITAV_free); 314 return *out != NULL; 315 } 316 317 static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error, 318 const OSSL_CMP_PKISI *statusInfo, 319 const ASN1_INTEGER *errorCode, 320 const OSSL_CMP_PKIFREETEXT *errorDetails) 321 { 322 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 323 char buf[OSSL_CMP_PKISI_BUFLEN]; 324 char *sibuf; 325 int i; 326 327 if (ctx == NULL || error == NULL) { 328 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 329 return; 330 } 331 332 BIO_printf(bio_err, "mock server received error:\n"); 333 334 if (statusInfo == NULL) { 335 BIO_printf(bio_err, "pkiStatusInfo absent\n"); 336 } else { 337 sibuf = OSSL_CMP_snprint_PKIStatusInfo(statusInfo, buf, sizeof(buf)); 338 BIO_printf(bio_err, "pkiStatusInfo: %s\n", 339 sibuf != NULL ? sibuf: "<invalid>"); 340 } 341 342 if (errorCode == NULL) 343 BIO_printf(bio_err, "errorCode absent\n"); 344 else 345 BIO_printf(bio_err, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode)); 346 347 if (sk_ASN1_UTF8STRING_num(errorDetails) <= 0) { 348 BIO_printf(bio_err, "errorDetails absent\n"); 349 } else { 350 BIO_printf(bio_err, "errorDetails: "); 351 for (i = 0; i < sk_ASN1_UTF8STRING_num(errorDetails); i++) { 352 if (i > 0) 353 BIO_printf(bio_err, ", "); 354 BIO_printf(bio_err, "\""); 355 ASN1_STRING_print(bio_err, 356 sk_ASN1_UTF8STRING_value(errorDetails, i)); 357 BIO_printf(bio_err, "\""); 358 } 359 BIO_printf(bio_err, "\n"); 360 } 361 } 362 363 static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, 364 const OSSL_CMP_MSG *certConf, 365 ossl_unused int certReqId, 366 const ASN1_OCTET_STRING *certHash, 367 const OSSL_CMP_PKISI *si) 368 { 369 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 370 ASN1_OCTET_STRING *digest; 371 372 if (ctx == NULL || certConf == NULL || certHash == NULL) { 373 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 374 return 0; 375 } 376 if (ctx->sendError == 1 377 || ctx->sendError == OSSL_CMP_MSG_get_bodytype(certConf) 378 || ctx->certOut == NULL) { 379 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 380 return 0; 381 } 382 383 if ((digest = X509_digest_sig(ctx->certOut, NULL, NULL)) == NULL) 384 return 0; 385 if (ASN1_OCTET_STRING_cmp(certHash, digest) != 0) { 386 ASN1_OCTET_STRING_free(digest); 387 ERR_raise(ERR_LIB_CMP, CMP_R_CERTHASH_UNMATCHED); 388 return 0; 389 } 390 ASN1_OCTET_STRING_free(digest); 391 return 1; 392 } 393 394 static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, 395 const OSSL_CMP_MSG *pollReq, 396 ossl_unused int certReqId, 397 OSSL_CMP_MSG **certReq, int64_t *check_after) 398 { 399 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 400 401 if (ctx == NULL || pollReq == NULL 402 || certReq == NULL || check_after == NULL) { 403 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 404 return 0; 405 } 406 if (ctx->sendError == 1 407 || ctx->sendError == OSSL_CMP_MSG_get_bodytype(pollReq)) { 408 *certReq = NULL; 409 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 410 return 0; 411 } 412 if (ctx->certReq == NULL) { 413 /* not currently in polling mode */ 414 *certReq = NULL; 415 ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); 416 return 0; 417 } 418 419 if (++ctx->curr_pollCount >= ctx->pollCount) { 420 /* end polling */ 421 *certReq = ctx->certReq; 422 ctx->certReq = NULL; 423 *check_after = 0; 424 } else { 425 *certReq = NULL; 426 *check_after = ctx->checkAfterTime; 427 } 428 return 1; 429 } 430 431 OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq) 432 { 433 OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_SRV_CTX_new(libctx, propq); 434 mock_srv_ctx *ctx = mock_srv_ctx_new(); 435 436 if (srv_ctx != NULL && ctx != NULL 437 && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request, 438 process_rr, process_genm, process_error, 439 process_certConf, process_pollReq)) 440 return srv_ctx; 441 442 mock_srv_ctx_free(ctx); 443 OSSL_CMP_SRV_CTX_free(srv_ctx); 444 return NULL; 445 } 446 447 void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx) 448 { 449 if (srv_ctx != NULL) 450 mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx)); 451 OSSL_CMP_SRV_CTX_free(srv_ctx); 452 } 453