]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/cmp/cmp_ctx.c
Introduce X509_add_cert[s] simplifying various additions to cert lists
[thirdparty/openssl.git] / crypto / cmp / cmp_ctx.c
CommitLineData
7960dbec 1/*
33388b44 2 * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
7960dbec
DDO
3 * Copyright Nokia 2007-2019
4 * Copyright Siemens AG 2015-2019
5 *
6 * Licensed under the Apache License 2.0 (the "License"). You may not use
7 * this file except in compliance with the License. You can obtain a copy
8 * in the file LICENSE in the source distribution or at
9 * https://www.openssl.org/source/license.html
10 */
11
12#include <openssl/trace.h>
13#include <openssl/bio.h>
14#include <openssl/ocsp.h> /* for OCSP_REVOKED_STATUS_* */
15
706457b7 16#include "cmp_local.h"
7960dbec
DDO
17
18/* explicit #includes not strictly needed since implied by the above: */
19#include <openssl/cmp.h>
20#include <openssl/crmf.h>
21#include <openssl/err.h>
22
852c2ed2
RS
23DEFINE_STACK_OF(X509)
24DEFINE_STACK_OF(X509_EXTENSION)
25DEFINE_STACK_OF(POLICYINFO)
26DEFINE_STACK_OF(ASN1_UTF8STRING)
27DEFINE_STACK_OF(GENERAL_NAME)
28DEFINE_STACK_OF(OSSL_CMP_ITAV)
29
30/*
31 * Get current certificate store containing trusted root CA certs
32 */
7960dbec
DDO
33X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
34{
35 if (ctx == NULL) {
36 CMPerr(0, CMP_R_NULL_ARGUMENT);
37 return NULL;
38 }
39 return ctx->trusted;
40}
41
42/*
43 * Set certificate store containing trusted (root) CA certs and possibly CRLs
44 * and a cert verification callback function used for CMP server authentication.
45 * Any already existing store entry is freed. Given NULL, the entry is reset.
7960dbec
DDO
46 */
47int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
48{
49 if (ctx == NULL) {
50 CMPerr(0, CMP_R_NULL_ARGUMENT);
51 return 0;
52 }
53 X509_STORE_free(ctx->trusted);
54 ctx->trusted = store;
55 return 1;
56}
57
afe554c2 58/* Get current list of non-trusted intermediate certs */
7960dbec
DDO
59STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted_certs(const OSSL_CMP_CTX *ctx)
60{
61 if (ctx == NULL) {
62 CMPerr(0, CMP_R_NULL_ARGUMENT);
63 return NULL;
64 }
65 return ctx->untrusted_certs;
66}
67
68/*
69 * Set untrusted certificates for path construction in authentication of
70 * the CMP server and potentially others (TLS server, newly enrolled cert).
7960dbec
DDO
71 */
72int OSSL_CMP_CTX_set1_untrusted_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
73{
59ae04d7 74 STACK_OF(X509) *untrusted_certs;
7960dbec
DDO
75 if (ctx == NULL) {
76 CMPerr(0, CMP_R_NULL_ARGUMENT);
77 return 0;
78 }
59ae04d7 79 if ((untrusted_certs = sk_X509_new_null()) == NULL)
7960dbec 80 return 0;
eeccc237
DDO
81 if (X509_add_certs(untrusted_certs, certs,
82 X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP) != 1)
59ae04d7 83 goto err;
84 sk_X509_pop_free(ctx->untrusted_certs, X509_free);
85 ctx->untrusted_certs = untrusted_certs;
86 return 1;
235595c4 87 err:
59ae04d7 88 sk_X509_pop_free(untrusted_certs, X509_free);
89 return 0;
7960dbec
DDO
90}
91
92/*
93 * Allocates and initializes OSSL_CMP_CTX context structure with default values.
94 * Returns new context on success, NULL on error
95 */
96OSSL_CMP_CTX *OSSL_CMP_CTX_new(void)
97{
98 OSSL_CMP_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
99
100 if (ctx == NULL)
101 return NULL;
102
103 ctx->log_verbosity = OSSL_CMP_LOG_INFO;
104
105 ctx->status = -1;
106 ctx->failInfoCode = -1;
107
7e765f46 108 ctx->msg_timeout = 2 * 60;
7960dbec
DDO
109
110 if ((ctx->untrusted_certs = sk_X509_new_null()) == NULL)
111 goto err;
112
113 ctx->pbm_slen = 16;
114 ctx->pbm_owf = NID_sha256;
115 ctx->pbm_itercnt = 500;
116 ctx->pbm_mac = NID_hmac_sha1;
117
118 ctx->digest = NID_sha256;
119 ctx->popoMethod = OSSL_CRMF_POPO_SIGNATURE;
120 ctx->revocationReason = CRL_REASON_NONE;
121
122 /* all other elements are initialized to 0 or NULL, respectively */
123 return ctx;
124
125 err:
126 OSSL_CMP_CTX_free(ctx);
127 return NULL;
128}
129
afe554c2 130/* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX */
7960dbec
DDO
131int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
132{
133 if (ctx == NULL) {
134 CMPerr(0, CMP_R_NULL_ARGUMENT);
135 return 0;
136 }
137
138 ctx->status = -1;
139 ctx->failInfoCode = -1;
140
141 return ossl_cmp_ctx_set0_statusString(ctx, NULL)
142 && ossl_cmp_ctx_set0_newCert(ctx, NULL)
143 && ossl_cmp_ctx_set1_caPubs(ctx, NULL)
144 && ossl_cmp_ctx_set1_extraCertsIn(ctx, NULL)
145 && ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL)
146 && OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
147 && OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)
148 && ossl_cmp_ctx_set1_recipNonce(ctx, NULL);
149}
150
afe554c2 151/* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new() */
7960dbec
DDO
152void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
153{
154 if (ctx == NULL)
155 return;
156
157 OPENSSL_free(ctx->serverPath);
4b1fe471 158 OPENSSL_free(ctx->server);
afe554c2
DDO
159 OPENSSL_free(ctx->proxy);
160 OPENSSL_free(ctx->no_proxy);
7960dbec
DDO
161
162 X509_free(ctx->srvCert);
163 X509_free(ctx->validatedSrvCert);
164 X509_NAME_free(ctx->expected_sender);
165 X509_STORE_free(ctx->trusted);
166 sk_X509_pop_free(ctx->untrusted_certs, X509_free);
167
63f1883d 168 X509_free(ctx->cert);
7960dbec
DDO
169 EVP_PKEY_free(ctx->pkey);
170 ASN1_OCTET_STRING_free(ctx->referenceValue);
171 if (ctx->secretValue != NULL)
172 OPENSSL_cleanse(ctx->secretValue->data, ctx->secretValue->length);
173 ASN1_OCTET_STRING_free(ctx->secretValue);
174
175 X509_NAME_free(ctx->recipient);
176 ASN1_OCTET_STRING_free(ctx->transactionID);
177 ASN1_OCTET_STRING_free(ctx->senderNonce);
178 ASN1_OCTET_STRING_free(ctx->recipNonce);
179 sk_OSSL_CMP_ITAV_pop_free(ctx->geninfo_ITAVs, OSSL_CMP_ITAV_free);
180 sk_X509_pop_free(ctx->extraCertsOut, X509_free);
181
182 EVP_PKEY_free(ctx->newPkey);
183 X509_NAME_free(ctx->issuer);
184 X509_NAME_free(ctx->subjectName);
185 sk_GENERAL_NAME_pop_free(ctx->subjectAltNames, GENERAL_NAME_free);
186 sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
187 sk_POLICYINFO_pop_free(ctx->policies, POLICYINFO_free);
188 X509_free(ctx->oldCert);
189 X509_REQ_free(ctx->p10CSR);
190
191 sk_OSSL_CMP_ITAV_pop_free(ctx->genm_ITAVs, OSSL_CMP_ITAV_free);
192
193 sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
194 X509_free(ctx->newCert);
195 sk_X509_pop_free(ctx->caPubs, X509_free);
196 sk_X509_pop_free(ctx->extraCertsIn, X509_free);
197
198 OPENSSL_free(ctx);
199}
200
201int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status)
202{
203 if (!ossl_assert(ctx != NULL))
4dde554c 204 return 0;
7960dbec
DDO
205 ctx->status = status;
206 return 1;
207}
208
209/*
210 * Returns the PKIStatus from the last CertRepMessage
211 * or Revocation Response or error message, -1 on error
212 */
213int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx)
214{
215 if (ctx == NULL) {
216 CMPerr(0, CMP_R_NULL_ARGUMENT);
217 return -1;
218 }
219 return ctx->status;
220}
221
222/*
223 * Returns the statusString from the last CertRepMessage
224 * or Revocation Response or error message, NULL on error
225 */
226OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx)
227{
228 if (ctx == NULL) {
229 CMPerr(0, CMP_R_NULL_ARGUMENT);
230 return NULL;
231 }
232 return ctx->statusString;
233}
234
235int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
236 OSSL_CMP_PKIFREETEXT *text)
237{
238 if (!ossl_assert(ctx != NULL))
239 return 0;
240 sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
241 ctx->statusString = text;
242 return 1;
243}
244
245int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert)
246{
247 if (!ossl_assert(ctx != NULL))
248 return 0;
249 X509_free(ctx->validatedSrvCert);
250 ctx->validatedSrvCert = cert;
251 return 1;
252}
253
afe554c2 254/* Set callback function for checking if the cert is ok or should be rejected */
7e765f46 255int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb)
7960dbec
DDO
256{
257 if (ctx == NULL) {
258 CMPerr(0, CMP_R_NULL_ARGUMENT);
259 return 0;
260 }
261 ctx->certConf_cb = cb;
262 return 1;
263}
264
265/*
266 * Set argument, respectively a pointer to a structure containing arguments,
267 * optionally to be used by the certConf callback.
7960dbec
DDO
268 */
269int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
270{
271 if (ctx == NULL) {
272 CMPerr(0, CMP_R_NULL_ARGUMENT);
273 return 0;
274 }
275 ctx->certConf_cb_arg = arg;
276 return 1;
277}
278
279/*
280 * Get argument, respectively the pointer to a structure containing arguments,
281 * optionally to be used by certConf callback.
282 * Returns callback argument set previously (NULL if not set or on error)
283 */
284void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx)
285{
286 if (ctx == NULL) {
287 CMPerr(0, CMP_R_NULL_ARGUMENT);
288 return NULL;
289 }
290 return ctx->certConf_cb_arg;
291}
292
293#ifndef OPENSSL_NO_TRACE
294static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt,
295 int category, int cmd, void *vdata)
296{
297 OSSL_CMP_CTX *ctx = vdata;
ebf30069 298 const char *msg;
7960dbec
DDO
299 OSSL_CMP_severity level = -1;
300 char *func = NULL;
301 char *file = NULL;
302 int line = 0;
303
304 if (buf == NULL || cnt == 0 || cmd != OSSL_TRACE_CTRL_WRITE || ctx == NULL)
305 return 0;
306 if (ctx->log_cb == NULL)
307 return 1; /* silently drop message */
308
ebf30069 309 msg = ossl_cmp_log_parse_metadata(buf, &level, &func, &file, &line);
7960dbec
DDO
310
311 if (level > ctx->log_verbosity) /* excludes the case level is unknown */
312 goto end; /* suppress output since severity is not sufficient */
313
314 if (!ctx->log_cb(func != NULL ? func : "(no func)",
315 file != NULL ? file : "(no file)",
ebf30069 316 line, level, msg))
7960dbec
DDO
317 cnt = 0;
318
319 end:
320 OPENSSL_free(func);
321 OPENSSL_free(file);
322 return cnt;
323}
324#endif
325
ebf30069
DDO
326/* Print CMP log messages (i.e., diagnostic info) via the log cb of the ctx */
327int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
328 const char *func, const char *file, int line,
329 const char *level_str, const char *format, ...)
330{
331 va_list args;
332 char hugebuf[1024 * 2];
333 int res = 0;
334
335 if (ctx == NULL || ctx->log_cb == NULL)
336 return 1; /* silently drop message */
337
338 if (level > ctx->log_verbosity) /* excludes the case level is unknown */
339 return 1; /* suppress output since severity is not sufficient */
340
341 if (format == NULL)
342 return 0;
343
344 va_start(args, format);
345
346 if (func == NULL)
347 func = "(unset function name)";
348 if (file == NULL)
349 file = "(unset file name)";
350 if (level_str == NULL)
351 level_str = "(unset level string)";
352
353#ifndef OPENSSL_NO_TRACE
354 if (OSSL_TRACE_ENABLED(CMP)) {
355 OSSL_TRACE_BEGIN(CMP) {
356 int printed =
357 BIO_snprintf(hugebuf, sizeof(hugebuf),
358 "%s:%s:%d:" OSSL_CMP_LOG_PREFIX "%s: ",
359 func, file, line, level_str);
360 if (printed > 0 && (size_t)printed < sizeof(hugebuf)) {
361 if (BIO_vsnprintf(hugebuf + printed,
362 sizeof(hugebuf) - printed, format, args) > 0)
363 res = BIO_puts(trc_out, hugebuf) > 0;
364 }
365 } OSSL_TRACE_END(CMP);
366 }
367#else /* compensate for disabled trace API */
368 {
369 if (BIO_vsnprintf(hugebuf, sizeof(hugebuf), format, args) > 0)
370 res = ctx->log_cb(func, file, line, level, hugebuf);
371 }
372#endif
373 va_end(args);
374 return res;
375}
376
afe554c2 377/* Set a callback function for error reporting and logging messages */
7e765f46 378int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb)
7960dbec
DDO
379{
380 if (ctx == NULL) {
381 CMPerr(0, CMP_R_NULL_ARGUMENT);
382 return 0;
383 }
384 ctx->log_cb = cb;
385
386#ifndef OPENSSL_NO_TRACE
387 /* do also in case cb == NULL, to switch off logging output: */
388 if (!OSSL_trace_set_callback(OSSL_TRACE_CATEGORY_CMP,
389 ossl_cmp_log_trace_cb, ctx))
390 return 0;
391#endif
392
393 return 1;
394}
395
396/* Print OpenSSL and CMP errors via the log cb of the ctx or ERR_print_errors */
c4a9e3eb 397void OSSL_CMP_CTX_print_errors(const OSSL_CMP_CTX *ctx)
7960dbec
DDO
398{
399 OSSL_CMP_print_errors_cb(ctx == NULL ? NULL : ctx->log_cb);
400}
401
402/*
403 * Set or clear the reference value to be used for identification
404 * (i.e., the user name) when using PBMAC.
7960dbec
DDO
405 */
406int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
407 const unsigned char *ref, int len)
408{
409 if (ctx == NULL) {
410 CMPerr(0, CMP_R_NULL_ARGUMENT);
411 return 0;
412 }
413 return ossl_cmp_asn1_octet_string_set1_bytes(&ctx->referenceValue, ref,
414 len);
415}
416
afe554c2 417/* Set or clear the password to be used for protecting messages with PBMAC */
7960dbec
DDO
418int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
419 const int len)
420{
59ae04d7 421 ASN1_OCTET_STRING *secretValue = NULL;
7960dbec
DDO
422 if (ctx == NULL) {
423 CMPerr(0, CMP_R_NULL_ARGUMENT);
424 return 0;
425 }
59ae04d7 426 if (ossl_cmp_asn1_octet_string_set1_bytes(&secretValue, sec, len) != 1)
427 return 0;
428 if (ctx->secretValue != NULL) {
7960dbec 429 OPENSSL_cleanse(ctx->secretValue->data, ctx->secretValue->length);
59ae04d7 430 ASN1_OCTET_STRING_free(ctx->secretValue);
431 }
432 ctx->secretValue = secretValue;
433 return 1;
7960dbec
DDO
434}
435
436/*
437 * Returns the stack of certificates received in a response message.
438 * The stack is duplicated so the caller must handle freeing it!
439 * Returns pointer to created stack on success, NULL on error
440 */
441STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx)
442{
443 if (ctx == NULL) {
444 CMPerr(0, CMP_R_NULL_ARGUMENT);
445 return NULL;
446 }
447 if (ctx->extraCertsIn == NULL)
448 return sk_X509_new_null();
449 return X509_chain_up_ref(ctx->extraCertsIn);
450}
451
452/*
453 * Copies any given stack of inbound X509 certificates to extraCertsIn
454 * of the OSSL_CMP_CTX structure so that they may be retrieved later.
7960dbec
DDO
455 */
456int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
457 STACK_OF(X509) *extraCertsIn)
458{
459 if (!ossl_assert(ctx != NULL))
460 return 0;
461
462 sk_X509_pop_free(ctx->extraCertsIn, X509_free);
463 ctx->extraCertsIn = NULL;
464 if (extraCertsIn == NULL)
465 return 1;
466 return (ctx->extraCertsIn = X509_chain_up_ref(extraCertsIn)) != NULL;
467}
468
469/*
470 * Duplicate and set the given stack as the new stack of X509
471 * certificates to send out in the extraCerts field.
7960dbec
DDO
472 */
473int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
474 STACK_OF(X509) *extraCertsOut)
475{
476 if (ctx == NULL) {
477 CMPerr(0, CMP_R_NULL_ARGUMENT);
478 return 0;
479 }
480
481 sk_X509_pop_free(ctx->extraCertsOut, X509_free);
482 ctx->extraCertsOut = NULL;
483 if (extraCertsOut == NULL)
484 return 1;
485 return (ctx->extraCertsOut = X509_chain_up_ref(extraCertsOut)) != NULL;
486}
487
488/*
489 * Add the given policy info object
490 * to the X509_EXTENSIONS of the requested certificate template.
7960dbec
DDO
491 */
492int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo)
493{
494 if (ctx == NULL || pinfo == NULL) {
495 CMPerr(0, CMP_R_NULL_ARGUMENT);
496 return 0;
497 }
498
499 if (ctx->policies == NULL
500 && (ctx->policies = CERTIFICATEPOLICIES_new()) == NULL)
501 return 0;
502
503 return sk_POLICYINFO_push(ctx->policies, pinfo);
504}
505
afe554c2 506/* Add an ITAV for geninfo of the PKI message header */
7960dbec
DDO
507int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
508{
509 if (ctx == NULL) {
510 CMPerr(0, CMP_R_NULL_ARGUMENT);
511 return 0;
512 }
513 return OSSL_CMP_ITAV_push0_stack_item(&ctx->geninfo_ITAVs, itav);
514}
515
afe554c2 516/* Add an itav for the body of outgoing general messages */
7960dbec
DDO
517int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
518{
519 if (ctx == NULL) {
520 CMPerr(0, CMP_R_NULL_ARGUMENT);
521 return 0;
522 }
523 return OSSL_CMP_ITAV_push0_stack_item(&ctx->genm_ITAVs, itav);
524}
525
526/*
527 * Returns a duplicate of the stack of X509 certificates that
528 * were received in the caPubs field of the last CertRepMessage.
529 * Returns NULL on error
530 */
531STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx)
532{
533 if (ctx == NULL) {
534 CMPerr(0, CMP_R_NULL_ARGUMENT);
535 return NULL;
536 }
537 if (ctx->caPubs == NULL)
538 return sk_X509_new_null();
539 return X509_chain_up_ref(ctx->caPubs);
540}
541
542/*
543 * Duplicate and copy the given stack of certificates to the given
544 * OSSL_CMP_CTX structure so that they may be retrieved later.
7960dbec
DDO
545 */
546int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs)
547{
548 if (!ossl_assert(ctx != NULL))
549 return 0;
550
551 sk_X509_pop_free(ctx->caPubs, X509_free);
552 ctx->caPubs = NULL;
553 if (caPubs == NULL)
554 return 1;
555 return (ctx->caPubs = X509_chain_up_ref(caPubs)) != NULL;
556}
557
558#define char_dup OPENSSL_strdup
559#define char_free OPENSSL_free
560#define DEFINE_OSSL_CMP_CTX_set1(FIELD, TYPE) /* this uses _dup */ \
561int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, const TYPE *val) \
562{ \
563 TYPE *val_dup = NULL; \
564 \
565 if (ctx == NULL) { \
566 CMPerr(0, CMP_R_NULL_ARGUMENT); \
567 return 0; \
568 } \
569 \
570 if (val != NULL && (val_dup = TYPE##_dup(val)) == NULL) \
571 return 0; \
572 TYPE##_free(ctx->FIELD); \
573 ctx->FIELD = val_dup; \
574 return 1; \
575}
576
577#define DEFINE_OSSL_CMP_CTX_set1_up_ref(FIELD, TYPE) \
578int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
579{ \
580 if (ctx == NULL) { \
581 CMPerr(0, CMP_R_NULL_ARGUMENT); \
582 return 0; \
583 } \
584 \
585 if (val != NULL && !TYPE##_up_ref(val)) \
586 return 0; \
587 TYPE##_free(ctx->FIELD); \
588 ctx->FIELD = val; \
589 return 1; \
590}
591
592/*
593 * Pins the server certificate to be directly trusted (even if it is expired)
594 * for verifying response messages.
595 * Cert pointer is not consumed. It may be NULL to clear the entry.
7960dbec
DDO
596 */
597DEFINE_OSSL_CMP_CTX_set1_up_ref(srvCert, X509)
598
afe554c2 599/* Set the X509 name of the recipient. Set in the PKIHeader */
7960dbec
DDO
600DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME)
601
afe554c2 602/* Store the X509 name of the expected sender in the PKIHeader of responses */
7960dbec
DDO
603DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME)
604
afe554c2 605/* Set the X509 name of the issuer. Set in the PKIHeader */
7960dbec
DDO
606DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME)
607
608/*
609 * Set the subject name that will be placed in the certificate
610 * request. This will be the subject name on the received certificate.
7960dbec
DDO
611 */
612DEFINE_OSSL_CMP_CTX_set1(subjectName, X509_NAME)
613
afe554c2 614/* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR */
7960dbec
DDO
615int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts)
616{
617 if (ctx == NULL) {
618 CMPerr(0, CMP_R_NULL_ARGUMENT);
619 return 0;
620 }
621
622 if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0 && exts != NULL
623 && X509v3_get_ext_by_NID(exts, NID_subject_alt_name, -1) >= 0) {
624 CMPerr(0, CMP_R_MULTIPLE_SAN_SOURCES);
625 return 0;
626 }
627 sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
628 ctx->reqExtensions = exts;
629 return 1;
630}
631
632/* returns 1 if ctx contains a Subject Alternative Name extension, else 0 */
633int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx)
634{
635 if (ctx == NULL) {
636 CMPerr(0, CMP_R_NULL_ARGUMENT);
637 return -1;
638 }
639 /* if one of the following conditions 'fail' this is not an error */
640 return ctx->reqExtensions != NULL
641 && X509v3_get_ext_by_NID(ctx->reqExtensions,
642 NID_subject_alt_name, -1) >= 0;
643}
644
645/*
646 * Add a GENERAL_NAME structure that will be added to the CRMF
647 * request's extensions field to request subject alternative names.
7960dbec
DDO
648 */
649int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
650 const GENERAL_NAME *name)
651{
652 GENERAL_NAME *name_dup;
653
654 if (ctx == NULL || name == NULL) {
655 CMPerr(0, CMP_R_NULL_ARGUMENT);
656 return 0;
657 }
658
659 if (OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1) {
660 CMPerr(0, CMP_R_MULTIPLE_SAN_SOURCES);
661 return 0;
662 }
663
664 if (ctx->subjectAltNames == NULL
665 && (ctx->subjectAltNames = sk_GENERAL_NAME_new_null()) == NULL)
666 return 0;
667 if ((name_dup = GENERAL_NAME_dup(name)) == NULL)
668 return 0;
669 if (!sk_GENERAL_NAME_push(ctx->subjectAltNames, name_dup)) {
670 GENERAL_NAME_free(name_dup);
671 return 0;
672 }
673 return 1;
674}
675
676/*
677 * Set our own client certificate, used for example in KUR and when
678 * doing the IR with existing certificate.
7960dbec 679 */
63f1883d 680DEFINE_OSSL_CMP_CTX_set1_up_ref(cert, X509)
7960dbec
DDO
681
682/*
683 * Set the old certificate that we are updating in KUR
684 * or the certificate to be revoked in RR, respectively.
63f1883d 685 * Also used as reference cert (defaulting to cert) for deriving subject DN
7960dbec 686 * and SANs. Its issuer is used as default recipient in the CMP message header.
7960dbec
DDO
687 */
688DEFINE_OSSL_CMP_CTX_set1_up_ref(oldCert, X509)
689
afe554c2 690/* Set the PKCS#10 CSR to be sent in P10CR */
7960dbec
DDO
691DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ)
692
693/*
afe554c2 694 * Set the (newly received in IP/KUP/CP) certificate in the context.
7960dbec
DDO
695 * TODO: this only permits for one cert to be enrolled at a time.
696 */
697int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert)
698{
699 if (!ossl_assert(ctx != NULL))
700 return 0;
701
702 X509_free(ctx->newCert);
703 ctx->newCert = cert;
704 return 1;
705}
706
707/*
708 * Get the (newly received in IP/KUP/CP) client certificate from the context
709 * TODO: this only permits for one client cert to be received...
710 */
711X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx)
712{
713 if (ctx == NULL) {
714 CMPerr(0, CMP_R_NULL_ARGUMENT);
715 return NULL;
716 }
717 return ctx->newCert;
718}
719
afe554c2 720/* Set the client's current private key */
7960dbec
DDO
721DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY)
722
afe554c2 723/* Set new key pair. Used e.g. when doing Key Update */
7960dbec
DDO
724int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
725{
726 if (ctx == NULL) {
727 CMPerr(0, CMP_R_NULL_ARGUMENT);
728 return 0;
729 }
730
731 EVP_PKEY_free(ctx->newPkey);
732 ctx->newPkey = pkey;
733 ctx->newPkey_priv = priv;
734 return 1;
735}
736
afe554c2 737/* Get the private/public key to use for cert enrollment, or NULL on error */
7960dbec
DDO
738EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv)
739{
740 if (ctx == NULL) {
741 CMPerr(0, CMP_R_NULL_ARGUMENT);
742 return NULL;
743 }
744
745 if (ctx->newPkey != NULL)
746 return priv && !ctx->newPkey_priv ? NULL : ctx->newPkey;
747 if (ctx->p10CSR != NULL)
748 return priv ? NULL : X509_REQ_get0_pubkey(ctx->p10CSR);
749 return ctx->pkey; /* may be NULL */
750}
751
afe554c2 752/* Set the given transactionID to the context */
7960dbec
DDO
753int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
754 const ASN1_OCTET_STRING *id)
755{
756 if (ctx == NULL) {
757 CMPerr(0, CMP_R_NULL_ARGUMENT);
758 return 0;
759 }
760 return ossl_cmp_asn1_octet_string_set1(&ctx->transactionID, id);
761}
762
afe554c2 763/* Set the nonce to be used for the recipNonce in the message created next */
7960dbec 764int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
ebf30069 765 const ASN1_OCTET_STRING *nonce)
7960dbec
DDO
766{
767 if (!ossl_assert(ctx != NULL))
768 return 0;
769 return ossl_cmp_asn1_octet_string_set1(&ctx->recipNonce, nonce);
770}
771
afe554c2 772/* Stores the given nonce as the last senderNonce sent out */
7960dbec
DDO
773int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
774 const ASN1_OCTET_STRING *nonce)
775{
776 if (ctx == NULL) {
777 CMPerr(0, CMP_R_NULL_ARGUMENT);
778 return 0;
779 }
780 return ossl_cmp_asn1_octet_string_set1(&ctx->senderNonce, nonce);
781}
782
afe554c2
DDO
783/* Set the proxy server to use for HTTP(S) connections */
784DEFINE_OSSL_CMP_CTX_set1(proxy, char)
7960dbec 785
afe554c2 786/* Set the (HTTP) host name of the CMP server */
4b1fe471 787DEFINE_OSSL_CMP_CTX_set1(server, char)
7960dbec 788
afe554c2
DDO
789/* Set the server exclusion list of the HTTP proxy server */
790DEFINE_OSSL_CMP_CTX_set1(no_proxy, char)
7960dbec 791
afe554c2 792/* Set the http connect/disconnect callback function to be used for HTTP(S) */
29f178bd 793int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
7960dbec
DDO
794{
795 if (ctx == NULL) {
796 CMPerr(0, CMP_R_NULL_ARGUMENT);
797 return 0;
798 }
799 ctx->http_cb = cb;
800 return 1;
801}
802
afe554c2 803/* Set argument optionally to be used by the http connect/disconnect callback */
7960dbec
DDO
804int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
805{
806 if (ctx == NULL) {
807 CMPerr(0, CMP_R_NULL_ARGUMENT);
808 return 0;
809 }
810 ctx->http_cb_arg = arg;
811 return 1;
812}
813
814/*
815 * Get argument optionally to be used by the http connect/disconnect callback
816 * Returns callback argument set previously (NULL if not set or on error)
817 */
818void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx)
819{
820 if (ctx == NULL) {
821 CMPerr(0, CMP_R_NULL_ARGUMENT);
822 return NULL;
823 }
824 return ctx->http_cb_arg;
825}
826
afe554c2 827/* Set callback function for sending CMP request and receiving response */
7e765f46 828int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb)
7960dbec
DDO
829{
830 if (ctx == NULL) {
831 CMPerr(0, CMP_R_NULL_ARGUMENT);
832 return 0;
833 }
834 ctx->transfer_cb = cb;
835 return 1;
836}
837
afe554c2 838/* Set argument optionally to be used by the transfer callback */
7960dbec
DDO
839int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
840{
841 if (ctx == NULL) {
842 CMPerr(0, CMP_R_NULL_ARGUMENT);
843 return 0;
844 }
845 ctx->transfer_cb_arg = arg;
846 return 1;
847}
848
849/*
850 * Get argument optionally to be used by the transfer callback.
851 * Returns callback argument set previously (NULL if not set or on error)
852 */
853void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx)
854{
855 if (ctx == NULL) {
856 CMPerr(0, CMP_R_NULL_ARGUMENT);
857 return NULL;
858 }
859 return ctx->transfer_cb_arg;
860}
861
afe554c2 862/** Set the HTTP server port to be used */
7960dbec
DDO
863int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
864{
865 if (ctx == NULL) {
866 CMPerr(0, CMP_R_NULL_ARGUMENT);
867 return 0;
868 }
869 ctx->serverPort = port;
870 return 1;
871}
872
afe554c2 873/* Set the HTTP path to be used on the server (e.g "pkix/") */
7960dbec
DDO
874DEFINE_OSSL_CMP_CTX_set1(serverPath, char)
875
afe554c2 876/* Set the failInfo error code as bit encoding in OSSL_CMP_CTX */
7960dbec
DDO
877int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info)
878{
879 if (!ossl_assert(ctx != NULL))
880 return 0;
881 ctx->failInfoCode = fail_info;
882 return 1;
883}
884
885/*
886 * Get the failInfo error code in OSSL_CMP_CTX as bit encoding.
887 * Returns bit string as integer on success, -1 on error
888 */
889int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx)
890{
891 if (ctx == NULL) {
892 CMPerr(0, CMP_R_NULL_ARGUMENT);
893 return -1;
894 }
895 return ctx->failInfoCode;
896}
897
afe554c2 898/* Set a Boolean or integer option of the context to the "val" arg */
3dbc5156
DDO
899int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
900{
7960dbec
DDO
901 int min_val;
902
903 if (ctx == NULL) {
904 CMPerr(0, CMP_R_NULL_ARGUMENT);
905 return 0;
906 }
907
908 switch (opt) {
909 case OSSL_CMP_OPT_REVOCATION_REASON:
910 min_val = OCSP_REVOKED_STATUS_NOSTATUS;
911 break;
7e765f46 912 case OSSL_CMP_OPT_POPO_METHOD:
7960dbec
DDO
913 min_val = OSSL_CRMF_POPO_NONE;
914 break;
915 default:
916 min_val = 0;
917 break;
918 }
919 if (val < min_val) {
11baa470 920 CMPerr(0, CMP_R_VALUE_TOO_SMALL);
7960dbec
DDO
921 return 0;
922 }
923
924 switch (opt) {
925 case OSSL_CMP_OPT_LOG_VERBOSITY:
926 if (val > OSSL_CMP_LOG_DEBUG) {
11baa470 927 CMPerr(0, CMP_R_VALUE_TOO_LARGE);
7960dbec
DDO
928 return 0;
929 }
930 ctx->log_verbosity = val;
931 break;
7e765f46 932 case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
7960dbec
DDO
933 ctx->implicitConfirm = val;
934 break;
7e765f46 935 case OSSL_CMP_OPT_DISABLE_CONFIRM:
7960dbec
DDO
936 ctx->disableConfirm = val;
937 break;
938 case OSSL_CMP_OPT_UNPROTECTED_SEND:
939 ctx->unprotectedSend = val;
940 break;
941 case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
942 ctx->unprotectedErrors = val;
943 break;
7e765f46 944 case OSSL_CMP_OPT_VALIDITY_DAYS:
7960dbec
DDO
945 ctx->days = val;
946 break;
947 case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
948 ctx->SubjectAltName_nodefault = val;
949 break;
950 case OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL:
951 ctx->setSubjectAltNameCritical = val;
952 break;
953 case OSSL_CMP_OPT_POLICIES_CRITICAL:
954 ctx->setPoliciesCritical = val;
955 break;
956 case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
957 ctx->ignore_keyusage = val;
958 break;
7e765f46 959 case OSSL_CMP_OPT_POPO_METHOD:
7960dbec 960 if (val > OSSL_CRMF_POPO_KEYAGREE) {
11baa470 961 CMPerr(0, CMP_R_VALUE_TOO_LARGE);
7960dbec
DDO
962 return 0;
963 }
964 ctx->popoMethod = val;
965 break;
966 case OSSL_CMP_OPT_DIGEST_ALGNID:
967 ctx->digest = val;
968 break;
969 case OSSL_CMP_OPT_OWF_ALGNID:
970 ctx->pbm_owf = val;
971 break;
972 case OSSL_CMP_OPT_MAC_ALGNID:
973 ctx->pbm_mac = val;
974 break;
7e765f46
DDO
975 case OSSL_CMP_OPT_MSG_TIMEOUT:
976 ctx->msg_timeout = val;
7960dbec 977 break;
7e765f46
DDO
978 case OSSL_CMP_OPT_TOTAL_TIMEOUT:
979 ctx->total_timeout = val;
7960dbec
DDO
980 break;
981 case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
982 ctx->permitTAInExtraCertsForIR = val;
983 break;
984 case OSSL_CMP_OPT_REVOCATION_REASON:
985 if (val > OCSP_REVOKED_STATUS_AACOMPROMISE) {
11baa470 986 CMPerr(0, CMP_R_VALUE_TOO_LARGE);
7960dbec
DDO
987 return 0;
988 }
989 ctx->revocationReason = val;
990 break;
991 default:
11baa470 992 CMPerr(0, CMP_R_INVALID_OPTION);
7960dbec
DDO
993 return 0;
994 }
995
996 return 1;
997}
998
999/*
1000 * Reads a Boolean or integer option value from the context.
1001 * Returns -1 on error (which is the default OSSL_CMP_OPT_REVOCATION_REASON)
1002 */
3dbc5156
DDO
1003int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
1004{
7960dbec
DDO
1005 if (ctx == NULL) {
1006 CMPerr(0, CMP_R_NULL_ARGUMENT);
1007 return -1;
1008 }
1009
1010 switch (opt) {
1011 case OSSL_CMP_OPT_LOG_VERBOSITY:
1012 return ctx->log_verbosity;
7e765f46 1013 case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
7960dbec 1014 return ctx->implicitConfirm;
7e765f46 1015 case OSSL_CMP_OPT_DISABLE_CONFIRM:
7960dbec
DDO
1016 return ctx->disableConfirm;
1017 case OSSL_CMP_OPT_UNPROTECTED_SEND:
1018 return ctx->unprotectedSend;
1019 case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
1020 return ctx->unprotectedErrors;
7e765f46 1021 case OSSL_CMP_OPT_VALIDITY_DAYS:
7960dbec
DDO
1022 return ctx->days;
1023 case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
1024 return ctx->SubjectAltName_nodefault;
1025 case OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL:
1026 return ctx->setSubjectAltNameCritical;
1027 case OSSL_CMP_OPT_POLICIES_CRITICAL:
1028 return ctx->setPoliciesCritical;
1029 case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
1030 return ctx->ignore_keyusage;
7e765f46 1031 case OSSL_CMP_OPT_POPO_METHOD:
7960dbec
DDO
1032 return ctx->popoMethod;
1033 case OSSL_CMP_OPT_DIGEST_ALGNID:
1034 return ctx->digest;
1035 case OSSL_CMP_OPT_OWF_ALGNID:
1036 return ctx->pbm_owf;
1037 case OSSL_CMP_OPT_MAC_ALGNID:
1038 return ctx->pbm_mac;
7e765f46
DDO
1039 case OSSL_CMP_OPT_MSG_TIMEOUT:
1040 return ctx->msg_timeout;
1041 case OSSL_CMP_OPT_TOTAL_TIMEOUT:
1042 return ctx->total_timeout;
7960dbec
DDO
1043 case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
1044 return ctx->permitTAInExtraCertsForIR;
1045 case OSSL_CMP_OPT_REVOCATION_REASON:
1046 return ctx->revocationReason;
1047 default:
11baa470 1048 CMPerr(0, CMP_R_INVALID_OPTION);
7960dbec
DDO
1049 return -1;
1050 }
1051}