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
*certReq
; /* ir/cr/p10cr/kur remembered while 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
->certReq
);
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 /* check for matching reference cert components, as far as given */
187 static int refcert_cmp(const X509
*refcert
,
188 const X509_NAME
*issuer
, const ASN1_INTEGER
*serial
)
190 const X509_NAME
*ref_issuer
;
191 const ASN1_INTEGER
*ref_serial
;
195 ref_issuer
= X509_get_issuer_name(refcert
);
196 ref_serial
= X509_get0_serialNumber(refcert
);
197 return (ref_issuer
== NULL
|| X509_NAME_cmp(issuer
, ref_issuer
) == 0)
198 && (ref_serial
== NULL
|| ASN1_INTEGER_cmp(serial
, ref_serial
) == 0);
201 static OSSL_CMP_PKISI
*process_cert_request(OSSL_CMP_SRV_CTX
*srv_ctx
,
202 const OSSL_CMP_MSG
*cert_req
,
203 ossl_unused
int certReqId
,
204 const OSSL_CRMF_MSG
*crm
,
205 const X509_REQ
*p10cr
,
207 STACK_OF(X509
) **chainOut
,
208 STACK_OF(X509
) **caPubs
)
210 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
212 OSSL_CMP_PKISI
*si
= NULL
;
214 if (ctx
== NULL
|| cert_req
== NULL
215 || certOut
== NULL
|| chainOut
== NULL
|| caPubs
== NULL
) {
216 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
219 bodytype
= OSSL_CMP_MSG_get_bodytype(cert_req
);
220 if (ctx
->sendError
== 1 || ctx
->sendError
== bodytype
) {
221 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
229 if (ctx
->pollCount
> 0 && ctx
->curr_pollCount
== 0) {
231 if (ctx
->certReq
!= NULL
) {
232 /* already in polling mode */
233 ERR_raise(ERR_LIB_CMP
, CMP_R_UNEXPECTED_PKIBODY
);
236 if ((ctx
->certReq
= OSSL_CMP_MSG_dup(cert_req
)) == NULL
)
238 return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting
, 0, NULL
);
240 if (ctx
->curr_pollCount
>= ctx
->pollCount
)
241 /* give final response after polling */
242 ctx
->curr_pollCount
= 0;
244 /* accept cert update request only for the reference cert, if given */
245 if (bodytype
== OSSL_CMP_KUR
246 && crm
!= NULL
/* thus not p10cr */ && ctx
->refCert
!= NULL
) {
247 const OSSL_CRMF_CERTID
*cid
= OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm
);
250 ERR_raise(ERR_LIB_CMP
, CMP_R_MISSING_CERTID
);
253 if (!refcert_cmp(ctx
->refCert
,
254 OSSL_CRMF_CERTID_get0_issuer(cid
),
255 OSSL_CRMF_CERTID_get0_serialNumber(cid
))) {
256 ERR_raise(ERR_LIB_CMP
, CMP_R_WRONG_CERTID
);
261 if (ctx
->certOut
!= NULL
262 && (*certOut
= X509_dup(ctx
->certOut
)) == NULL
)
263 /* Should return a cert produced from request template, see FR #16054 */
265 if (ctx
->chainOut
!= NULL
266 && (*chainOut
= X509_chain_up_ref(ctx
->chainOut
)) == NULL
)
268 if (ctx
->caPubsOut
!= NULL
/* OSSL_CMP_PKIBODY_IP not visible here */
269 && (*caPubs
= X509_chain_up_ref(ctx
->caPubsOut
)) == NULL
)
271 if (ctx
->statusOut
!= NULL
272 && (si
= OSSL_CMP_PKISI_dup(ctx
->statusOut
)) == NULL
)
279 OSSL_STACK_OF_X509_free(*chainOut
);
281 OSSL_STACK_OF_X509_free(*caPubs
);
286 static OSSL_CMP_PKISI
*process_rr(OSSL_CMP_SRV_CTX
*srv_ctx
,
287 const OSSL_CMP_MSG
*rr
,
288 const X509_NAME
*issuer
,
289 const ASN1_INTEGER
*serial
)
291 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
293 if (ctx
== NULL
|| rr
== NULL
) {
294 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
297 if (ctx
->sendError
== 1
298 || ctx
->sendError
== OSSL_CMP_MSG_get_bodytype(rr
)) {
299 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
303 /* allow any RR derived from CSR which does not include issuer and serial */
304 if ((issuer
!= NULL
|| serial
!= NULL
)
305 /* accept revocation only for the reference cert, if given */
306 && !refcert_cmp(ctx
->refCert
, issuer
, serial
)) {
307 ERR_raise_data(ERR_LIB_CMP
, CMP_R_REQUEST_NOT_ACCEPTED
,
308 "wrong certificate to revoke");
311 return OSSL_CMP_PKISI_dup(ctx
->statusOut
);
314 static OSSL_CMP_ITAV
*process_genm_itav(mock_srv_ctx
*ctx
, int req_nid
,
315 const OSSL_CMP_ITAV
*req
)
320 case NID_id_it_caCerts
:
321 rsp
= OSSL_CMP_ITAV_new_caCerts(ctx
->caPubsOut
);
323 case NID_id_it_rootCaCert
:
324 rsp
= OSSL_CMP_ITAV_new_rootCaKeyUpdate(ctx
->newWithNew
,
329 rsp
= OSSL_CMP_ITAV_dup(req
);
334 static int process_genm(OSSL_CMP_SRV_CTX
*srv_ctx
,
335 const OSSL_CMP_MSG
*genm
,
336 const STACK_OF(OSSL_CMP_ITAV
) *in
,
337 STACK_OF(OSSL_CMP_ITAV
) **out
)
339 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
341 if (ctx
== NULL
|| genm
== NULL
|| in
== NULL
|| out
== NULL
) {
342 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
345 if (ctx
->sendError
== 1
346 || ctx
->sendError
== OSSL_CMP_MSG_get_bodytype(genm
)
347 || sk_OSSL_CMP_ITAV_num(in
) > 1) {
348 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
351 if (sk_OSSL_CMP_ITAV_num(in
) == 1) {
352 OSSL_CMP_ITAV
*req
= sk_OSSL_CMP_ITAV_value(in
, 0), *rsp
;
353 ASN1_OBJECT
*obj
= OSSL_CMP_ITAV_get0_type(req
);
355 if ((*out
= sk_OSSL_CMP_ITAV_new_reserve(NULL
, 1)) == NULL
)
357 rsp
= process_genm_itav(ctx
, OBJ_obj2nid(obj
), req
);
358 if (rsp
!= NULL
&& sk_OSSL_CMP_ITAV_push(*out
, rsp
))
360 sk_OSSL_CMP_ITAV_free(*out
);
364 *out
= sk_OSSL_CMP_ITAV_deep_copy(in
, OSSL_CMP_ITAV_dup
,
369 static void process_error(OSSL_CMP_SRV_CTX
*srv_ctx
, const OSSL_CMP_MSG
*error
,
370 const OSSL_CMP_PKISI
*statusInfo
,
371 const ASN1_INTEGER
*errorCode
,
372 const OSSL_CMP_PKIFREETEXT
*errorDetails
)
374 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
375 char buf
[OSSL_CMP_PKISI_BUFLEN
];
379 if (ctx
== NULL
|| error
== NULL
) {
380 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
384 BIO_printf(bio_err
, "mock server received error:\n");
386 if (statusInfo
== NULL
) {
387 BIO_printf(bio_err
, "pkiStatusInfo absent\n");
389 sibuf
= OSSL_CMP_snprint_PKIStatusInfo(statusInfo
, buf
, sizeof(buf
));
390 BIO_printf(bio_err
, "pkiStatusInfo: %s\n",
391 sibuf
!= NULL
? sibuf
: "<invalid>");
394 if (errorCode
== NULL
)
395 BIO_printf(bio_err
, "errorCode absent\n");
397 BIO_printf(bio_err
, "errorCode: %ld\n", ASN1_INTEGER_get(errorCode
));
399 if (sk_ASN1_UTF8STRING_num(errorDetails
) <= 0) {
400 BIO_printf(bio_err
, "errorDetails absent\n");
402 BIO_printf(bio_err
, "errorDetails: ");
403 for (i
= 0; i
< sk_ASN1_UTF8STRING_num(errorDetails
); i
++) {
405 BIO_printf(bio_err
, ", ");
406 ASN1_STRING_print_ex(bio_err
,
407 sk_ASN1_UTF8STRING_value(errorDetails
, i
),
408 ASN1_STRFLGS_ESC_QUOTE
);
410 BIO_printf(bio_err
, "\n");
414 static int process_certConf(OSSL_CMP_SRV_CTX
*srv_ctx
,
415 const OSSL_CMP_MSG
*certConf
,
416 ossl_unused
int certReqId
,
417 const ASN1_OCTET_STRING
*certHash
,
418 const OSSL_CMP_PKISI
*si
)
420 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
421 ASN1_OCTET_STRING
*digest
;
423 if (ctx
== NULL
|| certConf
== NULL
|| certHash
== NULL
) {
424 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
427 if (ctx
->sendError
== 1
428 || ctx
->sendError
== OSSL_CMP_MSG_get_bodytype(certConf
)
429 || ctx
->certOut
== NULL
) {
430 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
434 if ((digest
= X509_digest_sig(ctx
->certOut
, NULL
, NULL
)) == NULL
)
436 if (ASN1_OCTET_STRING_cmp(certHash
, digest
) != 0) {
437 ASN1_OCTET_STRING_free(digest
);
438 ERR_raise(ERR_LIB_CMP
, CMP_R_CERTHASH_UNMATCHED
);
441 ASN1_OCTET_STRING_free(digest
);
445 static int process_pollReq(OSSL_CMP_SRV_CTX
*srv_ctx
,
446 const OSSL_CMP_MSG
*pollReq
,
447 ossl_unused
int certReqId
,
448 OSSL_CMP_MSG
**certReq
, int64_t *check_after
)
450 mock_srv_ctx
*ctx
= OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
);
452 if (ctx
== NULL
|| pollReq
== NULL
453 || certReq
== NULL
|| check_after
== NULL
) {
454 ERR_raise(ERR_LIB_CMP
, CMP_R_NULL_ARGUMENT
);
457 if (ctx
->sendError
== 1
458 || ctx
->sendError
== OSSL_CMP_MSG_get_bodytype(pollReq
)) {
460 ERR_raise(ERR_LIB_CMP
, CMP_R_ERROR_PROCESSING_MESSAGE
);
463 if (ctx
->certReq
== NULL
) {
464 /* not currently in polling mode */
466 ERR_raise(ERR_LIB_CMP
, CMP_R_UNEXPECTED_PKIBODY
);
470 if (++ctx
->curr_pollCount
>= ctx
->pollCount
) {
472 *certReq
= ctx
->certReq
;
477 *check_after
= ctx
->checkAfterTime
;
482 OSSL_CMP_SRV_CTX
*ossl_cmp_mock_srv_new(OSSL_LIB_CTX
*libctx
, const char *propq
)
484 OSSL_CMP_SRV_CTX
*srv_ctx
= OSSL_CMP_SRV_CTX_new(libctx
, propq
);
485 mock_srv_ctx
*ctx
= mock_srv_ctx_new();
487 if (srv_ctx
!= NULL
&& ctx
!= NULL
488 && OSSL_CMP_SRV_CTX_init(srv_ctx
, ctx
, process_cert_request
,
489 process_rr
, process_genm
, process_error
,
490 process_certConf
, process_pollReq
))
493 mock_srv_ctx_free(ctx
);
494 OSSL_CMP_SRV_CTX_free(srv_ctx
);
498 void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX
*srv_ctx
)
501 mock_srv_ctx_free(OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx
));
502 OSSL_CMP_SRV_CTX_free(srv_ctx
);