]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/cmp/cmp_util.c
2 * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright Nokia 2007-2019
4 * Copyright Siemens AG 2015-2019
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
13 #include <openssl/cmp_util.h>
14 #include "cmp_local.h" /* just for decls of internal functions defined here */
15 #include <openssl/cmperr.h>
16 #include <openssl/err.h> /* should be implied by cmperr.h */
17 #include <openssl/x509v3.h>
20 DEFINE_STACK_OF(X509_OBJECT
)
21 DEFINE_STACK_OF(ASN1_UTF8STRING
)
24 * use trace API for CMP-specific logging, prefixed by "CMP " and severity
27 int OSSL_CMP_log_open(void) /* is designed to be idempotent */
29 #ifndef OPENSSL_NO_STDIO
30 BIO
*bio
= BIO_new_fp(stdout
, BIO_NOCLOSE
);
32 if (bio
!= NULL
&& OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_CMP
, bio
))
36 CMPerr(0, CMP_R_NO_STDIO
);
40 void OSSL_CMP_log_close(void) /* is designed to be idempotent */
42 (void)OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_CMP
, NULL
);
45 /* return >= 0 if level contains logging level, possibly preceded by "CMP " */
46 #define max_level_len 5 /* = max length of the below strings, e.g., "EMERG" */
47 static OSSL_CMP_severity
parse_level(const char *level
)
49 const char *end_level
= strchr(level
, ':');
51 char level_copy
[max_level_len
+ 1];
53 if (end_level
== NULL
)
56 if (strncmp(level
, OSSL_CMP_LOG_PREFIX
,
57 strlen(OSSL_CMP_LOG_PREFIX
)) == 0)
58 level
+= strlen(OSSL_CMP_LOG_PREFIX
);
59 len
= end_level
- level
;
60 if (len
> max_level_len
)
62 OPENSSL_strlcpy(level_copy
, level
, len
+ 1);
64 strcmp(level_copy
, "EMERG") == 0 ? OSSL_CMP_LOG_EMERG
:
65 strcmp(level_copy
, "ALERT") == 0 ? OSSL_CMP_LOG_ALERT
:
66 strcmp(level_copy
, "CRIT") == 0 ? OSSL_CMP_LOG_CRIT
:
67 strcmp(level_copy
, "ERROR") == 0 ? OSSL_CMP_LOG_ERR
:
68 strcmp(level_copy
, "WARN") == 0 ? OSSL_CMP_LOG_WARNING
:
69 strcmp(level_copy
, "NOTE") == 0 ? OSSL_CMP_LOG_NOTICE
:
70 strcmp(level_copy
, "INFO") == 0 ? OSSL_CMP_LOG_INFO
:
71 strcmp(level_copy
, "DEBUG") == 0 ? OSSL_CMP_LOG_DEBUG
:
75 const char *ossl_cmp_log_parse_metadata(const char *buf
,
76 OSSL_CMP_severity
*level
,
77 char **func
, char **file
, int *line
)
79 const char *p_func
= buf
;
80 const char *p_file
= buf
== NULL
? NULL
: strchr(buf
, ':');
81 const char *p_level
= buf
;
82 const char *msg
= buf
;
90 const char *p_line
= strchr(++p_file
, ':');
92 if ((*level
= parse_level(buf
)) < 0 && p_line
!= NULL
) {
93 /* check if buf contains location info and logging level */
94 char *p_level_tmp
= (char *)p_level
;
95 const long line_number
= strtol(++p_line
, &p_level_tmp
, 10);
97 p_level
= p_level_tmp
;
98 if (p_level
> p_line
&& *(p_level
++) == ':') {
99 if ((*level
= parse_level(p_level
)) >= 0) {
100 *func
= OPENSSL_strndup(p_func
, p_file
- 1 - p_func
);
101 *file
= OPENSSL_strndup(p_file
, p_line
- 1 - p_file
);
102 /* no real problem if OPENSSL_strndup() returns NULL */
103 *line
= (int)line_number
;
104 msg
= strchr(p_level
, ':') + 1;
114 #define UNKNOWN_FUNC "(unknown function)" /* the default for OPENSSL_FUNC */
116 * substitute fallback if component/function name is NULL or empty or contains
117 * just pseudo-information "(unknown function)" due to -pedantic and macros.h
119 static const char *improve_location_name(const char *func
, const char *fallback
)
121 if (fallback
== NULL
)
122 return func
== NULL
? UNKNOWN_FUNC
: func
;
124 return func
== NULL
|| *func
== '\0' || strcmp(func
, UNKNOWN_FUNC
) == 0
128 int OSSL_CMP_print_to_bio(BIO
*bio
, const char *component
, const char *file
,
129 int line
, OSSL_CMP_severity level
, const char *msg
)
131 const char *level_string
=
132 level
== OSSL_CMP_LOG_EMERG
? "EMERG" :
133 level
== OSSL_CMP_LOG_ALERT
? "ALERT" :
134 level
== OSSL_CMP_LOG_CRIT
? "CRIT" :
135 level
== OSSL_CMP_LOG_ERR
? "error" :
136 level
== OSSL_CMP_LOG_WARNING
? "warning" :
137 level
== OSSL_CMP_LOG_NOTICE
? "NOTE" :
138 level
== OSSL_CMP_LOG_INFO
? "info" :
139 level
== OSSL_CMP_LOG_DEBUG
? "DEBUG" : "(unknown level)";
142 if (BIO_printf(bio
, "%s:%s:%d:", improve_location_name(component
, "CMP"),
146 return BIO_printf(bio
, OSSL_CMP_LOG_PREFIX
"%s: %s\n",
147 level_string
, msg
) >= 0;
150 #define ERR_PRINT_BUF_SIZE 4096
151 /* this is similar to ERR_print_errors_cb, but uses the CMP-specific cb type */
152 void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn
)
155 char msg
[ERR_PRINT_BUF_SIZE
];
156 const char *file
= NULL
, *func
= NULL
, *data
= NULL
;
159 while ((err
= ERR_get_error_all(&file
, &line
, &func
, &data
, &flags
)) != 0) {
160 const char *component
=
161 improve_location_name(func
, ERR_lib_error_string(err
));
163 if (!(flags
& ERR_TXT_STRING
))
165 BIO_snprintf(msg
, sizeof(msg
), "%s%s%s", ERR_reason_error_string(err
),
166 data
== NULL
|| *data
== '\0' ? "" : " : ",
167 data
== NULL
? "" : data
);
168 if (log_fn
== NULL
) {
169 #ifndef OPENSSL_NO_STDIO
170 BIO
*bio
= BIO_new_fp(stderr
, BIO_NOCLOSE
);
173 OSSL_CMP_print_to_bio(bio
, component
, file
, line
,
174 OSSL_CMP_LOG_ERR
, msg
);
178 /* CMPerr(0, CMP_R_NO_STDIO) makes no sense during error printing */
181 if (log_fn(component
, file
, line
, OSSL_CMP_LOG_ERR
, msg
) <= 0)
182 break; /* abort outputting the error report */
188 * functions manipulating lists of certificates etc.
189 * these functions could be generally useful.
192 int ossl_cmp_sk_X509_add1_cert(STACK_OF(X509
) *sk
, X509
*cert
,
193 int no_dup
, int prepend
)
196 CMPerr(0, CMP_R_NULL_ARGUMENT
);
201 * not using sk_X509_set_cmp_func() and sk_X509_find()
202 * because this re-orders the certs on the stack
206 for (i
= 0; i
< sk_X509_num(sk
); i
++) {
207 if (X509_cmp(sk_X509_value(sk
, i
), cert
) == 0)
211 if (!X509_up_ref(cert
))
213 if (!sk_X509_insert(sk
, cert
, prepend
? 0 : -1)) {
220 int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509
) *sk
, STACK_OF(X509
) *certs
,
221 int no_self_issued
, int no_dups
, int prepend
)
222 /* compiler would allow 'const' for the list of certs, yet they are up-ref'ed */
227 CMPerr(0, CMP_R_NULL_ARGUMENT
);
230 for (i
= 0; i
< sk_X509_num(certs
); i
++) { /* certs may be NULL */
231 X509
*cert
= sk_X509_value(certs
, i
);
233 if (!no_self_issued
|| X509_check_issued(cert
, cert
) != X509_V_OK
) {
234 if (!ossl_cmp_sk_X509_add1_cert(sk
, cert
, no_dups
, prepend
))
241 int ossl_cmp_X509_STORE_add1_certs(X509_STORE
*store
, STACK_OF(X509
) *certs
,
242 int only_self_issued
)
247 CMPerr(0, CMP_R_NULL_ARGUMENT
);
252 for (i
= 0; i
< sk_X509_num(certs
); i
++) {
253 X509
*cert
= sk_X509_value(certs
, i
);
255 if (!only_self_issued
|| X509_check_issued(cert
, cert
) == X509_V_OK
)
256 if (!X509_STORE_add_cert(store
, cert
)) /* ups cert ref counter */
263 * Builds up the certificate chain of certs as high up as possible using
264 * the given list of certs containing all possible intermediate certificates and
265 * optionally the (possible) trust anchor(s). See also ssl_add_cert_chain().
267 * Intended use of this function is to find all the certificates above the trust
268 * anchor needed to verify an EE's own certificate. Those are supposed to be
269 * included in the ExtraCerts field of every first sent message of a transaction
270 * when MSG_SIG_ALG is utilized.
272 * NOTE: This allocates a stack and increments the reference count of each cert,
273 * so when not needed any more the stack and all its elements should be freed.
274 * NOTE: in case there is more than one possibility for the chain,
275 * OpenSSL seems to take the first one, check X509_verify_cert() for details.
277 * returns a pointer to a stack of (up_ref'ed) X509 certificates containing:
278 * - the EE certificate given in the function arguments (cert)
279 * - all intermediate certificates up the chain toward the trust anchor
280 * whereas the (self-signed) trust anchor is not included
281 * returns NULL on error
283 STACK_OF(X509
) *ossl_cmp_build_cert_chain(STACK_OF(X509
) *certs
, X509
*cert
)
285 STACK_OF(X509
) *chain
= NULL
, *result
= NULL
;
286 X509_STORE
*store
= X509_STORE_new();
287 X509_STORE_CTX
*csc
= NULL
;
289 if (certs
== NULL
|| cert
== NULL
|| store
== NULL
) {
290 CMPerr(0, CMP_R_NULL_ARGUMENT
);
294 csc
= X509_STORE_CTX_new();
298 if (!ossl_cmp_X509_STORE_add1_certs(store
, certs
, 0)
299 || !X509_STORE_CTX_init(csc
, store
, cert
, NULL
))
302 (void)ERR_set_mark();
304 * ignore return value as it would fail without trust anchor given in store
306 (void)X509_verify_cert(csc
);
308 /* don't leave any new errors in the queue */
309 (void)ERR_pop_to_mark();
311 chain
= X509_STORE_CTX_get0_chain(csc
);
313 /* result list to store the up_ref'ed not self-issued certificates */
314 if ((result
= sk_X509_new_null()) == NULL
)
316 if (!ossl_cmp_sk_X509_add1_certs(result
, chain
, 1 /* no self-issued */,
317 1 /* no duplicates */, 0)) {
318 sk_X509_free(result
);
323 X509_STORE_free(store
);
324 X509_STORE_CTX_free(csc
);
328 int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING
) *sk
,
331 ASN1_UTF8STRING
*utf8string
;
333 if (!ossl_assert(sk
!= NULL
&& text
!= NULL
))
335 if ((utf8string
= ASN1_UTF8STRING_new()) == NULL
)
337 if (!ASN1_STRING_set(utf8string
, text
, -1))
339 if (!sk_ASN1_UTF8STRING_push(sk
, utf8string
))
344 ASN1_UTF8STRING_free(utf8string
);
348 int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING
**tgt
,
349 const ASN1_OCTET_STRING
*src
)
351 ASN1_OCTET_STRING
*new;
353 CMPerr(0, CMP_R_NULL_ARGUMENT
);
356 if (*tgt
== src
) /* self-assignment */
360 if ((new = ASN1_OCTET_STRING_dup(src
)) == NULL
)
366 ASN1_OCTET_STRING_free(*tgt
);
371 int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING
**tgt
,
372 const unsigned char *bytes
, int len
)
374 ASN1_OCTET_STRING
*new = NULL
;
377 CMPerr(0, CMP_R_NULL_ARGUMENT
);
381 if ((new = ASN1_OCTET_STRING_new()) == NULL
382 || !(ASN1_OCTET_STRING_set(new, bytes
, len
))) {
383 ASN1_OCTET_STRING_free(new);
388 ASN1_OCTET_STRING_free(*tgt
);