1 /* 2 * Copyright 2018-2021 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 also on valid requests */ 26 OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */ 27 int certReqId; /* id of last ir/cr/kur, used for polling */ 28 int pollCount; /* number of polls before actual cert response */ 29 int curr_pollCount; /* number of polls so far for current request */ 30 int checkAfterTime; /* time the client should wait between polling */ 31 } mock_srv_ctx; 32 33 34 static void mock_srv_ctx_free(mock_srv_ctx *ctx) 35 { 36 if (ctx == NULL) 37 return; 38 39 OSSL_CMP_PKISI_free(ctx->statusOut); 40 X509_free(ctx->certOut); 41 sk_X509_pop_free(ctx->chainOut, X509_free); 42 sk_X509_pop_free(ctx->caPubsOut, X509_free); 43 OSSL_CMP_MSG_free(ctx->certReq); 44 OPENSSL_free(ctx); 45 } 46 47 static mock_srv_ctx *mock_srv_ctx_new(void) 48 { 49 mock_srv_ctx *ctx = OPENSSL_zalloc(sizeof(mock_srv_ctx)); 50 51 if (ctx == NULL) 52 goto err; 53 54 if ((ctx->statusOut = OSSL_CMP_PKISI_new()) == NULL) 55 goto err; 56 57 ctx->certReqId = -1; 58 59 /* all other elements are initialized to 0 or NULL, respectively */ 60 return ctx; 61 err: 62 mock_srv_ctx_free(ctx); 63 return NULL; 64 } 65 66 int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert) 67 { 68 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 69 70 if (ctx == NULL) { 71 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 72 return 0; 73 } 74 if (cert == NULL || X509_up_ref(cert)) { 75 X509_free(ctx->certOut); 76 ctx->certOut = cert; 77 return 1; 78 } 79 return 0; 80 } 81 82 int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, 83 STACK_OF(X509) *chain) 84 { 85 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 86 STACK_OF(X509) *chain_copy = NULL; 87 88 if (ctx == NULL) { 89 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 90 return 0; 91 } 92 if (chain != NULL && (chain_copy = X509_chain_up_ref(chain)) == NULL) 93 return 0; 94 sk_X509_pop_free(ctx->chainOut, X509_free); 95 ctx->chainOut = chain_copy; 96 return 1; 97 } 98 99 int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, 100 STACK_OF(X509) *caPubs) 101 { 102 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 103 STACK_OF(X509) *caPubs_copy = NULL; 104 105 if (ctx == NULL) { 106 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 107 return 0; 108 } 109 if (caPubs != NULL && (caPubs_copy = X509_chain_up_ref(caPubs)) == NULL) 110 return 0; 111 sk_X509_pop_free(ctx->caPubsOut, X509_free); 112 ctx->caPubsOut = caPubs_copy; 113 return 1; 114 } 115 116 int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status, 117 int fail_info, const char *text) 118 { 119 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 120 OSSL_CMP_PKISI *si; 121 122 if (ctx == NULL) { 123 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 124 return 0; 125 } 126 if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, text)) == NULL) 127 return 0; 128 OSSL_CMP_PKISI_free(ctx->statusOut); 129 ctx->statusOut = si; 130 return 1; 131 } 132 133 int ossl_cmp_mock_srv_set_send_error(OSSL_CMP_SRV_CTX *srv_ctx, int val) 134 { 135 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 136 137 if (ctx == NULL) { 138 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 139 return 0; 140 } 141 ctx->sendError = val != 0; 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 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) { 191 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 192 return NULL; 193 } 194 195 *certOut = NULL; 196 *chainOut = NULL; 197 *caPubs = NULL; 198 ctx->certReqId = certReqId; 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->sendError || ctx->certOut == NULL) { 274 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 275 return NULL; 276 } 277 278 /* Allow any RR derived from CSR, which may include subject and serial */ 279 if (issuer == NULL || serial == NULL) 280 return OSSL_CMP_PKISI_dup(ctx->statusOut); 281 282 /* accept revocation only for the certificate we sent in ir/cr/kur */ 283 if (X509_NAME_cmp(issuer, X509_get_issuer_name(ctx->certOut)) != 0 284 || ASN1_INTEGER_cmp(serial, 285 X509_get0_serialNumber(ctx->certOut)) != 0) { 286 ERR_raise_data(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED, 287 "wrong certificate to revoke"); 288 return NULL; 289 } 290 return OSSL_CMP_PKISI_dup(ctx->statusOut); 291 } 292 293 static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx, 294 const OSSL_CMP_MSG *genm, 295 const STACK_OF(OSSL_CMP_ITAV) *in, 296 STACK_OF(OSSL_CMP_ITAV) **out) 297 { 298 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 299 300 if (ctx == NULL || genm == NULL || in == NULL || out == NULL) { 301 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 302 return 0; 303 } 304 if (sk_OSSL_CMP_ITAV_num(in) > 1 || ctx->sendError) { 305 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 306 return 0; 307 } 308 309 *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup, 310 OSSL_CMP_ITAV_free); 311 return *out != NULL; 312 } 313 314 static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error, 315 const OSSL_CMP_PKISI *statusInfo, 316 const ASN1_INTEGER *errorCode, 317 const OSSL_CMP_PKIFREETEXT *errorDetails) 318 { 319 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 320 char buf[OSSL_CMP_PKISI_BUFLEN]; 321 char *sibuf; 322 int i; 323 324 if (ctx == NULL || error == NULL) { 325 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 326 return; 327 } 328 329 BIO_printf(bio_err, "mock server received error:\n"); 330 331 if (statusInfo == NULL) { 332 BIO_printf(bio_err, "pkiStatusInfo absent\n"); 333 } else { 334 sibuf = OSSL_CMP_snprint_PKIStatusInfo(statusInfo, buf, sizeof(buf)); 335 BIO_printf(bio_err, "pkiStatusInfo: %s\n", 336 sibuf != NULL ? sibuf: "<invalid>"); 337 } 338 339 if (errorCode == NULL) 340 BIO_printf(bio_err, "errorCode absent\n"); 341 else 342 BIO_printf(bio_err, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode)); 343 344 if (sk_ASN1_UTF8STRING_num(errorDetails) <= 0) { 345 BIO_printf(bio_err, "errorDetails absent\n"); 346 } else { 347 BIO_printf(bio_err, "errorDetails: "); 348 for (i = 0; i < sk_ASN1_UTF8STRING_num(errorDetails); i++) { 349 if (i > 0) 350 BIO_printf(bio_err, ", "); 351 BIO_printf(bio_err, "\""); 352 ASN1_STRING_print(bio_err, 353 sk_ASN1_UTF8STRING_value(errorDetails, i)); 354 BIO_printf(bio_err, "\""); 355 } 356 BIO_printf(bio_err, "\n"); 357 } 358 } 359 360 static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, 361 const OSSL_CMP_MSG *certConf, int certReqId, 362 const ASN1_OCTET_STRING *certHash, 363 const OSSL_CMP_PKISI *si) 364 { 365 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 366 ASN1_OCTET_STRING *digest; 367 368 if (ctx == NULL || certConf == NULL || certHash == NULL) { 369 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 370 return 0; 371 } 372 if (ctx->sendError || ctx->certOut == NULL) { 373 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 374 return 0; 375 } 376 377 if (certReqId != ctx->certReqId) { 378 /* in case of error, invalid reqId -1 */ 379 ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); 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, int certReqId, 396 OSSL_CMP_MSG **certReq, int64_t *check_after) 397 { 398 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); 399 400 if (ctx == NULL || pollReq == NULL 401 || certReq == NULL || check_after == NULL) { 402 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); 403 return 0; 404 } 405 if (ctx->sendError) { 406 *certReq = NULL; 407 ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); 408 return 0; 409 } 410 if (ctx->certReq == NULL) { 411 /* not currently in polling mode */ 412 *certReq = NULL; 413 ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); 414 return 0; 415 } 416 417 if (++ctx->curr_pollCount >= ctx->pollCount) { 418 /* end polling */ 419 *certReq = ctx->certReq; 420 ctx->certReq = NULL; 421 *check_after = 0; 422 } else { 423 *certReq = NULL; 424 *check_after = ctx->checkAfterTime; 425 } 426 return 1; 427 } 428 429 OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq) 430 { 431 OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_SRV_CTX_new(libctx, propq); 432 mock_srv_ctx *ctx = mock_srv_ctx_new(); 433 434 if (srv_ctx != NULL && ctx != NULL 435 && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request, 436 process_rr, process_genm, process_error, 437 process_certConf, process_pollReq)) 438 return srv_ctx; 439 440 mock_srv_ctx_free(ctx); 441 OSSL_CMP_SRV_CTX_free(srv_ctx); 442 return NULL; 443 } 444 445 void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx) 446 { 447 if (srv_ctx != NULL) 448 mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx)); 449 OSSL_CMP_SRV_CTX_free(srv_ctx); 450 } 451