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