2 * Copyright 2007-2019 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 * use trace API for CMP-specific logging, prefixed by "CMP " and severity
23 int OSSL_CMP_log_open(void) /* is designed to be idempotent */
25 #ifndef OPENSSL_NO_STDIO
26 BIO
*bio
= BIO_new_fp(stdout
, BIO_NOCLOSE
);
28 if (bio
!= NULL
&& OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_CMP
, bio
))
32 CMPerr(0, CMP_R_NO_STDIO
);
36 void OSSL_CMP_log_close(void) /* is designed to be idempotent */
38 (void)OSSL_trace_set_channel(OSSL_TRACE_CATEGORY_CMP
, NULL
);
41 /* return >= 0 if level contains logging level, possibly preceded by "CMP " */
42 #define max_level_len 5 /* = max length of the below strings, e.g., "EMERG" */
43 static OSSL_CMP_severity
parse_level(const char *level
)
45 const char *end_level
= strchr(level
, ':');
47 char level_copy
[max_level_len
+ 1];
49 if (end_level
== NULL
)
52 if (strncmp(level
, OSSL_CMP_LOG_PREFIX
,
53 strlen(OSSL_CMP_LOG_PREFIX
)) == 0)
54 level
+= strlen(OSSL_CMP_LOG_PREFIX
);
55 len
= end_level
- level
;
56 if (len
> max_level_len
)
58 OPENSSL_strlcpy(level_copy
, level
, len
+ 1);
60 strcmp(level_copy
, "EMERG") == 0 ? OSSL_CMP_LOG_EMERG
:
61 strcmp(level_copy
, "ALERT") == 0 ? OSSL_CMP_LOG_ALERT
:
62 strcmp(level_copy
, "CRIT") == 0 ? OSSL_CMP_LOG_CRIT
:
63 strcmp(level_copy
, "ERROR") == 0 ? OSSL_CMP_LOG_ERR
:
64 strcmp(level_copy
, "WARN") == 0 ? OSSL_CMP_LOG_WARNING
:
65 strcmp(level_copy
, "NOTE") == 0 ? OSSL_CMP_LOG_NOTICE
:
66 strcmp(level_copy
, "INFO") == 0 ? OSSL_CMP_LOG_INFO
:
67 strcmp(level_copy
, "DEBUG") == 0 ? OSSL_CMP_LOG_DEBUG
:
71 const char *ossl_cmp_log_parse_metadata(const char *buf
,
72 OSSL_CMP_severity
*level
,
73 char **func
, char **file
, int *line
)
75 const char *p_func
= buf
;
76 const char *p_file
= buf
== NULL
? NULL
: strchr(buf
, ':');
77 const char *p_level
= buf
;
78 const char *msg
= buf
;
86 const char *p_line
= strchr(++p_file
, ':');
88 if ((*level
= parse_level(buf
)) < 0 && p_line
!= NULL
) {
89 /* check if buf contains location info and logging level */
90 char *p_level_tmp
= (char *)p_level
;
91 const long line_number
= strtol(++p_line
, &p_level_tmp
, 10);
93 p_level
= p_level_tmp
;
94 if (p_level
> p_line
&& *(p_level
++) == ':') {
95 if ((*level
= parse_level(p_level
)) >= 0) {
96 *func
= OPENSSL_strndup(p_func
, p_file
- 1 - p_func
);
97 *file
= OPENSSL_strndup(p_file
, p_line
- 1 - p_file
);
98 /* no real problem if OPENSSL_strndup() returns NULL */
99 *line
= (int)line_number
;
100 msg
= strchr(p_level
, ':') + 1;
110 #define UNKNOWN_FUNC "(unknown function)" /* the default for OPENSSL_FUNC */
112 * substitute fallback if component/function name is NULL or empty or contains
113 * just pseudo-information "(unknown function)" due to -pedantic and macros.h
115 static const char *improve_location_name(const char *func
, const char *fallback
)
117 if (!ossl_assert(fallback
!= NULL
))
119 return func
== NULL
|| *func
== '\0' || strcmp(func
, UNKNOWN_FUNC
) == 0
123 int OSSL_CMP_print_to_bio(BIO
*bio
, const char *component
, const char *file
,
124 int line
, OSSL_CMP_severity level
, const char *msg
)
126 const char *level_string
=
127 level
== OSSL_CMP_LOG_EMERG
? "EMERG" :
128 level
== OSSL_CMP_LOG_ALERT
? "ALERT" :
129 level
== OSSL_CMP_LOG_CRIT
? "CRIT" :
130 level
== OSSL_CMP_LOG_ERR
? "error" :
131 level
== OSSL_CMP_LOG_WARNING
? "warning" :
132 level
== OSSL_CMP_LOG_NOTICE
? "NOTE" :
133 level
== OSSL_CMP_LOG_INFO
? "info" :
134 level
== OSSL_CMP_LOG_DEBUG
? "DEBUG" : "(unknown level)";
137 if (BIO_printf(bio
, "%s:%s:%d:", improve_location_name(component
, "CMP"),
141 return BIO_printf(bio
, OSSL_CMP_LOG_PREFIX
"%s: %s\n",
142 level_string
, msg
) >= 0;
145 #define ERR_PRINT_BUF_SIZE 4096
146 /* this is similar to ERR_print_errors_cb, but uses the CMP-specific cb type */
147 void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn
)
150 char msg
[ERR_PRINT_BUF_SIZE
];
151 const char *file
= NULL
, *func
= NULL
, *data
= NULL
;
154 while ((err
= ERR_get_error_all(&file
, &line
, &func
, &data
, &flags
)) != 0) {
155 const char *component
=
156 improve_location_name(func
, ERR_lib_error_string(err
));
158 if (!(flags
& ERR_TXT_STRING
))
160 BIO_snprintf(msg
, sizeof(msg
), "%s%s%s", ERR_reason_error_string(err
),
161 data
== NULL
|| *data
== '\0' ? "" : " : ",
162 data
== NULL
? "" : data
);
163 if (log_fn
== NULL
) {
164 #ifndef OPENSSL_NO_STDIO
165 BIO
*bio
= BIO_new_fp(stderr
, BIO_NOCLOSE
);
168 OSSL_CMP_print_to_bio(bio
, component
, file
, line
,
169 OSSL_CMP_LOG_ERR
, msg
);
173 /* CMPerr(0, CMP_R_NO_STDIO) makes no sense during error printing */
176 if (log_fn(component
, file
, line
, OSSL_CMP_LOG_ERR
, msg
) <= 0)
177 break; /* abort outputting the error report */
183 * functions manipulating lists of certificates etc.
184 * these functions could be generally useful.
187 int ossl_cmp_sk_X509_add1_cert(STACK_OF(X509
) *sk
, X509
*cert
,
188 int no_dup
, int prepend
)
191 CMPerr(0, CMP_R_NULL_ARGUMENT
);
196 * not using sk_X509_set_cmp_func() and sk_X509_find()
197 * because this re-orders the certs on the stack
201 for (i
= 0; i
< sk_X509_num(sk
); i
++) {
202 if (X509_cmp(sk_X509_value(sk
, i
), cert
) == 0)
206 if (!X509_up_ref(cert
))
208 if (!sk_X509_insert(sk
, cert
, prepend
? 0 : -1)) {
215 int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509
) *sk
, STACK_OF(X509
) *certs
,
216 int no_self_issued
, int no_dups
, int prepend
)
217 /* compiler would allow 'const' for the list of certs, yet they are up-ref'ed */
222 CMPerr(0, CMP_R_NULL_ARGUMENT
);
225 for (i
= 0; i
< sk_X509_num(certs
); i
++) { /* certs may be NULL */
226 X509
*cert
= sk_X509_value(certs
, i
);
228 if (!no_self_issued
|| X509_check_issued(cert
, cert
) != X509_V_OK
) {
229 if (!ossl_cmp_sk_X509_add1_cert(sk
, cert
, no_dups
, prepend
))
236 int ossl_cmp_X509_STORE_add1_certs(X509_STORE
*store
, STACK_OF(X509
) *certs
,
237 int only_self_issued
)
242 CMPerr(0, CMP_R_NULL_ARGUMENT
);
247 for (i
= 0; i
< sk_X509_num(certs
); i
++) {
248 X509
*cert
= sk_X509_value(certs
, i
);
250 if (!only_self_issued
|| X509_check_issued(cert
, cert
) == X509_V_OK
)
251 if (!X509_STORE_add_cert(store
, cert
)) /* ups cert ref counter */
258 * Builds up the certificate chain of certs as high up as possible using
259 * the given list of certs containing all possible intermediate certificates and
260 * optionally the (possible) trust anchor(s). See also ssl_add_cert_chain().
262 * Intended use of this function is to find all the certificates above the trust
263 * anchor needed to verify an EE's own certificate. Those are supposed to be
264 * included in the ExtraCerts field of every first sent message of a transaction
265 * when MSG_SIG_ALG is utilized.
267 * NOTE: This allocates a stack and increments the reference count of each cert,
268 * so when not needed any more the stack and all its elements should be freed.
269 * NOTE: in case there is more than one possibility for the chain,
270 * OpenSSL seems to take the first one, check X509_verify_cert() for details.
272 * returns a pointer to a stack of (up_ref'ed) X509 certificates containing:
273 * - the EE certificate given in the function arguments (cert)
274 * - all intermediate certificates up the chain toward the trust anchor
275 * whereas the (self-signed) trust anchor is not included
276 * returns NULL on error
278 STACK_OF(X509
) *ossl_cmp_build_cert_chain(STACK_OF(X509
) *certs
, X509
*cert
)
280 STACK_OF(X509
) *chain
= NULL
, *result
= NULL
;
281 X509_STORE
*store
= X509_STORE_new();
282 X509_STORE_CTX
*csc
= NULL
;
284 if (certs
== NULL
|| cert
== NULL
|| store
== NULL
) {
285 CMPerr(0, CMP_R_NULL_ARGUMENT
);
289 csc
= X509_STORE_CTX_new();
293 if (!ossl_cmp_X509_STORE_add1_certs(store
, certs
, 0)
294 || !X509_STORE_CTX_init(csc
, store
, cert
, NULL
))
297 (void)ERR_set_mark();
299 * ignore return value as it would fail without trust anchor given in store
301 (void)X509_verify_cert(csc
);
303 /* don't leave any new errors in the queue */
304 (void)ERR_pop_to_mark();
306 chain
= X509_STORE_CTX_get0_chain(csc
);
308 /* result list to store the up_ref'ed not self-issued certificates */
309 if ((result
= sk_X509_new_null()) == NULL
)
311 if (!ossl_cmp_sk_X509_add1_certs(result
, chain
, 1 /* no self-issued */,
312 1 /* no duplicates */, 0)) {
313 sk_X509_free(result
);
318 X509_STORE_free(store
);
319 X509_STORE_CTX_free(csc
);
323 int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING
) *sk
,
326 ASN1_UTF8STRING
*utf8string
;
328 if (!ossl_assert(sk
!= NULL
&& text
!= NULL
))
330 if ((utf8string
= ASN1_UTF8STRING_new()) == NULL
)
332 if (!ASN1_STRING_set(utf8string
, text
, -1))
334 if (!sk_ASN1_UTF8STRING_push(sk
, utf8string
))
339 ASN1_UTF8STRING_free(utf8string
);
343 int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING
**tgt
,
344 const ASN1_OCTET_STRING
*src
)
346 ASN1_OCTET_STRING
*new;
348 CMPerr(0, CMP_R_NULL_ARGUMENT
);
351 if (*tgt
== src
) /* self-assignment */
355 if ((new = ASN1_OCTET_STRING_dup(src
)) == NULL
)
361 ASN1_OCTET_STRING_free(*tgt
);
366 int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING
**tgt
,
367 const unsigned char *bytes
, int len
)
369 ASN1_OCTET_STRING
*new = NULL
;
372 CMPerr(0, CMP_R_NULL_ARGUMENT
);
376 if ((new = ASN1_OCTET_STRING_new()) == NULL
377 || !(ASN1_OCTET_STRING_set(new, bytes
, len
))) {
378 ASN1_OCTET_STRING_free(new);
383 ASN1_OCTET_STRING_free(*tgt
);
389 * calculate a digest of the given certificate,
390 * using the same hash algorithm as in the certificate signature.
392 ASN1_OCTET_STRING
*OSSL_CMP_X509_digest(const X509
*cert
)
395 unsigned char hash
[EVP_MAX_MD_SIZE
];
397 const EVP_MD
*md
= NULL
;
398 ASN1_OCTET_STRING
*new = NULL
;
400 if (!ossl_assert(cert
!= NULL
))
404 * select hash algorithm, as stated in CMP RFC 4210 Appendix F.
405 * Compilable ASN.1 defs:
406 * the hash of the certificate, using the same hash algorithm
407 * as is used to create and verify the certificate signature
409 if (!OBJ_find_sigid_algs(X509_get_signature_nid(cert
), &md_NID
, NULL
)
410 || (md
= EVP_get_digestbynid(md_NID
)) == NULL
) {
411 CMPerr(0, CMP_R_UNSUPPORTED_ALGORITHM
);
414 if (!X509_digest(cert
, md
, hash
, &len
)
415 || (new = ASN1_OCTET_STRING_new()) == NULL
)
417 if (!(ASN1_OCTET_STRING_set(new, hash
, len
))) {
418 ASN1_OCTET_STRING_free(new);