summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan M. Wilbur <jonathan@wilbur.space>2024-09-12 12:52:20 +0200
committerTomas Mraz <tomas@openssl.org>2024-09-16 22:56:02 +0200
commit935f6e63c96b44a03e12a7272b01c23956f3d4f3 (patch)
tree49a4cdd32d521618c5f0954b68053cfaa678c070
parenttest: the roleSpecCertIdentifier X.509v3 extension (diff)
downloadopenssl-935f6e63c96b44a03e12a7272b01c23956f3d4f3.tar.xz
openssl-935f6e63c96b44a03e12a7272b01c23956f3d4f3.zip
feat: add ossl_serial_number_print
Reviewed-by: Neil Horman <nhorman@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/25428)
-rw-r--r--crypto/x509/t_x509.c46
-rw-r--r--crypto/x509/v3_rolespec.c2
-rw-r--r--doc/internal/man3/ossl_serial_number_print.pod38
-rw-r--r--include/crypto/x509.h2
-rw-r--r--test/recipes/25-test_x509.t2
5 files changed, 86 insertions, 4 deletions
diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c
index 192998d453..4befbe25da 100644
--- a/crypto/x509/t_x509.c
+++ b/crypto/x509/t_x509.c
@@ -54,11 +54,10 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
unsigned long cflag)
{
long l;
- int ret = 0, i;
+ int ret = 0;
char mlch = ' ';
int nmindent = 0, printok = 0;
EVP_PKEY *pkey = NULL;
- const char *neg;
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mlch = '\n';
@@ -531,3 +530,46 @@ int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx)
return ok;
}
+
+/*
+ * Prints serial numbers in decimal and hexadecimal. The indent argument is only
+ * used if the serial number is too large to fit in a long int.
+ */
+int ossl_serial_number_print(BIO *out, const ASN1_INTEGER *bs, int indent)
+{
+ int i;
+ long l;
+ unsigned long ul;
+ const char *neg;
+
+ if (bs->length <= (int)sizeof(long)) {
+ ERR_set_mark();
+ l = ASN1_INTEGER_get(bs);
+ ERR_pop_to_mark();
+ } else {
+ l = -1;
+ }
+ if (l != -1) { /* Reading a long int succeeded: print decimal and hex. */
+ if (bs->type == V_ASN1_NEG_INTEGER) {
+ ul = 0 - (unsigned long)l;
+ neg = "-";
+ } else {
+ ul = l;
+ neg = "";
+ }
+ if (BIO_printf(out, " %s%lu (%s0x%lx)", neg, ul, neg, ul) <= 0)
+ return -1;
+ } else { /* Reading a long int failed: just print hex. */
+ neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
+ if (BIO_printf(out, "\n%*s%s", indent, "", neg) <= 0)
+ return -1;
+
+ for (i = 0; i < bs->length - 1; i++) {
+ if (BIO_printf(out, "%02x%c", bs->data[i], ':') <= 0)
+ return -1;
+ }
+ if (BIO_printf(out, "%02x", bs->data[i]) <= 0)
+ return -1;
+ }
+ return 0;
+}
diff --git a/crypto/x509/v3_rolespec.c b/crypto/x509/v3_rolespec.c
index c371e145d7..57111b1f0f 100644
--- a/crypto/x509/v3_rolespec.c
+++ b/crypto/x509/v3_rolespec.c
@@ -45,7 +45,7 @@ static int i2r_OSSL_ROLE_SPEC_CERT_ID(X509V3_EXT_METHOD *method,
if (rscid->roleCertSerialNumber != NULL) {
if (BIO_puts(out, "\n") <= 0)
return 0;
- if (BIO_printf(out, "%*sRole Certificate Serial Number: ", indent, "") <= 0)
+ if (BIO_printf(out, "%*sRole Certificate Serial Number:", indent, "") <= 0)
return 0;
if (ossl_serial_number_print(out, rscid->roleCertSerialNumber, indent) != 0)
return 0;
diff --git a/doc/internal/man3/ossl_serial_number_print.pod b/doc/internal/man3/ossl_serial_number_print.pod
new file mode 100644
index 0000000000..9ea4802350
--- /dev/null
+++ b/doc/internal/man3/ossl_serial_number_print.pod
@@ -0,0 +1,38 @@
+=pod
+
+=head1 NAME
+
+ossl_serial_number_print
+- Print a CertificateSerialNumber
+
+=head1 SYNOPSIS
+
+ #include <crypto/x509.h>
+
+ int ossl_serial_number_print(BIO *out, const ASN1_INTEGER *bs, int indent);
+
+=head1 DESCRIPTION
+
+This function writes a certificate serial number I<bs> to BIO I<out> in decimal if the serial
+number can be read into a long int, as well as hexadecimal. It notifies the
+user of negative serial numbers, and handles wrapping of huge serial numbers.
+The output is written to a newline and indented by I<indent> spaces if the
+serial number cannot be read into a long int.
+
+If the serial number fits into a long int, it is printed on the same line as
+whatever precedes it, after a single SPACE character.
+
+=head1 RETURN VALUES
+
+This function returns 0 on success and -1 on failure.
+
+=head1 COPYRIGHT
+
+Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index 338e58b491..332108d1bb 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -394,4 +394,6 @@ int ossl_print_attribute_value(BIO *out,
const ASN1_TYPE *av,
int indent);
+int ossl_serial_number_print(BIO *out, const ASN1_INTEGER *bs, int indent);
+
#endif /* OSSL_CRYPTO_X509_H */
diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t
index 1d458d3362..39440498ef 100644
--- a/test/recipes/25-test_x509.t
+++ b/test/recipes/25-test_x509.t
@@ -323,7 +323,7 @@ cert_contains($role_spec_cert,
"Role Certificate Issuer: DirName:CN",
1, 'X.509 Role Spec Certificate Identifier');
cert_contains($role_spec_cert,
- "Role Certificate Serial Number: 0x02040608",
+ "Role Certificate Serial Number: 33818120 \\(0x2040608\\)",
1, 'X.509 Role Spec Certificate Identifier');
cert_contains($role_spec_cert,
"DNS:wildboarsoftware.com",