2 * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright Siemens AG 2018-2020
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
12 #include "cmp_mock_srv.h"
14 #include <openssl/cmp.h>
15 #include <openssl/err.h>
16 #include <openssl/cmperr.h>
18 /* the context for the CMP mock server */
21 X509
*refCert
; /* cert to expect for oldCertID in kur/rr msg */
22 X509
*certOut
; /* certificate to be returned in cp/ip/kup msg */
23 STACK_OF(X509
) *chainOut
; /* chain of certOut to add to extraCerts field */
24 STACK_OF(X509
) *caPubsOut
; /* used in caPubs of ip and in caCerts of genp */
25 X509
*newWithNew
; /* to return in newWithNew of rootKeyUpdate */
26 X509
*newWithOld
; /* to return in newWithOld of rootKeyUpdate */
27 X509
*oldWithNew
; /* to return in oldWithNew of rootKeyUpdate */
28 OSSL_CMP_PKISI
*statusOut
; /* status for ip/cp/kup/rp msg unless polling */
29 int sendError
; /* send error response on given request type */
30 OSSL_CMP_MSG
*req
; /* original request message during polling */
31 int pollCount
; /* number of polls before actual cert response */
32 int curr_pollCount
; /* number of polls so far for current request */
33 int checkAfterTime
; /* time the client should wait between polling */
36 static void mock_srv_ctx_free(mock_srv_ctx
*ctx
)
41 OSSL_CMP_PKISI_free(ctx
->statusOut
);
42 X509_free(ctx
->refCert
);
43 X509_free(ctx
->certOut
);
44 OSSL_STACK_OF_X509_free(ctx
->chainOut
);
45 OSSL_STACK_OF_X509_free(ctx
->caPubsOut
);
46 OSSL_CMP_MSG_free(ctx
->req
);
50 static mock_srv_ctx
*mock_srv_ctx_new(void)
52 mock_srv_ctx
*ctx
= OPENSSL_zalloc(sizeof(mock_srv_ctx
));
57 if ((ctx
->statusOut
= OSSL_CMP_PKISI_new()) == NULL
)
62 /* all other elements are initialized to 0 or NULL, respectively */
65 mock_srv_ctx_free(ctx
);
69 #define DEFINE_OSSL_SET1_CERT(FIELD) \
70 int ossl_cmp_mock_srv_set1_##FIELD(OSSL_CMP_SRV_CTX *srv_ctx, \
73 mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); \
76 ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
79 if (cert == NULL || X509_up_ref(cert)) { \
80 X509_free(ctx->FIELD); \
87 DEFINE_OSSL_SET1_CERT(refCert
)
88 DEFINE_OSSL_SET1_CERT(certOut
)
90 int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX
*srv_ctx
,
91 STACK_OF(X509
) *chain
)
93 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
94 STACK_OF(X509
) *chain_copy
= NULL
;
97 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
100 if (chain
!= NULL
&& (chain_copy
= X509_chain_up_ref(chain
)) == NULL
)
102 OSSL_STACK_OF_X509_free(ctx
->chainOut
);
103 ctx
->chainOut
= chain_copy
;
107 int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX
*srv_ctx
,
108 STACK_OF(X509
) *caPubs
)
110 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
111 STACK_OF(X509
) *caPubs_copy
= NULL
;
114 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
117 if (caPubs
!= NULL
&& (caPubs_copy
= X509_chain_up_ref(caPubs
)) == NULL
)
119 OSSL_STACK_OF_X509_free(ctx
->caPubsOut
);
120 ctx
->caPubsOut
= caPubs_copy
;
124 DEFINE_OSSL_SET1_CERT(newWithNew
)
125 DEFINE_OSSL_SET1_CERT(newWithOld
)
126 DEFINE_OSSL_SET1_CERT(oldWithNew
)
128 int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX
*srv_ctx
, int status
,
129 int fail_info
, const char *text
)
131 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
135 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
138 if ((si
= OSSL_CMP_STATUSINFO_new(status
, fail_info
, text
)) == NULL
)
140 OSSL_CMP_PKISI_free(ctx
->statusOut
);
145 int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX
*srv_ctx
, int bodytype
)
147 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
150 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
153 /* might check bodytype, but this would require exporting all body types */
154 ctx
->sendError
= bodytype
;
158 int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX
*srv_ctx
, int count
)
160 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
163 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
167 ERR_raise(ERR_LIB_CMP
, CMP_R_INVALID_ARGS
);
170 ctx
->pollCount
= count
;
174 int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX
*srv_ctx
, int sec
)
176 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
179 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
182 ctx
->checkAfterTime
= sec
;
186 /* determine whether to delay response to (non-polling) request */
187 static int delayed_delivery(OSSL_CMP_SRV_CTX
*srv_ctx
, const OSSL_CMP_MSG
*req
)
189 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
190 int req_type
= OSSL_CMP_MSG_get_bodytype(req
);
192 if (ctx
== NULL
|| req
== NULL
) {
193 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
198 * For ir/cr/p10cr/kur delayed delivery is handled separately in
199 * process_cert_request
201 if (req_type
== OSSL_CMP_IR
202 || req_type
== OSSL_CMP_CR
203 || req_type
== OSSL_CMP_P10CR
204 || req_type
== OSSL_CMP_KUR
205 /* Client may use error to abort the ongoing polling */
206 || req_type
== OSSL_CMP_ERROR
)
209 if (ctx
->pollCount
> 0 && ctx
->curr_pollCount
== 0) {
211 if (ctx
->req
!= NULL
) { /* TODO: move this check to cmp_server.c */
212 /* already in polling mode */
213 ERR_raise(ERR_LIB_CMP
, CMP_R_UNEXPECTED_PKIBODY
);
216 if ((ctx
->req
= OSSL_CMP_MSG_dup(req
)) == NULL
)
223 /* check for matching reference cert components, as far as given */
224 static int refcert_cmp(const X509
*refcert
,
225 const X509_NAME
*issuer
, const ASN1_INTEGER
*serial
)
227 const X509_NAME
*ref_issuer
;
228 const ASN1_INTEGER
*ref_serial
;
232 ref_issuer
= X509_get_issuer_name(refcert
);
233 ref_serial
= X509_get0_serialNumber(refcert
);
234 return (ref_issuer
== NULL
|| X509_NAME_cmp(issuer
, ref_issuer
) == 0)
235 && (ref_serial
== NULL
|| ASN1_INTEGER_cmp(serial
, ref_serial
) == 0);
238 /* reset the state that belongs to a transaction */
239 static int clean_transaction(OSSL_CMP_SRV_CTX
*srv_ctx
,
240 ossl_unused
const ASN1_OCTET_STRING
*id
)
242 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
245 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
249 ctx
->curr_pollCount
= 0;
250 OSSL_CMP_MSG_free(ctx
->req
);
255 static OSSL_CMP_PKISI
*process_cert_request(OSSL_CMP_SRV_CTX
*srv_ctx
,
256 const OSSL_CMP_MSG
*cert_req
,
257 ossl_unused
int certReqId
,
258 const OSSL_CRMF_MSG
*crm
,
259 const X509_REQ
*p10cr
,
261 STACK_OF(X509
) **chainOut
,
262 STACK_OF(X509
) **caPubs
)
264 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
266 OSSL_CMP_PKISI
*si
= NULL
;
268 if (ctx
== NULL
|| cert_req
== NULL
269 || certOut
== NULL
|| chainOut
== NULL
|| caPubs
== NULL
) {
270 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
273 bodytype
= OSSL_CMP_MSG_get_bodytype(cert_req
);
274 if (ctx
->sendError
== 1 || ctx
->sendError
== bodytype
) {
275 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
283 if (ctx
->pollCount
> 0 && ctx
->curr_pollCount
== 0) {
285 if (ctx
->req
!= NULL
) {
286 /* already in polling mode */
287 ERR_raise(ERR_LIB_CMP
, CMP_R_UNEXPECTED_PKIBODY
);
290 if ((ctx
->req
= OSSL_CMP_MSG_dup(cert_req
)) == NULL
)
292 return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting
, 0, NULL
);
294 if (ctx
->curr_pollCount
>= ctx
->pollCount
)
295 /* give final response after polling */
296 ctx
->curr_pollCount
= 0;
298 /* accept cert profile for cr messages only with the configured name */
299 if (OSSL_CMP_MSG_get_bodytype(cert_req
) == OSSL_CMP_CR
) {
300 STACK_OF(OSSL_CMP_ITAV
) *itavs
=
301 OSSL_CMP_HDR_get0_geninfo_ITAVs(OSSL_CMP_MSG_get0_header(cert_req
));
304 for (i
= 0; i
< sk_OSSL_CMP_ITAV_num(itavs
); i
++) {
305 OSSL_CMP_ITAV
*itav
= sk_OSSL_CMP_ITAV_value(itavs
, i
);
306 ASN1_OBJECT
*obj
= OSSL_CMP_ITAV_get0_type(itav
);
307 STACK_OF(ASN1_UTF8STRING
) *strs
;
308 ASN1_UTF8STRING
*str
;
311 if (OBJ_obj2nid(obj
) == NID_id_it_certProfile
) {
312 if (!OSSL_CMP_ITAV_get0_certProfile(itav
, &strs
))
314 if (sk_ASN1_UTF8STRING_num(strs
) < 1) {
315 ERR_raise(ERR_LIB_CMP
, CMP_R_UNEXPECTED_CERTPROFILE
);
318 str
= sk_ASN1_UTF8STRING_value(strs
, 0);
321 (const char *)ASN1_STRING_get0_data(str
)) == NULL
) {
322 ERR_raise(ERR_LIB_CMP
, ERR_R_PASSED_INVALID_ARGUMENT
);
325 if (strcmp(data
, "profile1") != 0) {
326 ERR_raise(ERR_LIB_CMP
, CMP_R_UNEXPECTED_CERTPROFILE
);
334 /* accept cert update request only for the reference cert, if given */
335 if (bodytype
== OSSL_CMP_KUR
336 && crm
!= NULL
/* thus not p10cr */ && ctx
->refCert
!= NULL
) {
337 const OSSL_CRMF_CERTID
*cid
= OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm
);
340 ERR_raise(ERR_LIB_CMP
, CMP_R_MISSING_CERTID
);
343 if (!refcert_cmp(ctx
->refCert
,
344 OSSL_CRMF_CERTID_get0_issuer(cid
),
345 OSSL_CRMF_CERTID_get0_serialNumber(cid
))) {
346 ERR_raise(ERR_LIB_CMP
, CMP_R_WRONG_CERTID
);
351 if (ctx
->certOut
!= NULL
352 && (*certOut
= X509_dup(ctx
->certOut
)) == NULL
)
353 /* Should return a cert produced from request template, see FR #16054 */
355 if (ctx
->chainOut
!= NULL
356 && (*chainOut
= X509_chain_up_ref(ctx
->chainOut
)) == NULL
)
358 if (ctx
->caPubsOut
!= NULL
/* OSSL_CMP_PKIBODY_IP not visible here */
359 && (*caPubs
= X509_chain_up_ref(ctx
->caPubsOut
)) == NULL
)
361 if (ctx
->statusOut
!= NULL
362 && (si
= OSSL_CMP_PKISI_dup(ctx
->statusOut
)) == NULL
)
369 OSSL_STACK_OF_X509_free(*chainOut
);
371 OSSL_STACK_OF_X509_free(*caPubs
);
376 static OSSL_CMP_PKISI
*process_rr(OSSL_CMP_SRV_CTX
*srv_ctx
,
377 const OSSL_CMP_MSG
*rr
,
378 const X509_NAME
*issuer
,
379 const ASN1_INTEGER
*serial
)
381 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
383 if (ctx
== NULL
|| rr
== NULL
) {
384 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
387 if (ctx
->sendError
== 1
388 || ctx
->sendError
== OSSL_CMP_MSG_get_bodytype(rr
)) {
389 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
393 /* allow any RR derived from CSR which does not include issuer and serial */
394 if ((issuer
!= NULL
|| serial
!= NULL
)
395 /* accept revocation only for the reference cert, if given */
396 && !refcert_cmp(ctx
->refCert
, issuer
, serial
)) {
397 ERR_raise_data(ERR_LIB_CMP
, CMP_R_REQUEST_NOT_ACCEPTED
,
398 "wrong certificate to revoke");
401 return OSSL_CMP_PKISI_dup(ctx
->statusOut
);
404 static OSSL_CMP_ITAV
*process_genm_itav(mock_srv_ctx
*ctx
, int req_nid
,
405 const OSSL_CMP_ITAV
*req
)
410 case NID_id_it_caCerts
:
411 rsp
= OSSL_CMP_ITAV_new_caCerts(ctx
->caPubsOut
);
413 case NID_id_it_rootCaCert
:
414 rsp
= OSSL_CMP_ITAV_new_rootCaKeyUpdate(ctx
->newWithNew
,
419 rsp
= OSSL_CMP_ITAV_dup(req
);
424 static int process_genm(OSSL_CMP_SRV_CTX
*srv_ctx
,
425 const OSSL_CMP_MSG
*genm
,
426 const STACK_OF(OSSL_CMP_ITAV
) *in
,
427 STACK_OF(OSSL_CMP_ITAV
) **out
)
429 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
431 if (ctx
== NULL
|| genm
== NULL
|| in
== NULL
|| out
== NULL
) {
432 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
435 if (ctx
->sendError
== 1
436 || ctx
->sendError
== OSSL_CMP_MSG_get_bodytype(genm
)
437 || sk_OSSL_CMP_ITAV_num(in
) > 1) {
438 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
441 if (sk_OSSL_CMP_ITAV_num(in
) == 1) {
442 OSSL_CMP_ITAV
*req
= sk_OSSL_CMP_ITAV_value(in
, 0), *rsp
;
443 ASN1_OBJECT
*obj
= OSSL_CMP_ITAV_get0_type(req
);
445 if ((*out
= sk_OSSL_CMP_ITAV_new_reserve(NULL
, 1)) == NULL
)
447 rsp
= process_genm_itav(ctx
, OBJ_obj2nid(obj
), req
);
448 if (rsp
!= NULL
&& sk_OSSL_CMP_ITAV_push(*out
, rsp
))
450 sk_OSSL_CMP_ITAV_free(*out
);
454 *out
= sk_OSSL_CMP_ITAV_deep_copy(in
, OSSL_CMP_ITAV_dup
,
459 static void process_error(OSSL_CMP_SRV_CTX
*srv_ctx
, const OSSL_CMP_MSG
*error
,
460 const OSSL_CMP_PKISI
*statusInfo
,
461 const ASN1_INTEGER
*errorCode
,
462 const OSSL_CMP_PKIFREETEXT
*errorDetails
)
464 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
465 char buf
[OSSL_CMP_PKISI_BUFLEN
];
469 if (ctx
== NULL
|| error
== NULL
) {
470 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
474 BIO_printf(bio_err
, "mock server received error:\n");
476 if (statusInfo
== NULL
) {
477 BIO_printf(bio_err
, "pkiStatusInfo absent\n");
479 sibuf
= OSSL_CMP_snprint_PKIStatusInfo(statusInfo
, buf
, sizeof(buf
));
480 BIO_printf(bio_err
, "pkiStatusInfo: %s\n",
481 sibuf
!= NULL
? sibuf
: "<invalid>");
484 if (errorCode
== NULL
)
485 BIO_printf(bio_err
, "errorCode absent\n");
487 BIO_printf(bio_err
, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode
));
489 if (sk_ASN1_UTF8STRING_num(errorDetails
) <= 0) {
490 BIO_printf(bio_err
, "errorDetails absent\n");
492 BIO_printf(bio_err
, "errorDetails: ");
493 for (i
= 0; i
< sk_ASN1_UTF8STRING_num(errorDetails
); i
++) {
495 BIO_printf(bio_err
, ", ");
496 ASN1_STRING_print_ex(bio_err
,
497 sk_ASN1_UTF8STRING_value(errorDetails
, i
),
498 ASN1_STRFLGS_ESC_QUOTE
);
500 BIO_printf(bio_err
, "\n");
504 static int process_certConf(OSSL_CMP_SRV_CTX
*srv_ctx
,
505 const OSSL_CMP_MSG
*certConf
,
506 ossl_unused
int certReqId
,
507 const ASN1_OCTET_STRING
*certHash
,
508 const OSSL_CMP_PKISI
*si
)
510 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
511 ASN1_OCTET_STRING
*digest
;
513 if (ctx
== NULL
|| certConf
== NULL
|| certHash
== NULL
) {
514 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
517 if (ctx
->sendError
== 1
518 || ctx
->sendError
== OSSL_CMP_MSG_get_bodytype(certConf
)
519 || ctx
->certOut
== NULL
) {
520 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
524 if ((digest
= X509_digest_sig(ctx
->certOut
, NULL
, NULL
)) == NULL
)
526 if (ASN1_OCTET_STRING_cmp(certHash
, digest
) != 0) {
527 ASN1_OCTET_STRING_free(digest
);
528 ERR_raise(ERR_LIB_CMP
, CMP_R_CERTHASH_UNMATCHED
);
531 ASN1_OCTET_STRING_free(digest
);
535 /* return 0 on failure, 1 on success, setting *req or otherwise *check_after */
536 static int process_pollReq(OSSL_CMP_SRV_CTX
*srv_ctx
,
537 const OSSL_CMP_MSG
*pollReq
,
538 ossl_unused
int certReqId
,
539 OSSL_CMP_MSG
**req
, int64_t *check_after
)
541 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
545 if (ctx
== NULL
|| pollReq
== NULL
546 || req
== NULL
|| check_after
== NULL
) {
547 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
551 if (ctx
->sendError
== 1
552 || ctx
->sendError
== OSSL_CMP_MSG_get_bodytype(pollReq
)) {
553 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
556 if (ctx
->req
== NULL
) { /* not currently in polling mode */
557 ERR_raise(ERR_LIB_CMP
, CMP_R_UNEXPECTED_POLLREQ
);
561 if (++ctx
->curr_pollCount
>= ctx
->pollCount
) {
567 *check_after
= ctx
->checkAfterTime
;
572 OSSL_CMP_SRV_CTX
*ossl_cmp_mock_srv_new(OSSL_LIB_CTX
*libctx
, const char *propq
)
574 OSSL_CMP_SRV_CTX
*srv_ctx
= OSSL_CMP_SRV_CTX_new(libctx
, propq
);
575 mock_srv_ctx
*ctx
= mock_srv_ctx_new();
577 if (srv_ctx
!= NULL
&& ctx
!= NULL
578 && OSSL_CMP_SRV_CTX_init(srv_ctx
, ctx
, process_cert_request
,
579 process_rr
, process_genm
, process_error
,
580 process_certConf
, process_pollReq
)
581 && OSSL_CMP_SRV_CTX_init_trans(srv_ctx
,
582 delayed_delivery
, clean_transaction
))
585 mock_srv_ctx_free(ctx
);
586 OSSL_CMP_SRV_CTX_free(srv_ctx
);
590 void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX
*srv_ctx
)
593 mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
));
594 OSSL_CMP_SRV_CTX_free(srv_ctx
);