]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
feat: add ossl_serial_number_print
authorJonathan M. Wilbur <jonathan@wilbur.space>
Thu, 12 Sep 2024 10:52:20 +0000 (10:52 +0000)
committerTomas Mraz <tomas@openssl.org>
Mon, 16 Sep 2024 20:56:02 +0000 (22:56 +0200)
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25428)

crypto/x509/t_x509.c
crypto/x509/v3_rolespec.c
doc/internal/man3/ossl_serial_number_print.pod [new file with mode: 0644]
include/crypto/x509.h
test/recipes/25-test_x509.t

index 192998d45332c961effbefa2193af80336b1784a..4befbe25daf924e992df1097375892391a6acec5 100644 (file)
@@ -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;
+}
index c371e145d7be0fd72471320b4d657f9b93042afe..57111b1f0f1156da9955d451b71a114e0b258b00 100644 (file)
@@ -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 (file)
index 0000000..9ea4802
--- /dev/null
@@ -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
index 338e58b4919f9a12a31ca3833d968b1016350dc4..332108d1bb588d4dbafb14f7f367e4c00b094f1f 100644 (file)
@@ -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 */
index 1d458d336290923b192c09e9785afecaa9f798a9..39440498efe9320f154258f61cb9f58e25a36db6 100644 (file)
@@ -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",