[edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib

Li, Yi posted 1 patch 1 year, 5 months ago
Failed in applying to current master (apply log)
CryptoPkg/CryptoPkg.ci.yaml                   |   4 +-
.../Library/BaseCryptLib/SysCall/CrtWrapper.c |  27 -
.../SysCall/UnitTestHostCrtWrapper.c          |  25 -
CryptoPkg/Library/OpensslLib/OpensslLib.inf   |   1 +
.../Library/OpensslLib/OpensslLibAccel.inf    |   1 +
.../Library/OpensslLib/OpensslLibCrypto.inf   |   1 +
.../Library/OpensslLib/OpensslLibFull.inf     |   1 +
.../OpensslLib/OpensslLibFullAccel.inf        |   1 +
CryptoPkg/Library/OpensslLib/b_print.c        | 613 ++++++++++++++++++
9 files changed, 621 insertions(+), 53 deletions(-)
create mode 100644 CryptoPkg/Library/OpensslLib/b_print.c
[edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib
Posted by Li, Yi 1 year, 5 months ago
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4110

Openssl will use BIO_snprintf() to print time string when converting
time_t to ASN1_time.
Currently edk2 code just give it a NULL implement in CrtWrapper.c, so
getting current time in X509 time check will be fail.

This patch add a copy of OpensslLib\openssl\crypto\bio\b_print.c to
OpensslLib, with below changes:

1. All floating point related code removed.
2. Replace ull divide and remainder with DivU64x32Remainder().

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
---
 CryptoPkg/CryptoPkg.ci.yaml                   |   4 +-
 .../Library/BaseCryptLib/SysCall/CrtWrapper.c |  27 -
 .../SysCall/UnitTestHostCrtWrapper.c          |  25 -
 CryptoPkg/Library/OpensslLib/OpensslLib.inf   |   1 +
 .../Library/OpensslLib/OpensslLibAccel.inf    |   1 +
 .../Library/OpensslLib/OpensslLibCrypto.inf   |   1 +
 .../Library/OpensslLib/OpensslLibFull.inf     |   1 +
 .../OpensslLib/OpensslLibFullAccel.inf        |   1 +
 CryptoPkg/Library/OpensslLib/b_print.c        | 613 ++++++++++++++++++
 9 files changed, 621 insertions(+), 53 deletions(-)
 create mode 100644 CryptoPkg/Library/OpensslLib/b_print.c

diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml
index 47f2975967..8c25f581fb 100644
--- a/CryptoPkg/CryptoPkg.ci.yaml
+++ b/CryptoPkg/CryptoPkg.ci.yaml
@@ -13,7 +13,9 @@
             "Library/OpensslLib/IA32Gcc",
             "Library/OpensslLib/X64",
             "Library/OpensslLib/X64Gcc",
-            "Library/Include/openssl"
+            "Library/Include/openssl",
+            # b_print.c is a copy from OpenSSl.
+            "Library/OpensslLib/b_print.c"
         ]
     },
     "EccCheck": {
diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
index b65d29485b..6d7ac3efdc 100644
--- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
+++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
@@ -472,33 +472,6 @@ fwrite (
   return 0;
 }
 
-//
-//  -- Dummy OpenSSL Support Routines --
-//
-
-int
-BIO_printf (
-  void        *bio,
-  const char  *format,
-  ...
-  )
-{
-  return 0;
-}
-
-int
-BIO_snprintf (
-  char        *buf,
-  size_t      n,
-  const char  *format,
-  ...
-  )
-{
-  // Because the function does not actually print anything to buf, it returns -1 as error.
-  // Otherwise, the consumer may think that the buf is valid and parse the buffer.
-  return -1;
-}
-
 #ifdef __GNUC__
 
 typedef
diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
index 066d53e4fa..244e57437e 100644
--- a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
+++ b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
@@ -72,31 +72,6 @@ sscanf (
   return 0;
 }
 
-//
-//  -- Dummy OpenSSL Support Routines --
-//
-
-int
-BIO_printf (
-  void        *bio,
-  const char  *format,
-  ...
-  )
-{
-  return 0;
-}
-
-int
-BIO_snprintf (
-  char        *buf,
-  size_t      n,
-  const char  *format,
-  ...
-  )
-{
-  return 0;
-}
-
 uid_t
 getuid (
   void
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
index 60c6c24b0a..f8ddfadc51 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
@@ -580,6 +580,7 @@
   rand_pool.c
 #  SslNull.c
   EcSm2Null.c
+  b_print.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
index 103ef7bda2..6ee7bfd329 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
@@ -580,6 +580,7 @@
   rand_pool.c
 #  SslNull.c
   EcSm2Null.c
+  b_print.c
 
 [Sources.IA32]
 # Autogenerated IA32 files list starts here
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
index c4eaea888c..3e43cf146b 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
@@ -530,6 +530,7 @@
   rand_pool.c
   SslNull.c
   EcSm2Null.c
+  b_print.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
index 309e43055c..440d3e7e1d 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
@@ -635,6 +635,7 @@
   rand_pool.c
 #  SslNull.c
 #  EcSm2Null.c
+  b_print.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
index 4eeeeb79bd..413f70f733 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
@@ -635,6 +635,7 @@
   rand_pool.c
 #  SslNull.c
 #  EcSm2Null.c
+  b_print.c
 
 [Sources.IA32]
 # Autogenerated IA32 files list starts here
diff --git a/CryptoPkg/Library/OpensslLib/b_print.c b/CryptoPkg/Library/OpensslLib/b_print.c
new file mode 100644
index 0000000000..885c3b9264
--- /dev/null
+++ b/CryptoPkg/Library/OpensslLib/b_print.c
@@ -0,0 +1,613 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (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
+ * https://www.openssl.org/source/license.html
+ *
+ * Please notes:
+ * This file is a copy of OpensslLib\openssl\crypto\bio\b_print.c
+ * with all floating point related code removed (Not supported in UEFI).
+ * This means that '%f' '%g' '%e' and related combined formats are no longer supported.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "internal/cryptlib.h"
+#include "crypto/ctype.h"
+#include "internal/numbers.h"
+#include <openssl/bio.h>
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell <papowell@astart.com>
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions.
+ */
+
+static int fmtstr(char **, char **, size_t *, size_t *,
+                  const char *, int, int, int);
+static int fmtint(char **, char **, size_t *, size_t *,
+                  int64_t, int, int, int, int);
+static int doapr_outch(char **, char **, size_t *, size_t *, int);
+static int _dopr(char **sbuffer, char **buffer,
+                 size_t *maxlen, size_t *retlen, int *truncated,
+                 const char *format, va_list args);
+
+/* format read states */
+#define DP_S_DEFAULT    0
+#define DP_S_FLAGS      1
+#define DP_S_MIN        2
+#define DP_S_DOT        3
+#define DP_S_MAX        4
+#define DP_S_MOD        5
+#define DP_S_CONV       6
+#define DP_S_DONE       7
+
+/* format flags - Bits */
+/* left-aligned padding */
+#define DP_F_MINUS      (1 << 0)
+/* print an explicit '+' for a value with positive sign */
+#define DP_F_PLUS       (1 << 1)
+/* print an explicit ' ' for a value with positive sign */
+#define DP_F_SPACE      (1 << 2)
+/* print 0/0x prefix for octal/hex and decimal point for floating point */
+#define DP_F_NUM        (1 << 3)
+/* print leading zeroes */
+#define DP_F_ZERO       (1 << 4)
+/* print HEX in UPPPERcase */
+#define DP_F_UP         (1 << 5)
+/* treat value as unsigned */
+#define DP_F_UNSIGNED   (1 << 6)
+
+/* conversion flags */
+#define DP_C_SHORT      1
+#define DP_C_LONG       2
+// #define DP_C_LDOUBLE    3
+#define DP_C_LLONG      4
+#define DP_C_SIZE       5
+
+/* Floating point formats */
+// #define F_FORMAT        0
+// #define E_FORMAT        1
+// #define G_FORMAT        2
+
+/* some handy macros */
+#define char_to_int(p) (p - '0')
+#define OSSL_MAX(p,q) ((p >= q) ? p : q)
+
+static int
+_dopr(char **sbuffer,
+      char **buffer,
+      size_t *maxlen,
+      size_t *retlen, int *truncated, const char *format, va_list args)
+{
+    char ch;
+    int64_t value;
+    char *strvalue;
+    int min;
+    int max;
+    int state;
+    int flags;
+    int cflags;
+    size_t currlen;
+
+    state = DP_S_DEFAULT;
+    flags = currlen = cflags = min = 0;
+    max = -1;
+    ch = *format++;
+
+    while (state != DP_S_DONE) {
+        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
+            state = DP_S_DONE;
+
+        switch (state) {
+        case DP_S_DEFAULT:
+            if (ch == '%')
+                state = DP_S_FLAGS;
+            else
+                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+                    return 0;
+            ch = *format++;
+            break;
+        case DP_S_FLAGS:
+            switch (ch) {
+            case '-':
+                flags |= DP_F_MINUS;
+                ch = *format++;
+                break;
+            case '+':
+                flags |= DP_F_PLUS;
+                ch = *format++;
+                break;
+            case ' ':
+                flags |= DP_F_SPACE;
+                ch = *format++;
+                break;
+            case '#':
+                flags |= DP_F_NUM;
+                ch = *format++;
+                break;
+            case '0':
+                flags |= DP_F_ZERO;
+                ch = *format++;
+                break;
+            default:
+                state = DP_S_MIN;
+                break;
+            }
+            break;
+        case DP_S_MIN:
+            if (ossl_isdigit(ch)) {
+                min = 10 * min + char_to_int(ch);
+                ch = *format++;
+            } else if (ch == '*') {
+                min = va_arg(args, int);
+                ch = *format++;
+                state = DP_S_DOT;
+            } else
+                state = DP_S_DOT;
+            break;
+        case DP_S_DOT:
+            if (ch == '.') {
+                state = DP_S_MAX;
+                ch = *format++;
+            } else
+                state = DP_S_MOD;
+            break;
+        case DP_S_MAX:
+            if (ossl_isdigit(ch)) {
+                if (max < 0)
+                    max = 0;
+                max = 10 * max + char_to_int(ch);
+                ch = *format++;
+            } else if (ch == '*') {
+                max = va_arg(args, int);
+                ch = *format++;
+                state = DP_S_MOD;
+            } else
+                state = DP_S_MOD;
+            break;
+        case DP_S_MOD:
+            switch (ch) {
+            case 'h':
+                cflags = DP_C_SHORT;
+                ch = *format++;
+                break;
+            case 'l':
+                if (*format == 'l') {
+                    cflags = DP_C_LLONG;
+                    format++;
+                } else
+                    cflags = DP_C_LONG;
+                ch = *format++;
+                break;
+            case 'q':
+            case 'j':
+                cflags = DP_C_LLONG;
+                ch = *format++;
+                break;
+            case 'L':
+                //Unsupported fmt in UEFI
+                return -1;
+            case 'z':
+                cflags = DP_C_SIZE;
+                ch = *format++;
+                break;
+            default:
+                break;
+            }
+            state = DP_S_CONV;
+            break;
+        case DP_S_CONV:
+            switch (ch) {
+            case 'd':
+            case 'i':
+                switch (cflags) {
+                case DP_C_SHORT:
+                    value = (short int)va_arg(args, int);
+                    break;
+                case DP_C_LONG:
+                    value = va_arg(args, long int);
+                    break;
+                case DP_C_LLONG:
+                    value = va_arg(args, int64_t);
+                    break;
+                case DP_C_SIZE:
+                    value = va_arg(args, ossl_ssize_t);
+                    break;
+                default:
+                    value = va_arg(args, int);
+                    break;
+                }
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
+                            max, flags))
+                    return 0;
+                break;
+            case 'X':
+                flags |= DP_F_UP;
+                /* FALLTHROUGH */
+            case 'x':
+            case 'o':
+            case 'u':
+                flags |= DP_F_UNSIGNED;
+                switch (cflags) {
+                case DP_C_SHORT:
+                    value = (unsigned short int)va_arg(args, unsigned int);
+                    break;
+                case DP_C_LONG:
+                    value = va_arg(args, unsigned long int);
+                    break;
+                case DP_C_LLONG:
+                    value = va_arg(args, uint64_t);
+                    break;
+                case DP_C_SIZE:
+                    value = va_arg(args, size_t);
+                    break;
+                default:
+                    value = va_arg(args, unsigned int);
+                    break;
+                }
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
+                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
+                            min, max, flags))
+                    return 0;
+                break;
+            case 'f':
+            case 'E':
+            case 'e':
+            case 'G':
+            case 'g':
+                return -1;
+            case 'c':
+                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
+                                 va_arg(args, int)))
+                    return 0;
+                break;
+            case 's':
+                strvalue = va_arg(args, char *);
+                if (max < 0) {
+                    if (buffer)
+                        max = INT_MAX;
+                    else
+                        max = *maxlen;
+                }
+                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
+                            flags, min, max))
+                    return 0;
+                break;
+            case 'p':
+                value = (size_t)va_arg(args, void *);
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
+                            value, 16, min, max, flags | DP_F_NUM))
+                    return 0;
+                break;
+            case 'n':
+                {
+                    int *num;
+                    num = va_arg(args, int *);
+                    *num = currlen;
+                }
+                break;
+            case '%':
+                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+                    return 0;
+                break;
+            case 'w':
+                /* not supported yet, treat as next char */
+                ch = *format++;
+                break;
+            default:
+                /* unknown, skip */
+                break;
+            }
+            ch = *format++;
+            state = DP_S_DEFAULT;
+            flags = cflags = min = 0;
+            max = -1;
+            break;
+        case DP_S_DONE:
+            break;
+        default:
+            break;
+        }
+    }
+    /*
+     * We have to truncate if there is no dynamic buffer and we have filled the
+     * static buffer.
+     */
+    if (buffer == NULL) {
+        *truncated = (currlen > *maxlen - 1);
+        if (*truncated)
+            currlen = *maxlen - 1;
+    }
+    if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
+        return 0;
+    *retlen = currlen - 1;
+    return 1;
+}
+
+static int
+fmtstr(char **sbuffer,
+       char **buffer,
+       size_t *currlen,
+       size_t *maxlen, const char *value, int flags, int min, int max)
+{
+    int padlen;
+    size_t strln;
+    int cnt = 0;
+
+    if (value == 0)
+        value = "<NULL>";
+
+    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
+
+    padlen = min - strln;
+    if (min < 0 || padlen < 0)
+        padlen = 0;
+    if (max >= 0) {
+        /*
+         * Calculate the maximum output including padding.
+         * Make sure max doesn't overflow into negativity
+         */
+        if (max < INT_MAX - padlen)
+            max += padlen;
+        else
+            max = INT_MAX;
+    }
+    if (flags & DP_F_MINUS)
+        padlen = -padlen;
+
+    while ((padlen > 0) && (max < 0 || cnt < max)) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
+        --padlen;
+        ++cnt;
+    }
+    while (strln > 0 && (max < 0 || cnt < max)) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
+            return 0;
+        --strln;
+        ++cnt;
+    }
+    while ((padlen < 0) && (max < 0 || cnt < max)) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
+        ++padlen;
+        ++cnt;
+    }
+    return 1;
+}
+
+static int
+fmtint(char **sbuffer,
+       char **buffer,
+       size_t *currlen,
+       size_t *maxlen, int64_t value, int base, int min, int max, int flags)
+{
+    int signvalue = 0;
+    const char *prefix = "";
+    uint64_t uvalue;
+    char convert[DECIMAL_SIZE(value) + 3];
+    int place = 0;
+    int spadlen = 0;
+    int zpadlen = 0;
+    int caps = 0;
+    uint32_t uremainder = 0;
+
+    if (max < 0)
+        max = 0;
+    uvalue = value;
+    if (!(flags & DP_F_UNSIGNED)) {
+        if (value < 0) {
+            signvalue = '-';
+            uvalue = 0 - (uint64_t)value;
+        } else if (flags & DP_F_PLUS)
+            signvalue = '+';
+        else if (flags & DP_F_SPACE)
+            signvalue = ' ';
+    }
+    if (flags & DP_F_NUM) {
+        if (base == 8)
+            prefix = "0";
+        if (base == 16)
+            prefix = "0x";
+    }
+    if (flags & DP_F_UP)
+        caps = 1;
+    do {
+        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, &uremainder);
+        convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+            [uremainder];
+    } while (uvalue && (place < (int)sizeof(convert)));
+    if (place == sizeof(convert))
+        place--;
+    convert[place] = 0;
+
+    zpadlen = max - place;
+    spadlen =
+        min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
+    if (zpadlen < 0)
+        zpadlen = 0;
+    if (spadlen < 0)
+        spadlen = 0;
+    if (flags & DP_F_ZERO) {
+        zpadlen = OSSL_MAX(zpadlen, spadlen);
+        spadlen = 0;
+    }
+    if (flags & DP_F_MINUS)
+        spadlen = -spadlen;
+
+    /* spaces */
+    while (spadlen > 0) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
+        --spadlen;
+    }
+
+    /* sign */
+    if (signvalue)
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+            return 0;
+
+    /* prefix */
+    while (*prefix) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
+            return 0;
+        prefix++;
+    }
+
+    /* zeros */
+    if (zpadlen > 0) {
+        while (zpadlen > 0) {
+            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+                return 0;
+            --zpadlen;
+        }
+    }
+    /* digits */
+    while (place > 0) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
+            return 0;
+    }
+
+    /* left justified spaces */
+    while (spadlen < 0) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
+        ++spadlen;
+    }
+    return 1;
+}
+
+#define BUFFER_INC  1024
+
+static int
+doapr_outch(char **sbuffer,
+            char **buffer, size_t *currlen, size_t *maxlen, int c)
+{
+    /* If we haven't at least one buffer, someone has done a big booboo */
+    if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
+        return 0;
+
+    /* |currlen| must always be <= |*maxlen| */
+    if (!ossl_assert(*currlen <= *maxlen))
+        return 0;
+
+    if (buffer && *currlen == *maxlen) {
+        if (*maxlen > INT_MAX - BUFFER_INC)
+            return 0;
+
+        *maxlen += BUFFER_INC;
+        if (*buffer == NULL) {
+            if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
+                BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+            if (*currlen > 0) {
+                if (!ossl_assert(*sbuffer != NULL))
+                    return 0;
+                memcpy(*buffer, *sbuffer, *currlen);
+            }
+            *sbuffer = NULL;
+        } else {
+            char *tmpbuf;
+            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
+            if (tmpbuf == NULL)
+                return 0;
+            *buffer = tmpbuf;
+        }
+    }
+
+    if (*currlen < *maxlen) {
+        if (*sbuffer)
+            (*sbuffer)[(*currlen)++] = (char)c;
+        else
+            (*buffer)[(*currlen)++] = (char)c;
+    }
+
+    return 1;
+}
+
+/***************************************************************************/
+
+int BIO_printf(BIO *bio, const char *format, ...)
+{
+    va_list args;
+    int ret;
+
+    va_start(args, format);
+
+    ret = BIO_vprintf(bio, format, args);
+
+    va_end(args);
+    return ret;
+}
+
+int BIO_vprintf(BIO *bio, const char *format, va_list args)
+{
+    int ret;
+    size_t retlen;
+    char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
+                                 * in small-stack environments, like threads
+                                 * or DOS programs. */
+    char *hugebufp = hugebuf;
+    size_t hugebufsize = sizeof(hugebuf);
+    char *dynbuf = NULL;
+    int ignored;
+
+    dynbuf = NULL;
+    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
+                args)) {
+        OPENSSL_free(dynbuf);
+        return -1;
+    }
+    if (dynbuf) {
+        ret = BIO_write(bio, dynbuf, (int)retlen);
+        OPENSSL_free(dynbuf);
+    } else {
+        ret = BIO_write(bio, hugebuf, (int)retlen);
+    }
+    return ret;
+}
+
+/*
+ * As snprintf is not available everywhere, we provide our own
+ * implementation. This function has nothing to do with BIOs, but it's
+ * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
+ * function should be renamed, but to what?)
+ */
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+{
+    va_list args;
+    int ret;
+
+    va_start(args, format);
+
+    ret = BIO_vsnprintf(buf, n, format, args);
+
+    va_end(args);
+    return ret;
+}
+
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+{
+    size_t retlen;
+    int truncated;
+
+    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
+        return -1;
+
+    if (truncated)
+        /*
+         * In case of truncation, return -1 like traditional snprintf.
+         * (Current drafts for ISO/IEC 9899 say snprintf should return the
+         * number of characters that would have been written, had the buffer
+         * been large enough.)
+         */
+        return -1;
+    else
+        return (retlen <= INT_MAX) ? (int)retlen : -1;
+}
-- 
2.31.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96503): https://edk2.groups.io/g/devel/message/96503
Mute This Topic: https://groups.io/mt/95135786/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib
Posted by Li, Yi 1 year, 5 months ago
Hi all,

This patch is the pre-work for enabling the X509 certificate time check.
I know it looks weird to add a new b_print.c, so I wanted to explain the background of this patch.

1. Why not directly use the b_print.c file in openssl?
The original file uses code related to floating-point and ulldrvm, which will cause compilation errors like:
unresolved external symbol __aulldvrm
error: SSE register return with SSE disabled 
ref: https://github.com/tianocore/edk2/pull/3508

So I removed all float code and replaced ulldrvm with DivU64x32Remainder():
1). 
            case 'f':
            case 'E':
            case 'e':
            case 'G':
            case 'g':
                return -1;
2).
+        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, &uremainder);
         convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
-            [uvalue % (unsigned)base];
-        uvalue = (uvalue / (unsigned)base);
+            [uremainder];


2. Why not use the similar print function AsciiVSPrint in EDK2?
EDK2 functions are all ms_abi but openssl functions not, so they use different va_list definitions, the relevant codes are as follows:
GCC:*_*_X64_CC_FLAGS     = ......  -DNO_MSABI_VA_FUNCS
https://github.com/tianocore/edk2/blob/fff6d81270b57ee786ea18ad74f43149b9f03494/CryptoPkg/Library/OpensslLib/OpensslLib.inf#LL636C2-L636C3

Therefore, segmentation fault will occur when calling the edk2 VA parameter function in the openssl function.

3. Why not remove NO_MSABI_VA_FUNCS?
Similarly, ms va_list cannot be used in the sysv function in openssl, which will also cause segmentation fault.

I am not expert of compilation, let me know if there is other better idea.

Thanks,
Yi

-----Original Message-----
From: Li, Yi1 <yi1.li@intel.com> 
Sent: Sunday, November 20, 2022 12:28 AM
To: devel@edk2.groups.io
Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4110

Openssl will use BIO_snprintf() to print time string when converting time_t to ASN1_time.
Currently edk2 code just give it a NULL implement in CrtWrapper.c, so getting current time in X509 time check will be fail.

This patch add a copy of OpensslLib\openssl\crypto\bio\b_print.c to OpensslLib, with below changes:

1. All floating point related code removed.
2. Replace ull divide and remainder with DivU64x32Remainder().

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Yi Li <yi1.li@intel.com>
---
 CryptoPkg/CryptoPkg.ci.yaml                   |   4 +-
 .../Library/BaseCryptLib/SysCall/CrtWrapper.c |  27 -
 .../SysCall/UnitTestHostCrtWrapper.c          |  25 -
 CryptoPkg/Library/OpensslLib/OpensslLib.inf   |   1 +
 .../Library/OpensslLib/OpensslLibAccel.inf    |   1 +
 .../Library/OpensslLib/OpensslLibCrypto.inf   |   1 +
 .../Library/OpensslLib/OpensslLibFull.inf     |   1 +
 .../OpensslLib/OpensslLibFullAccel.inf        |   1 +
 CryptoPkg/Library/OpensslLib/b_print.c        | 613 ++++++++++++++++++
 9 files changed, 621 insertions(+), 53 deletions(-)  create mode 100644 CryptoPkg/Library/OpensslLib/b_print.c

diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml index 47f2975967..8c25f581fb 100644
--- a/CryptoPkg/CryptoPkg.ci.yaml
+++ b/CryptoPkg/CryptoPkg.ci.yaml
@@ -13,7 +13,9 @@
             "Library/OpensslLib/IA32Gcc",
             "Library/OpensslLib/X64",
             "Library/OpensslLib/X64Gcc",
-            "Library/Include/openssl"
+            "Library/Include/openssl",
+            # b_print.c is a copy from OpenSSl.
+            "Library/OpensslLib/b_print.c"
         ]
     },
     "EccCheck": {
diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
index b65d29485b..6d7ac3efdc 100644
--- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
+++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
@@ -472,33 +472,6 @@ fwrite (
   return 0;
 }
 
-//
-//  -- Dummy OpenSSL Support Routines -- -//
-
-int
-BIO_printf (
-  void        *bio,
-  const char  *format,
-  ...
-  )
-{
-  return 0;
-}
-
-int
-BIO_snprintf (
-  char        *buf,
-  size_t      n,
-  const char  *format,
-  ...
-  )
-{
-  // Because the function does not actually print anything to buf, it returns -1 as error.
-  // Otherwise, the consumer may think that the buf is valid and parse the buffer.
-  return -1;
-}
-
 #ifdef __GNUC__
 
 typedef
diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
index 066d53e4fa..244e57437e 100644
--- a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
+++ b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
@@ -72,31 +72,6 @@ sscanf (
   return 0;
 }
 
-//
-//  -- Dummy OpenSSL Support Routines -- -//
-
-int
-BIO_printf (
-  void        *bio,
-  const char  *format,
-  ...
-  )
-{
-  return 0;
-}
-
-int
-BIO_snprintf (
-  char        *buf,
-  size_t      n,
-  const char  *format,
-  ...
-  )
-{
-  return 0;
-}
-
 uid_t
 getuid (
   void
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
index 60c6c24b0a..f8ddfadc51 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
@@ -580,6 +580,7 @@
   rand_pool.c
 #  SslNull.c
   EcSm2Null.c
+  b_print.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
index 103ef7bda2..6ee7bfd329 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
@@ -580,6 +580,7 @@
   rand_pool.c
 #  SslNull.c
   EcSm2Null.c
+  b_print.c
 
 [Sources.IA32]
 # Autogenerated IA32 files list starts here diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
index c4eaea888c..3e43cf146b 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
@@ -530,6 +530,7 @@
   rand_pool.c
   SslNull.c
   EcSm2Null.c
+  b_print.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
index 309e43055c..440d3e7e1d 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
@@ -635,6 +635,7 @@
   rand_pool.c
 #  SslNull.c
 #  EcSm2Null.c
+  b_print.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
index 4eeeeb79bd..413f70f733 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
@@ -635,6 +635,7 @@
   rand_pool.c
 #  SslNull.c
 #  EcSm2Null.c
+  b_print.c
 
 [Sources.IA32]
 # Autogenerated IA32 files list starts here diff --git a/CryptoPkg/Library/OpensslLib/b_print.c b/CryptoPkg/Library/OpensslLib/b_print.c
new file mode 100644
index 0000000000..885c3b9264
--- /dev/null
+++ b/CryptoPkg/Library/OpensslLib/b_print.c
@@ -0,0 +1,613 @@
+/*
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (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
+ * https://www.openssl.org/source/license.html
+ *
+ * Please notes:
+ * This file is a copy of OpensslLib\openssl\crypto\bio\b_print.c
+ * with all floating point related code removed (Not supported in UEFI).
+ * This means that '%f' '%g' '%e' and related combined formats are no longer supported.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "internal/cryptlib.h"
+#include "crypto/ctype.h"
+#include "internal/numbers.h"
+#include <openssl/bio.h>
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell 
+<papowell@astart.com>
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions.
+ */
+
+static int fmtstr(char **, char **, size_t *, size_t *,
+                  const char *, int, int, int); static int fmtint(char 
+**, char **, size_t *, size_t *,
+                  int64_t, int, int, int, int); static int 
+doapr_outch(char **, char **, size_t *, size_t *, int); static int 
+_dopr(char **sbuffer, char **buffer,
+                 size_t *maxlen, size_t *retlen, int *truncated,
+                 const char *format, va_list args);
+
+/* format read states */
+#define DP_S_DEFAULT    0
+#define DP_S_FLAGS      1
+#define DP_S_MIN        2
+#define DP_S_DOT        3
+#define DP_S_MAX        4
+#define DP_S_MOD        5
+#define DP_S_CONV       6
+#define DP_S_DONE       7
+
+/* format flags - Bits */
+/* left-aligned padding */
+#define DP_F_MINUS      (1 << 0)
+/* print an explicit '+' for a value with positive sign */
+#define DP_F_PLUS       (1 << 1)
+/* print an explicit ' ' for a value with positive sign */
+#define DP_F_SPACE      (1 << 2)
+/* print 0/0x prefix for octal/hex and decimal point for floating point */
+#define DP_F_NUM        (1 << 3)
+/* print leading zeroes */
+#define DP_F_ZERO       (1 << 4)
+/* print HEX in UPPPERcase */
+#define DP_F_UP         (1 << 5)
+/* treat value as unsigned */
+#define DP_F_UNSIGNED   (1 << 6)
+
+/* conversion flags */
+#define DP_C_SHORT      1
+#define DP_C_LONG       2
+// #define DP_C_LDOUBLE    3
+#define DP_C_LLONG      4
+#define DP_C_SIZE       5
+
+/* Floating point formats */
+// #define F_FORMAT        0
+// #define E_FORMAT        1
+// #define G_FORMAT        2
+
+/* some handy macros */
+#define char_to_int(p) (p - '0')
+#define OSSL_MAX(p,q) ((p >= q) ? p : q)
+
+static int
+_dopr(char **sbuffer,
+      char **buffer,
+      size_t *maxlen,
+      size_t *retlen, int *truncated, const char *format, va_list args) 
+{
+    char ch;
+    int64_t value;
+    char *strvalue;
+    int min;
+    int max;
+    int state;
+    int flags;
+    int cflags;
+    size_t currlen;
+
+    state = DP_S_DEFAULT;
+    flags = currlen = cflags = min = 0;
+    max = -1;
+    ch = *format++;
+
+    while (state != DP_S_DONE) {
+        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
+            state = DP_S_DONE;
+
+        switch (state) {
+        case DP_S_DEFAULT:
+            if (ch == '%')
+                state = DP_S_FLAGS;
+            else
+                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+                    return 0;
+            ch = *format++;
+            break;
+        case DP_S_FLAGS:
+            switch (ch) {
+            case '-':
+                flags |= DP_F_MINUS;
+                ch = *format++;
+                break;
+            case '+':
+                flags |= DP_F_PLUS;
+                ch = *format++;
+                break;
+            case ' ':
+                flags |= DP_F_SPACE;
+                ch = *format++;
+                break;
+            case '#':
+                flags |= DP_F_NUM;
+                ch = *format++;
+                break;
+            case '0':
+                flags |= DP_F_ZERO;
+                ch = *format++;
+                break;
+            default:
+                state = DP_S_MIN;
+                break;
+            }
+            break;
+        case DP_S_MIN:
+            if (ossl_isdigit(ch)) {
+                min = 10 * min + char_to_int(ch);
+                ch = *format++;
+            } else if (ch == '*') {
+                min = va_arg(args, int);
+                ch = *format++;
+                state = DP_S_DOT;
+            } else
+                state = DP_S_DOT;
+            break;
+        case DP_S_DOT:
+            if (ch == '.') {
+                state = DP_S_MAX;
+                ch = *format++;
+            } else
+                state = DP_S_MOD;
+            break;
+        case DP_S_MAX:
+            if (ossl_isdigit(ch)) {
+                if (max < 0)
+                    max = 0;
+                max = 10 * max + char_to_int(ch);
+                ch = *format++;
+            } else if (ch == '*') {
+                max = va_arg(args, int);
+                ch = *format++;
+                state = DP_S_MOD;
+            } else
+                state = DP_S_MOD;
+            break;
+        case DP_S_MOD:
+            switch (ch) {
+            case 'h':
+                cflags = DP_C_SHORT;
+                ch = *format++;
+                break;
+            case 'l':
+                if (*format == 'l') {
+                    cflags = DP_C_LLONG;
+                    format++;
+                } else
+                    cflags = DP_C_LONG;
+                ch = *format++;
+                break;
+            case 'q':
+            case 'j':
+                cflags = DP_C_LLONG;
+                ch = *format++;
+                break;
+            case 'L':
+                //Unsupported fmt in UEFI
+                return -1;
+            case 'z':
+                cflags = DP_C_SIZE;
+                ch = *format++;
+                break;
+            default:
+                break;
+            }
+            state = DP_S_CONV;
+            break;
+        case DP_S_CONV:
+            switch (ch) {
+            case 'd':
+            case 'i':
+                switch (cflags) {
+                case DP_C_SHORT:
+                    value = (short int)va_arg(args, int);
+                    break;
+                case DP_C_LONG:
+                    value = va_arg(args, long int);
+                    break;
+                case DP_C_LLONG:
+                    value = va_arg(args, int64_t);
+                    break;
+                case DP_C_SIZE:
+                    value = va_arg(args, ossl_ssize_t);
+                    break;
+                default:
+                    value = va_arg(args, int);
+                    break;
+                }
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
+                            max, flags))
+                    return 0;
+                break;
+            case 'X':
+                flags |= DP_F_UP;
+                /* FALLTHROUGH */
+            case 'x':
+            case 'o':
+            case 'u':
+                flags |= DP_F_UNSIGNED;
+                switch (cflags) {
+                case DP_C_SHORT:
+                    value = (unsigned short int)va_arg(args, unsigned int);
+                    break;
+                case DP_C_LONG:
+                    value = va_arg(args, unsigned long int);
+                    break;
+                case DP_C_LLONG:
+                    value = va_arg(args, uint64_t);
+                    break;
+                case DP_C_SIZE:
+                    value = va_arg(args, size_t);
+                    break;
+                default:
+                    value = va_arg(args, unsigned int);
+                    break;
+                }
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
+                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
+                            min, max, flags))
+                    return 0;
+                break;
+            case 'f':
+            case 'E':
+            case 'e':
+            case 'G':
+            case 'g':
+                return -1;
+            case 'c':
+                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
+                                 va_arg(args, int)))
+                    return 0;
+                break;
+            case 's':
+                strvalue = va_arg(args, char *);
+                if (max < 0) {
+                    if (buffer)
+                        max = INT_MAX;
+                    else
+                        max = *maxlen;
+                }
+                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
+                            flags, min, max))
+                    return 0;
+                break;
+            case 'p':
+                value = (size_t)va_arg(args, void *);
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
+                            value, 16, min, max, flags | DP_F_NUM))
+                    return 0;
+                break;
+            case 'n':
+                {
+                    int *num;
+                    num = va_arg(args, int *);
+                    *num = currlen;
+                }
+                break;
+            case '%':
+                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+                    return 0;
+                break;
+            case 'w':
+                /* not supported yet, treat as next char */
+                ch = *format++;
+                break;
+            default:
+                /* unknown, skip */
+                break;
+            }
+            ch = *format++;
+            state = DP_S_DEFAULT;
+            flags = cflags = min = 0;
+            max = -1;
+            break;
+        case DP_S_DONE:
+            break;
+        default:
+            break;
+        }
+    }
+    /*
+     * We have to truncate if there is no dynamic buffer and we have filled the
+     * static buffer.
+     */
+    if (buffer == NULL) {
+        *truncated = (currlen > *maxlen - 1);
+        if (*truncated)
+            currlen = *maxlen - 1;
+    }
+    if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
+        return 0;
+    *retlen = currlen - 1;
+    return 1;
+}
+
+static int
+fmtstr(char **sbuffer,
+       char **buffer,
+       size_t *currlen,
+       size_t *maxlen, const char *value, int flags, int min, int max) 
+{
+    int padlen;
+    size_t strln;
+    int cnt = 0;
+
+    if (value == 0)
+        value = "<NULL>";
+
+    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
+
+    padlen = min - strln;
+    if (min < 0 || padlen < 0)
+        padlen = 0;
+    if (max >= 0) {
+        /*
+         * Calculate the maximum output including padding.
+         * Make sure max doesn't overflow into negativity
+         */
+        if (max < INT_MAX - padlen)
+            max += padlen;
+        else
+            max = INT_MAX;
+    }
+    if (flags & DP_F_MINUS)
+        padlen = -padlen;
+
+    while ((padlen > 0) && (max < 0 || cnt < max)) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
+        --padlen;
+        ++cnt;
+    }
+    while (strln > 0 && (max < 0 || cnt < max)) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
+            return 0;
+        --strln;
+        ++cnt;
+    }
+    while ((padlen < 0) && (max < 0 || cnt < max)) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
+        ++padlen;
+        ++cnt;
+    }
+    return 1;
+}
+
+static int
+fmtint(char **sbuffer,
+       char **buffer,
+       size_t *currlen,
+       size_t *maxlen, int64_t value, int base, int min, int max, int 
+flags) {
+    int signvalue = 0;
+    const char *prefix = "";
+    uint64_t uvalue;
+    char convert[DECIMAL_SIZE(value) + 3];
+    int place = 0;
+    int spadlen = 0;
+    int zpadlen = 0;
+    int caps = 0;
+    uint32_t uremainder = 0;
+
+    if (max < 0)
+        max = 0;
+    uvalue = value;
+    if (!(flags & DP_F_UNSIGNED)) {
+        if (value < 0) {
+            signvalue = '-';
+            uvalue = 0 - (uint64_t)value;
+        } else if (flags & DP_F_PLUS)
+            signvalue = '+';
+        else if (flags & DP_F_SPACE)
+            signvalue = ' ';
+    }
+    if (flags & DP_F_NUM) {
+        if (base == 8)
+            prefix = "0";
+        if (base == 16)
+            prefix = "0x";
+    }
+    if (flags & DP_F_UP)
+        caps = 1;
+    do {
+        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, &uremainder);
+        convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+            [uremainder];
+    } while (uvalue && (place < (int)sizeof(convert)));
+    if (place == sizeof(convert))
+        place--;
+    convert[place] = 0;
+
+    zpadlen = max - place;
+    spadlen =
+        min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
+    if (zpadlen < 0)
+        zpadlen = 0;
+    if (spadlen < 0)
+        spadlen = 0;
+    if (flags & DP_F_ZERO) {
+        zpadlen = OSSL_MAX(zpadlen, spadlen);
+        spadlen = 0;
+    }
+    if (flags & DP_F_MINUS)
+        spadlen = -spadlen;
+
+    /* spaces */
+    while (spadlen > 0) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
+        --spadlen;
+    }
+
+    /* sign */
+    if (signvalue)
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+            return 0;
+
+    /* prefix */
+    while (*prefix) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
+            return 0;
+        prefix++;
+    }
+
+    /* zeros */
+    if (zpadlen > 0) {
+        while (zpadlen > 0) {
+            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+                return 0;
+            --zpadlen;
+        }
+    }
+    /* digits */
+    while (place > 0) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
+            return 0;
+    }
+
+    /* left justified spaces */
+    while (spadlen < 0) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
+        ++spadlen;
+    }
+    return 1;
+}
+
+#define BUFFER_INC  1024
+
+static int
+doapr_outch(char **sbuffer,
+            char **buffer, size_t *currlen, size_t *maxlen, int c) {
+    /* If we haven't at least one buffer, someone has done a big booboo */
+    if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
+        return 0;
+
+    /* |currlen| must always be <= |*maxlen| */
+    if (!ossl_assert(*currlen <= *maxlen))
+        return 0;
+
+    if (buffer && *currlen == *maxlen) {
+        if (*maxlen > INT_MAX - BUFFER_INC)
+            return 0;
+
+        *maxlen += BUFFER_INC;
+        if (*buffer == NULL) {
+            if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
+                BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+            if (*currlen > 0) {
+                if (!ossl_assert(*sbuffer != NULL))
+                    return 0;
+                memcpy(*buffer, *sbuffer, *currlen);
+            }
+            *sbuffer = NULL;
+        } else {
+            char *tmpbuf;
+            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
+            if (tmpbuf == NULL)
+                return 0;
+            *buffer = tmpbuf;
+        }
+    }
+
+    if (*currlen < *maxlen) {
+        if (*sbuffer)
+            (*sbuffer)[(*currlen)++] = (char)c;
+        else
+            (*buffer)[(*currlen)++] = (char)c;
+    }
+
+    return 1;
+}
+
+/**********************************************************************
+*****/
+
+int BIO_printf(BIO *bio, const char *format, ...) {
+    va_list args;
+    int ret;
+
+    va_start(args, format);
+
+    ret = BIO_vprintf(bio, format, args);
+
+    va_end(args);
+    return ret;
+}
+
+int BIO_vprintf(BIO *bio, const char *format, va_list args) {
+    int ret;
+    size_t retlen;
+    char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
+                                 * in small-stack environments, like threads
+                                 * or DOS programs. */
+    char *hugebufp = hugebuf;
+    size_t hugebufsize = sizeof(hugebuf);
+    char *dynbuf = NULL;
+    int ignored;
+
+    dynbuf = NULL;
+    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
+                args)) {
+        OPENSSL_free(dynbuf);
+        return -1;
+    }
+    if (dynbuf) {
+        ret = BIO_write(bio, dynbuf, (int)retlen);
+        OPENSSL_free(dynbuf);
+    } else {
+        ret = BIO_write(bio, hugebuf, (int)retlen);
+    }
+    return ret;
+}
+
+/*
+ * As snprintf is not available everywhere, we provide our own
+ * implementation. This function has nothing to do with BIOs, but it's
+ * closely related to BIO_printf, and we need *some* name prefix ... 
+(XXX the
+ * function should be renamed, but to what?)  */ int BIO_snprintf(char 
+*buf, size_t n, const char *format, ...) {
+    va_list args;
+    int ret;
+
+    va_start(args, format);
+
+    ret = BIO_vsnprintf(buf, n, format, args);
+
+    va_end(args);
+    return ret;
+}
+
+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list 
+args) {
+    size_t retlen;
+    int truncated;
+
+    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
+        return -1;
+
+    if (truncated)
+        /*
+         * In case of truncation, return -1 like traditional snprintf.
+         * (Current drafts for ISO/IEC 9899 say snprintf should return the
+         * number of characters that would have been written, had the buffer
+         * been large enough.)
+         */
+        return -1;
+    else
+        return (retlen <= INT_MAX) ? (int)retlen : -1; }
--
2.31.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96504): https://edk2.groups.io/g/devel/message/96504
Mute This Topic: https://groups.io/mt/95135786/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib
Posted by Yao, Jiewen 1 year, 5 months ago
HI Yi
I have question for 1 - The original file uses code related to floating-point and ulldrvm.

a) Openssl supports OPENSSL_SYS_UEFI macro (https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf.h#L28), why not use OPENSSL_SYS_UEFI macro to eliminate float point action?

b) For ulldrvm, why not implement it in https://github.com/tianocore/edk2/tree/master/CryptoPkg/Library/IntrinsicLib, as we already did.

Thank you
Yao, Jiewen

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Sunday, November 20, 2022 12:33 AM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [PATCH] CryptoPkg: Add b_print.c which removed floating-
> point to OpensslLib
> 
> Hi all,
> 
> This patch is the pre-work for enabling the X509 certificate time check.
> I know it looks weird to add a new b_print.c, so I wanted to explain the
> background of this patch.
> 
> 1. Why not directly use the b_print.c file in openssl?
> The original file uses code related to floating-point and ulldrvm, which will
> cause compilation errors like:
> unresolved external symbol __aulldvrm
> error: SSE register return with SSE disabled
> ref: https://github.com/tianocore/edk2/pull/3508
> 
> So I removed all float code and replaced ulldrvm with
> DivU64x32Remainder():
> 1).
>             case 'f':
>             case 'E':
>             case 'e':
>             case 'G':
>             case 'g':
>                 return -1;
> 2).
> +        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, &uremainder);
>          convert[place++] = (caps ? "0123456789ABCDEF" :
> "0123456789abcdef")
> -            [uvalue % (unsigned)base];
> -        uvalue = (uvalue / (unsigned)base);
> +            [uremainder];
> 
> 
> 2. Why not use the similar print function AsciiVSPrint in EDK2?
> EDK2 functions are all ms_abi but openssl functions not, so they use
> different va_list definitions, the relevant codes are as follows:
> GCC:*_*_X64_CC_FLAGS     = ......  -DNO_MSABI_VA_FUNCS
> https://github.com/tianocore/edk2/blob/fff6d81270b57ee786ea18ad74f4
> 3149b9f03494/CryptoPkg/Library/OpensslLib/OpensslLib.inf#LL636C2-
> L636C3
> 
> Therefore, segmentation fault will occur when calling the edk2 VA
> parameter function in the openssl function.
> 
> 3. Why not remove NO_MSABI_VA_FUNCS?
> Similarly, ms va_list cannot be used in the sysv function in openssl, which
> will also cause segmentation fault.
> 
> I am not expert of compilation, let me know if there is other better idea.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Sunday, November 20, 2022 12:28 AM
> To: devel@edk2.groups.io
> Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Wang,
> Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang,
> Guomin <guomin.jiang@intel.com>
> Subject: [PATCH] CryptoPkg: Add b_print.c which removed floating-point to
> OpensslLib
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4110
> 
> Openssl will use BIO_snprintf() to print time string when converting time_t
> to ASN1_time.
> Currently edk2 code just give it a NULL implement in CrtWrapper.c, so
> getting current time in X509 time check will be fail.
> 
> This patch add a copy of OpensslLib\openssl\crypto\bio\b_print.c to
> OpensslLib, with below changes:
> 
> 1. All floating point related code removed.
> 2. Replace ull divide and remainder with DivU64x32Remainder().
> 
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> Cc: Guomin Jiang <guomin.jiang@intel.com>
> Signed-off-by: Yi Li <yi1.li@intel.com>
> ---
>  CryptoPkg/CryptoPkg.ci.yaml                   |   4 +-
>  .../Library/BaseCryptLib/SysCall/CrtWrapper.c |  27 -
>  .../SysCall/UnitTestHostCrtWrapper.c          |  25 -
>  CryptoPkg/Library/OpensslLib/OpensslLib.inf   |   1 +
>  .../Library/OpensslLib/OpensslLibAccel.inf    |   1 +
>  .../Library/OpensslLib/OpensslLibCrypto.inf   |   1 +
>  .../Library/OpensslLib/OpensslLibFull.inf     |   1 +
>  .../OpensslLib/OpensslLibFullAccel.inf        |   1 +
>  CryptoPkg/Library/OpensslLib/b_print.c        | 613 ++++++++++++++++++
>  9 files changed, 621 insertions(+), 53 deletions(-)  create mode 100644
> CryptoPkg/Library/OpensslLib/b_print.c
> 
> diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml
> index 47f2975967..8c25f581fb 100644
> --- a/CryptoPkg/CryptoPkg.ci.yaml
> +++ b/CryptoPkg/CryptoPkg.ci.yaml
> @@ -13,7 +13,9 @@
>              "Library/OpensslLib/IA32Gcc",
>              "Library/OpensslLib/X64",
>              "Library/OpensslLib/X64Gcc",
> -            "Library/Include/openssl"
> +            "Library/Include/openssl",
> +            # b_print.c is a copy from OpenSSl.
> +            "Library/OpensslLib/b_print.c"
>          ]
>      },
>      "EccCheck": {
> diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> index b65d29485b..6d7ac3efdc 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> @@ -472,33 +472,6 @@ fwrite (
>    return 0;
>  }
> 
> -//
> -//  -- Dummy OpenSSL Support Routines -- -//
> -
> -int
> -BIO_printf (
> -  void        *bio,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
> -int
> -BIO_snprintf (
> -  char        *buf,
> -  size_t      n,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  // Because the function does not actually print anything to buf, it returns
> -1 as error.
> -  // Otherwise, the consumer may think that the buf is valid and parse the
> buffer.
> -  return -1;
> -}
> -
>  #ifdef __GNUC__
> 
>  typedef
> diff --git
> a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> index 066d53e4fa..244e57437e 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> @@ -72,31 +72,6 @@ sscanf (
>    return 0;
>  }
> 
> -//
> -//  -- Dummy OpenSSL Support Routines -- -//
> -
> -int
> -BIO_printf (
> -  void        *bio,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
> -int
> -BIO_snprintf (
> -  char        *buf,
> -  size_t      n,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
>  uid_t
>  getuid (
>    void
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> index 60c6c24b0a..f8ddfadc51 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> @@ -580,6 +580,7 @@
>    rand_pool.c
>  #  SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> index 103ef7bda2..6ee7bfd329 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> @@ -580,6 +580,7 @@
>    rand_pool.c
>  #  SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Sources.IA32]
>  # Autogenerated IA32 files list starts here diff --git
> a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> index c4eaea888c..3e43cf146b 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> @@ -530,6 +530,7 @@
>    rand_pool.c
>    SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> index 309e43055c..440d3e7e1d 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> @@ -635,6 +635,7 @@
>    rand_pool.c
>  #  SslNull.c
>  #  EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> index 4eeeeb79bd..413f70f733 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> @@ -635,6 +635,7 @@
>    rand_pool.c
>  #  SslNull.c
>  #  EcSm2Null.c
> +  b_print.c
> 
>  [Sources.IA32]
>  # Autogenerated IA32 files list starts here diff --git
> a/CryptoPkg/Library/OpensslLib/b_print.c
> b/CryptoPkg/Library/OpensslLib/b_print.c
> new file mode 100644
> index 0000000000..885c3b9264
> --- /dev/null
> +++ b/CryptoPkg/Library/OpensslLib/b_print.c
> @@ -0,0 +1,613 @@
> +/*
> + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
> + *
> + * Licensed under the OpenSSL license (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
> + * https://www.openssl.org/source/license.html
> + *
> + * Please notes:
> + * This file is a copy of OpensslLib\openssl\crypto\bio\b_print.c
> + * with all floating point related code removed (Not supported in UEFI).
> + * This means that '%f' '%g' '%e' and related combined formats are no
> longer supported.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <string.h>
> +#include "internal/cryptlib.h"
> +#include "crypto/ctype.h"
> +#include "internal/numbers.h"
> +#include <openssl/bio.h>
> +
> +/*
> + * Copyright Patrick Powell 1995
> + * This code is based on code written by Patrick Powell
> +<papowell@astart.com>
> + * It may be used for any purpose as long as this notice remains intact
> + * on all source code distributions.
> + */
> +
> +static int fmtstr(char **, char **, size_t *, size_t *,
> +                  const char *, int, int, int); static int fmtint(char
> +**, char **, size_t *, size_t *,
> +                  int64_t, int, int, int, int); static int
> +doapr_outch(char **, char **, size_t *, size_t *, int); static int
> +_dopr(char **sbuffer, char **buffer,
> +                 size_t *maxlen, size_t *retlen, int *truncated,
> +                 const char *format, va_list args);
> +
> +/* format read states */
> +#define DP_S_DEFAULT    0
> +#define DP_S_FLAGS      1
> +#define DP_S_MIN        2
> +#define DP_S_DOT        3
> +#define DP_S_MAX        4
> +#define DP_S_MOD        5
> +#define DP_S_CONV       6
> +#define DP_S_DONE       7
> +
> +/* format flags - Bits */
> +/* left-aligned padding */
> +#define DP_F_MINUS      (1 << 0)
> +/* print an explicit '+' for a value with positive sign */
> +#define DP_F_PLUS       (1 << 1)
> +/* print an explicit ' ' for a value with positive sign */
> +#define DP_F_SPACE      (1 << 2)
> +/* print 0/0x prefix for octal/hex and decimal point for floating point */
> +#define DP_F_NUM        (1 << 3)
> +/* print leading zeroes */
> +#define DP_F_ZERO       (1 << 4)
> +/* print HEX in UPPPERcase */
> +#define DP_F_UP         (1 << 5)
> +/* treat value as unsigned */
> +#define DP_F_UNSIGNED   (1 << 6)
> +
> +/* conversion flags */
> +#define DP_C_SHORT      1
> +#define DP_C_LONG       2
> +// #define DP_C_LDOUBLE    3
> +#define DP_C_LLONG      4
> +#define DP_C_SIZE       5
> +
> +/* Floating point formats */
> +// #define F_FORMAT        0
> +// #define E_FORMAT        1
> +// #define G_FORMAT        2
> +
> +/* some handy macros */
> +#define char_to_int(p) (p - '0')
> +#define OSSL_MAX(p,q) ((p >= q) ? p : q)
> +
> +static int
> +_dopr(char **sbuffer,
> +      char **buffer,
> +      size_t *maxlen,
> +      size_t *retlen, int *truncated, const char *format, va_list args)
> +{
> +    char ch;
> +    int64_t value;
> +    char *strvalue;
> +    int min;
> +    int max;
> +    int state;
> +    int flags;
> +    int cflags;
> +    size_t currlen;
> +
> +    state = DP_S_DEFAULT;
> +    flags = currlen = cflags = min = 0;
> +    max = -1;
> +    ch = *format++;
> +
> +    while (state != DP_S_DONE) {
> +        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
> +            state = DP_S_DONE;
> +
> +        switch (state) {
> +        case DP_S_DEFAULT:
> +            if (ch == '%')
> +                state = DP_S_FLAGS;
> +            else
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
> +                    return 0;
> +            ch = *format++;
> +            break;
> +        case DP_S_FLAGS:
> +            switch (ch) {
> +            case '-':
> +                flags |= DP_F_MINUS;
> +                ch = *format++;
> +                break;
> +            case '+':
> +                flags |= DP_F_PLUS;
> +                ch = *format++;
> +                break;
> +            case ' ':
> +                flags |= DP_F_SPACE;
> +                ch = *format++;
> +                break;
> +            case '#':
> +                flags |= DP_F_NUM;
> +                ch = *format++;
> +                break;
> +            case '0':
> +                flags |= DP_F_ZERO;
> +                ch = *format++;
> +                break;
> +            default:
> +                state = DP_S_MIN;
> +                break;
> +            }
> +            break;
> +        case DP_S_MIN:
> +            if (ossl_isdigit(ch)) {
> +                min = 10 * min + char_to_int(ch);
> +                ch = *format++;
> +            } else if (ch == '*') {
> +                min = va_arg(args, int);
> +                ch = *format++;
> +                state = DP_S_DOT;
> +            } else
> +                state = DP_S_DOT;
> +            break;
> +        case DP_S_DOT:
> +            if (ch == '.') {
> +                state = DP_S_MAX;
> +                ch = *format++;
> +            } else
> +                state = DP_S_MOD;
> +            break;
> +        case DP_S_MAX:
> +            if (ossl_isdigit(ch)) {
> +                if (max < 0)
> +                    max = 0;
> +                max = 10 * max + char_to_int(ch);
> +                ch = *format++;
> +            } else if (ch == '*') {
> +                max = va_arg(args, int);
> +                ch = *format++;
> +                state = DP_S_MOD;
> +            } else
> +                state = DP_S_MOD;
> +            break;
> +        case DP_S_MOD:
> +            switch (ch) {
> +            case 'h':
> +                cflags = DP_C_SHORT;
> +                ch = *format++;
> +                break;
> +            case 'l':
> +                if (*format == 'l') {
> +                    cflags = DP_C_LLONG;
> +                    format++;
> +                } else
> +                    cflags = DP_C_LONG;
> +                ch = *format++;
> +                break;
> +            case 'q':
> +            case 'j':
> +                cflags = DP_C_LLONG;
> +                ch = *format++;
> +                break;
> +            case 'L':
> +                //Unsupported fmt in UEFI
> +                return -1;
> +            case 'z':
> +                cflags = DP_C_SIZE;
> +                ch = *format++;
> +                break;
> +            default:
> +                break;
> +            }
> +            state = DP_S_CONV;
> +            break;
> +        case DP_S_CONV:
> +            switch (ch) {
> +            case 'd':
> +            case 'i':
> +                switch (cflags) {
> +                case DP_C_SHORT:
> +                    value = (short int)va_arg(args, int);
> +                    break;
> +                case DP_C_LONG:
> +                    value = va_arg(args, long int);
> +                    break;
> +                case DP_C_LLONG:
> +                    value = va_arg(args, int64_t);
> +                    break;
> +                case DP_C_SIZE:
> +                    value = va_arg(args, ossl_ssize_t);
> +                    break;
> +                default:
> +                    value = va_arg(args, int);
> +                    break;
> +                }
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
> +                            max, flags))
> +                    return 0;
> +                break;
> +            case 'X':
> +                flags |= DP_F_UP;
> +                /* FALLTHROUGH */
> +            case 'x':
> +            case 'o':
> +            case 'u':
> +                flags |= DP_F_UNSIGNED;
> +                switch (cflags) {
> +                case DP_C_SHORT:
> +                    value = (unsigned short int)va_arg(args, unsigned int);
> +                    break;
> +                case DP_C_LONG:
> +                    value = va_arg(args, unsigned long int);
> +                    break;
> +                case DP_C_LLONG:
> +                    value = va_arg(args, uint64_t);
> +                    break;
> +                case DP_C_SIZE:
> +                    value = va_arg(args, size_t);
> +                    break;
> +                default:
> +                    value = va_arg(args, unsigned int);
> +                    break;
> +                }
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
> +                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
> +                            min, max, flags))
> +                    return 0;
> +                break;
> +            case 'f':
> +            case 'E':
> +            case 'e':
> +            case 'G':
> +            case 'g':
> +                return -1;
> +            case 'c':
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
> +                                 va_arg(args, int)))
> +                    return 0;
> +                break;
> +            case 's':
> +                strvalue = va_arg(args, char *);
> +                if (max < 0) {
> +                    if (buffer)
> +                        max = INT_MAX;
> +                    else
> +                        max = *maxlen;
> +                }
> +                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
> +                            flags, min, max))
> +                    return 0;
> +                break;
> +            case 'p':
> +                value = (size_t)va_arg(args, void *);
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
> +                            value, 16, min, max, flags | DP_F_NUM))
> +                    return 0;
> +                break;
> +            case 'n':
> +                {
> +                    int *num;
> +                    num = va_arg(args, int *);
> +                    *num = currlen;
> +                }
> +                break;
> +            case '%':
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
> +                    return 0;
> +                break;
> +            case 'w':
> +                /* not supported yet, treat as next char */
> +                ch = *format++;
> +                break;
> +            default:
> +                /* unknown, skip */
> +                break;
> +            }
> +            ch = *format++;
> +            state = DP_S_DEFAULT;
> +            flags = cflags = min = 0;
> +            max = -1;
> +            break;
> +        case DP_S_DONE:
> +            break;
> +        default:
> +            break;
> +        }
> +    }
> +    /*
> +     * We have to truncate if there is no dynamic buffer and we have filled
> the
> +     * static buffer.
> +     */
> +    if (buffer == NULL) {
> +        *truncated = (currlen > *maxlen - 1);
> +        if (*truncated)
> +            currlen = *maxlen - 1;
> +    }
> +    if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
> +        return 0;
> +    *retlen = currlen - 1;
> +    return 1;
> +}
> +
> +static int
> +fmtstr(char **sbuffer,
> +       char **buffer,
> +       size_t *currlen,
> +       size_t *maxlen, const char *value, int flags, int min, int max)
> +{
> +    int padlen;
> +    size_t strln;
> +    int cnt = 0;
> +
> +    if (value == 0)
> +        value = "<NULL>";
> +
> +    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
> +
> +    padlen = min - strln;
> +    if (min < 0 || padlen < 0)
> +        padlen = 0;
> +    if (max >= 0) {
> +        /*
> +         * Calculate the maximum output including padding.
> +         * Make sure max doesn't overflow into negativity
> +         */
> +        if (max < INT_MAX - padlen)
> +            max += padlen;
> +        else
> +            max = INT_MAX;
> +    }
> +    if (flags & DP_F_MINUS)
> +        padlen = -padlen;
> +
> +    while ((padlen > 0) && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        --padlen;
> +        ++cnt;
> +    }
> +    while (strln > 0 && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
> +            return 0;
> +        --strln;
> +        ++cnt;
> +    }
> +    while ((padlen < 0) && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        ++padlen;
> +        ++cnt;
> +    }
> +    return 1;
> +}
> +
> +static int
> +fmtint(char **sbuffer,
> +       char **buffer,
> +       size_t *currlen,
> +       size_t *maxlen, int64_t value, int base, int min, int max, int
> +flags) {
> +    int signvalue = 0;
> +    const char *prefix = "";
> +    uint64_t uvalue;
> +    char convert[DECIMAL_SIZE(value) + 3];
> +    int place = 0;
> +    int spadlen = 0;
> +    int zpadlen = 0;
> +    int caps = 0;
> +    uint32_t uremainder = 0;
> +
> +    if (max < 0)
> +        max = 0;
> +    uvalue = value;
> +    if (!(flags & DP_F_UNSIGNED)) {
> +        if (value < 0) {
> +            signvalue = '-';
> +            uvalue = 0 - (uint64_t)value;
> +        } else if (flags & DP_F_PLUS)
> +            signvalue = '+';
> +        else if (flags & DP_F_SPACE)
> +            signvalue = ' ';
> +    }
> +    if (flags & DP_F_NUM) {
> +        if (base == 8)
> +            prefix = "0";
> +        if (base == 16)
> +            prefix = "0x";
> +    }
> +    if (flags & DP_F_UP)
> +        caps = 1;
> +    do {
> +        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, &uremainder);
> +        convert[place++] = (caps ? "0123456789ABCDEF" :
> "0123456789abcdef")
> +            [uremainder];
> +    } while (uvalue && (place < (int)sizeof(convert)));
> +    if (place == sizeof(convert))
> +        place--;
> +    convert[place] = 0;
> +
> +    zpadlen = max - place;
> +    spadlen =
> +        min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
> +    if (zpadlen < 0)
> +        zpadlen = 0;
> +    if (spadlen < 0)
> +        spadlen = 0;
> +    if (flags & DP_F_ZERO) {
> +        zpadlen = OSSL_MAX(zpadlen, spadlen);
> +        spadlen = 0;
> +    }
> +    if (flags & DP_F_MINUS)
> +        spadlen = -spadlen;
> +
> +    /* spaces */
> +    while (spadlen > 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        --spadlen;
> +    }
> +
> +    /* sign */
> +    if (signvalue)
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
> +            return 0;
> +
> +    /* prefix */
> +    while (*prefix) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
> +            return 0;
> +        prefix++;
> +    }
> +
> +    /* zeros */
> +    if (zpadlen > 0) {
> +        while (zpadlen > 0) {
> +            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
> +                return 0;
> +            --zpadlen;
> +        }
> +    }
> +    /* digits */
> +    while (place > 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
> +            return 0;
> +    }
> +
> +    /* left justified spaces */
> +    while (spadlen < 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        ++spadlen;
> +    }
> +    return 1;
> +}
> +
> +#define BUFFER_INC  1024
> +
> +static int
> +doapr_outch(char **sbuffer,
> +            char **buffer, size_t *currlen, size_t *maxlen, int c) {
> +    /* If we haven't at least one buffer, someone has done a big booboo */
> +    if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
> +        return 0;
> +
> +    /* |currlen| must always be <= |*maxlen| */
> +    if (!ossl_assert(*currlen <= *maxlen))
> +        return 0;
> +
> +    if (buffer && *currlen == *maxlen) {
> +        if (*maxlen > INT_MAX - BUFFER_INC)
> +            return 0;
> +
> +        *maxlen += BUFFER_INC;
> +        if (*buffer == NULL) {
> +            if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
> +                BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
> +                return 0;
> +            }
> +            if (*currlen > 0) {
> +                if (!ossl_assert(*sbuffer != NULL))
> +                    return 0;
> +                memcpy(*buffer, *sbuffer, *currlen);
> +            }
> +            *sbuffer = NULL;
> +        } else {
> +            char *tmpbuf;
> +            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
> +            if (tmpbuf == NULL)
> +                return 0;
> +            *buffer = tmpbuf;
> +        }
> +    }
> +
> +    if (*currlen < *maxlen) {
> +        if (*sbuffer)
> +            (*sbuffer)[(*currlen)++] = (char)c;
> +        else
> +            (*buffer)[(*currlen)++] = (char)c;
> +    }
> +
> +    return 1;
> +}
> +
> +/*********************************************************
> *************
> +*****/
> +
> +int BIO_printf(BIO *bio, const char *format, ...) {
> +    va_list args;
> +    int ret;
> +
> +    va_start(args, format);
> +
> +    ret = BIO_vprintf(bio, format, args);
> +
> +    va_end(args);
> +    return ret;
> +}
> +
> +int BIO_vprintf(BIO *bio, const char *format, va_list args) {
> +    int ret;
> +    size_t retlen;
> +    char hugebuf[1024 * 2];     /* Was previously 10k, which is
> unreasonable
> +                                 * in small-stack environments, like threads
> +                                 * or DOS programs. */
> +    char *hugebufp = hugebuf;
> +    size_t hugebufsize = sizeof(hugebuf);
> +    char *dynbuf = NULL;
> +    int ignored;
> +
> +    dynbuf = NULL;
> +    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored,
> format,
> +                args)) {
> +        OPENSSL_free(dynbuf);
> +        return -1;
> +    }
> +    if (dynbuf) {
> +        ret = BIO_write(bio, dynbuf, (int)retlen);
> +        OPENSSL_free(dynbuf);
> +    } else {
> +        ret = BIO_write(bio, hugebuf, (int)retlen);
> +    }
> +    return ret;
> +}
> +
> +/*
> + * As snprintf is not available everywhere, we provide our own
> + * implementation. This function has nothing to do with BIOs, but it's
> + * closely related to BIO_printf, and we need *some* name prefix ...
> +(XXX the
> + * function should be renamed, but to what?)  */ int BIO_snprintf(char
> +*buf, size_t n, const char *format, ...) {
> +    va_list args;
> +    int ret;
> +
> +    va_start(args, format);
> +
> +    ret = BIO_vsnprintf(buf, n, format, args);
> +
> +    va_end(args);
> +    return ret;
> +}
> +
> +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list
> +args) {
> +    size_t retlen;
> +    int truncated;
> +
> +    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
> +        return -1;
> +
> +    if (truncated)
> +        /*
> +         * In case of truncation, return -1 like traditional snprintf.
> +         * (Current drafts for ISO/IEC 9899 say snprintf should return the
> +         * number of characters that would have been written, had the buffer
> +         * been large enough.)
> +         */
> +        return -1;
> +    else
> +        return (retlen <= INT_MAX) ? (int)retlen : -1; }
> --
> 2.31.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96505): https://edk2.groups.io/g/devel/message/96505
Mute This Topic: https://groups.io/mt/95135786/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib
Posted by Gerd Hoffmann 1 year, 5 months ago
On Sun, Nov 20, 2022 at 02:18:36AM +0000, Yao, Jiewen wrote:
> HI Yi
> I have question for 1 - The original file uses code related to floating-point and ulldrvm.
> 
> a) Openssl supports OPENSSL_SYS_UEFI macro (https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf.h#L28), why not use OPENSSL_SYS_UEFI macro to eliminate float point action?

openssl 3.x already has that btw.

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96510): https://edk2.groups.io/g/devel/message/96510
Mute This Topic: https://groups.io/mt/95135786/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib
Posted by Li, Yi 1 year, 5 months ago
Hi Gerd,

Cool! I noticed your patch in openssl3.0 branch.
Because the Tls cert time check needs to be solved as soon as possible,
I will cherry-pick your patch to 1.1.1 branch instead of updating edk2 openssl to 3.0. The latter seems to take a long time.

By the way, I remember you are already working on upstream openssl3.0, right?
How is it doing now, I can help with some work if needed.

Thanks,
Yi

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Gerd Hoffmann
Sent: Monday, November 21, 2022 2:24 PM
To: devel@edk2.groups.io; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Li, Yi1 <yi1.li@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib

On Sun, Nov 20, 2022 at 02:18:36AM +0000, Yao, Jiewen wrote:
> HI Yi
> I have question for 1 - The original file uses code related to floating-point and ulldrvm.
> 
> a) Openssl supports OPENSSL_SYS_UEFI macro (https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf.h#L28), why not use OPENSSL_SYS_UEFI macro to eliminate float point action?

openssl 3.x already has that btw.

take care,
  Gerd








-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96513): https://edk2.groups.io/g/devel/message/96513
Mute This Topic: https://groups.io/mt/95135786/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib
Posted by Gerd Hoffmann 1 year, 5 months ago
On Mon, Nov 21, 2022 at 08:31:19AM +0000, Li, Yi wrote:
> Hi Gerd,
> 
> Cool! I noticed your patch in openssl3.0 branch.
> Because the Tls cert time check needs to be solved as soon as possible,
> I will cherry-pick your patch to 1.1.1 branch instead of updating edk2 openssl to 3.0. The latter seems to take a long time.
> 
> By the way, I remember you are already working on upstream openssl3.0, right?

Tried, yes (that's why it is fixed already in upstream openssl3).

> How is it doing now, I can help with some work if needed.

The blocker is that openssl 3 noticeable larger than the 1.1.1 version.
Which is according to Jiewen Yao not acceptable because it wouldn't
fit into the flash layout for existing roms.

I don't have any good idea how to move forward with this.  My old WIP
branch is here:

https://github.com/kraxel/edk2/commits/archive/openssl3-v1

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96515): https://edk2.groups.io/g/devel/message/96515
Mute This Topic: https://groups.io/mt/95135786/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib
Posted by Yao, Jiewen 1 year, 5 months ago
Right. Size is the biggest concern, because some platforms already have limited space based on our internal survey. If we migrate to openssl3 directly, then we have no way to build these platforms.

One idea of size optimization is to use MACRO to disable some features in openssl, if they are not needed by UEFI.
It could be the MACRO already defined by openssl, or we may add new MACRO to make it smaller.

Thank you
Yao, Jiewen

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Gerd
> Hoffmann
> Sent: Monday, November 21, 2022 5:22 PM
> To: devel@edk2.groups.io; Li, Yi1 <yi1.li@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Yao,
> Jiewen <jiewen.yao@intel.com>
> Subject: Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed
> floating-point to OpensslLib
> 
> On Mon, Nov 21, 2022 at 08:31:19AM +0000, Li, Yi wrote:
> > Hi Gerd,
> >
> > Cool! I noticed your patch in openssl3.0 branch.
> > Because the Tls cert time check needs to be solved as soon as possible,
> > I will cherry-pick your patch to 1.1.1 branch instead of updating edk2
> openssl to 3.0. The latter seems to take a long time.
> >
> > By the way, I remember you are already working on upstream openssl3.0,
> right?
> 
> Tried, yes (that's why it is fixed already in upstream openssl3).
> 
> > How is it doing now, I can help with some work if needed.
> 
> The blocker is that openssl 3 noticeable larger than the 1.1.1 version.
> Which is according to Jiewen Yao not acceptable because it wouldn't
> fit into the flash layout for existing roms.
> 
> I don't have any good idea how to move forward with this.  My old WIP
> branch is here:
> 
> https://github.com/kraxel/edk2/commits/archive/openssl3-v1
> 
> take care,
>   Gerd
> 
> 
> 
> 
> 



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96516): https://edk2.groups.io/g/devel/message/96516
Mute This Topic: https://groups.io/mt/95135786/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib
Posted by Li, Yi 1 year, 5 months ago
Hi Jiewen,

Oh, I didn't realize we had this macro, maybe we could use it to eliminate floating point actions and upstream to openssl.

If it can be upstreamed, then we don't need these workarounds, I will try to do these things, thank you.

-----Original Message-----
From: Yao, Jiewen <jiewen.yao@intel.com> 
Sent: Sunday, November 20, 2022 10:19 AM
To: Li, Yi1 <yi1.li@intel.com>; devel@edk2.groups.io
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
Subject: RE: [PATCH] CryptoPkg: Add b_print.c which removed floating-point to OpensslLib

HI Yi
I have question for 1 - The original file uses code related to floating-point and ulldrvm.

a) Openssl supports OPENSSL_SYS_UEFI macro (https://github.com/tianocore/edk2/blob/master/CryptoPkg/Library/Include/openssl/opensslconf.h#L28), why not use OPENSSL_SYS_UEFI macro to eliminate float point action?

b) For ulldrvm, why not implement it in https://github.com/tianocore/edk2/tree/master/CryptoPkg/Library/IntrinsicLib, as we already did.

Thank you
Yao, Jiewen

> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Sunday, November 20, 2022 12:33 AM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J 
> <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, 
> Guomin <guomin.jiang@intel.com>
> Subject: RE: [PATCH] CryptoPkg: Add b_print.c which removed floating- 
> point to OpensslLib
> 
> Hi all,
> 
> This patch is the pre-work for enabling the X509 certificate time check.
> I know it looks weird to add a new b_print.c, so I wanted to explain 
> the background of this patch.
> 
> 1. Why not directly use the b_print.c file in openssl?
> The original file uses code related to floating-point and ulldrvm, 
> which will cause compilation errors like:
> unresolved external symbol __aulldvrm
> error: SSE register return with SSE disabled
> ref: https://github.com/tianocore/edk2/pull/3508
> 
> So I removed all float code and replaced ulldrvm with
> DivU64x32Remainder():
> 1).
>             case 'f':
>             case 'E':
>             case 'e':
>             case 'G':
>             case 'g':
>                 return -1;
> 2).
> +        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, 
> + &uremainder);
>          convert[place++] = (caps ? "0123456789ABCDEF" :
> "0123456789abcdef")
> -            [uvalue % (unsigned)base];
> -        uvalue = (uvalue / (unsigned)base);
> +            [uremainder];
> 
> 
> 2. Why not use the similar print function AsciiVSPrint in EDK2?
> EDK2 functions are all ms_abi but openssl functions not, so they use 
> different va_list definitions, the relevant codes are as follows:
> GCC:*_*_X64_CC_FLAGS     = ......  -DNO_MSABI_VA_FUNCS
> https://github.com/tianocore/edk2/blob/fff6d81270b57ee786ea18ad74f4
> 3149b9f03494/CryptoPkg/Library/OpensslLib/OpensslLib.inf#LL636C2-
> L636C3
> 
> Therefore, segmentation fault will occur when calling the edk2 VA 
> parameter function in the openssl function.
> 
> 3. Why not remove NO_MSABI_VA_FUNCS?
> Similarly, ms va_list cannot be used in the sysv function in openssl, 
> which will also cause segmentation fault.
> 
> I am not expert of compilation, let me know if there is other better idea.
> 
> Thanks,
> Yi
> 
> -----Original Message-----
> From: Li, Yi1 <yi1.li@intel.com>
> Sent: Sunday, November 20, 2022 12:28 AM
> To: devel@edk2.groups.io
> Cc: Li, Yi1 <yi1.li@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; 
> Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 
> <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: [PATCH] CryptoPkg: Add b_print.c which removed floating-point 
> to OpensslLib
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4110
> 
> Openssl will use BIO_snprintf() to print time string when converting 
> time_t to ASN1_time.
> Currently edk2 code just give it a NULL implement in CrtWrapper.c, so 
> getting current time in X509 time check will be fail.
> 
> This patch add a copy of OpensslLib\openssl\crypto\bio\b_print.c to 
> OpensslLib, with below changes:
> 
> 1. All floating point related code removed.
> 2. Replace ull divide and remainder with DivU64x32Remainder().
> 
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> Cc: Guomin Jiang <guomin.jiang@intel.com>
> Signed-off-by: Yi Li <yi1.li@intel.com>
> ---
>  CryptoPkg/CryptoPkg.ci.yaml                   |   4 +-
>  .../Library/BaseCryptLib/SysCall/CrtWrapper.c |  27 -
>  .../SysCall/UnitTestHostCrtWrapper.c          |  25 -
>  CryptoPkg/Library/OpensslLib/OpensslLib.inf   |   1 +
>  .../Library/OpensslLib/OpensslLibAccel.inf    |   1 +
>  .../Library/OpensslLib/OpensslLibCrypto.inf   |   1 +
>  .../Library/OpensslLib/OpensslLibFull.inf     |   1 +
>  .../OpensslLib/OpensslLibFullAccel.inf        |   1 +
>  CryptoPkg/Library/OpensslLib/b_print.c        | 613 ++++++++++++++++++
>  9 files changed, 621 insertions(+), 53 deletions(-)  create mode 
> 100644 CryptoPkg/Library/OpensslLib/b_print.c
> 
> diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml 
> index 47f2975967..8c25f581fb 100644
> --- a/CryptoPkg/CryptoPkg.ci.yaml
> +++ b/CryptoPkg/CryptoPkg.ci.yaml
> @@ -13,7 +13,9 @@
>              "Library/OpensslLib/IA32Gcc",
>              "Library/OpensslLib/X64",
>              "Library/OpensslLib/X64Gcc",
> -            "Library/Include/openssl"
> +            "Library/Include/openssl",
> +            # b_print.c is a copy from OpenSSl.
> +            "Library/OpensslLib/b_print.c"
>          ]
>      },
>      "EccCheck": {
> diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> index b65d29485b..6d7ac3efdc 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
> @@ -472,33 +472,6 @@ fwrite (
>    return 0;
>  }
> 
> -//
> -//  -- Dummy OpenSSL Support Routines -- -//
> -
> -int
> -BIO_printf (
> -  void        *bio,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
> -int
> -BIO_snprintf (
> -  char        *buf,
> -  size_t      n,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  // Because the function does not actually print anything to buf, it 
> returns
> -1 as error.
> -  // Otherwise, the consumer may think that the buf is valid and 
> parse the buffer.
> -  return -1;
> -}
> -
>  #ifdef __GNUC__
> 
>  typedef
> diff --git
> a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> index 066d53e4fa..244e57437e 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
> @@ -72,31 +72,6 @@ sscanf (
>    return 0;
>  }
> 
> -//
> -//  -- Dummy OpenSSL Support Routines -- -//
> -
> -int
> -BIO_printf (
> -  void        *bio,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
> -int
> -BIO_snprintf (
> -  char        *buf,
> -  size_t      n,
> -  const char  *format,
> -  ...
> -  )
> -{
> -  return 0;
> -}
> -
>  uid_t
>  getuid (
>    void
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> index 60c6c24b0a..f8ddfadc51 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
> @@ -580,6 +580,7 @@
>    rand_pool.c
>  #  SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> index 103ef7bda2..6ee7bfd329 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibAccel.inf
> @@ -580,6 +580,7 @@
>    rand_pool.c
>  #  SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Sources.IA32]
>  # Autogenerated IA32 files list starts here diff --git 
> a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> index c4eaea888c..3e43cf146b 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
> @@ -530,6 +530,7 @@
>    rand_pool.c
>    SslNull.c
>    EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> index 309e43055c..440d3e7e1d 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
> @@ -635,6 +635,7 @@
>    rand_pool.c
>  #  SslNull.c
>  #  EcSm2Null.c
> +  b_print.c
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> index 4eeeeb79bd..413f70f733 100644
> --- a/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> +++ b/CryptoPkg/Library/OpensslLib/OpensslLibFullAccel.inf
> @@ -635,6 +635,7 @@
>    rand_pool.c
>  #  SslNull.c
>  #  EcSm2Null.c
> +  b_print.c
> 
>  [Sources.IA32]
>  # Autogenerated IA32 files list starts here diff --git 
> a/CryptoPkg/Library/OpensslLib/b_print.c
> b/CryptoPkg/Library/OpensslLib/b_print.c
> new file mode 100644
> index 0000000000..885c3b9264
> --- /dev/null
> +++ b/CryptoPkg/Library/OpensslLib/b_print.c
> @@ -0,0 +1,613 @@
> +/*
> + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
> + *
> + * Licensed under the OpenSSL license (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
> + * https://www.openssl.org/source/license.html
> + *
> + * Please notes:
> + * This file is a copy of OpensslLib\openssl\crypto\bio\b_print.c
> + * with all floating point related code removed (Not supported in UEFI).
> + * This means that '%f' '%g' '%e' and related combined formats are no
> longer supported.
> + *
> + */
> +
> +#include <stdio.h>
> +#include <string.h>
> +#include "internal/cryptlib.h"
> +#include "crypto/ctype.h"
> +#include "internal/numbers.h"
> +#include <openssl/bio.h>
> +
> +/*
> + * Copyright Patrick Powell 1995
> + * This code is based on code written by Patrick Powell 
> +<papowell@astart.com>
> + * It may be used for any purpose as long as this notice remains 
> +intact
> + * on all source code distributions.
> + */
> +
> +static int fmtstr(char **, char **, size_t *, size_t *,
> +                  const char *, int, int, int); static int 
> +fmtint(char **, char **, size_t *, size_t *,
> +                  int64_t, int, int, int, int); static int 
> +doapr_outch(char **, char **, size_t *, size_t *, int); static int 
> +_dopr(char **sbuffer, char **buffer,
> +                 size_t *maxlen, size_t *retlen, int *truncated,
> +                 const char *format, va_list args);
> +
> +/* format read states */
> +#define DP_S_DEFAULT    0
> +#define DP_S_FLAGS      1
> +#define DP_S_MIN        2
> +#define DP_S_DOT        3
> +#define DP_S_MAX        4
> +#define DP_S_MOD        5
> +#define DP_S_CONV       6
> +#define DP_S_DONE       7
> +
> +/* format flags - Bits */
> +/* left-aligned padding */
> +#define DP_F_MINUS      (1 << 0)
> +/* print an explicit '+' for a value with positive sign */
> +#define DP_F_PLUS       (1 << 1)
> +/* print an explicit ' ' for a value with positive sign */
> +#define DP_F_SPACE      (1 << 2)
> +/* print 0/0x prefix for octal/hex and decimal point for floating point */
> +#define DP_F_NUM        (1 << 3)
> +/* print leading zeroes */
> +#define DP_F_ZERO       (1 << 4)
> +/* print HEX in UPPPERcase */
> +#define DP_F_UP         (1 << 5)
> +/* treat value as unsigned */
> +#define DP_F_UNSIGNED   (1 << 6)
> +
> +/* conversion flags */
> +#define DP_C_SHORT      1
> +#define DP_C_LONG       2
> +// #define DP_C_LDOUBLE    3
> +#define DP_C_LLONG      4
> +#define DP_C_SIZE       5
> +
> +/* Floating point formats */
> +// #define F_FORMAT        0
> +// #define E_FORMAT        1
> +// #define G_FORMAT        2
> +
> +/* some handy macros */
> +#define char_to_int(p) (p - '0')
> +#define OSSL_MAX(p,q) ((p >= q) ? p : q)
> +
> +static int
> +_dopr(char **sbuffer,
> +      char **buffer,
> +      size_t *maxlen,
> +      size_t *retlen, int *truncated, const char *format, va_list 
> +args) {
> +    char ch;
> +    int64_t value;
> +    char *strvalue;
> +    int min;
> +    int max;
> +    int state;
> +    int flags;
> +    int cflags;
> +    size_t currlen;
> +
> +    state = DP_S_DEFAULT;
> +    flags = currlen = cflags = min = 0;
> +    max = -1;
> +    ch = *format++;
> +
> +    while (state != DP_S_DONE) {
> +        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
> +            state = DP_S_DONE;
> +
> +        switch (state) {
> +        case DP_S_DEFAULT:
> +            if (ch == '%')
> +                state = DP_S_FLAGS;
> +            else
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
> +                    return 0;
> +            ch = *format++;
> +            break;
> +        case DP_S_FLAGS:
> +            switch (ch) {
> +            case '-':
> +                flags |= DP_F_MINUS;
> +                ch = *format++;
> +                break;
> +            case '+':
> +                flags |= DP_F_PLUS;
> +                ch = *format++;
> +                break;
> +            case ' ':
> +                flags |= DP_F_SPACE;
> +                ch = *format++;
> +                break;
> +            case '#':
> +                flags |= DP_F_NUM;
> +                ch = *format++;
> +                break;
> +            case '0':
> +                flags |= DP_F_ZERO;
> +                ch = *format++;
> +                break;
> +            default:
> +                state = DP_S_MIN;
> +                break;
> +            }
> +            break;
> +        case DP_S_MIN:
> +            if (ossl_isdigit(ch)) {
> +                min = 10 * min + char_to_int(ch);
> +                ch = *format++;
> +            } else if (ch == '*') {
> +                min = va_arg(args, int);
> +                ch = *format++;
> +                state = DP_S_DOT;
> +            } else
> +                state = DP_S_DOT;
> +            break;
> +        case DP_S_DOT:
> +            if (ch == '.') {
> +                state = DP_S_MAX;
> +                ch = *format++;
> +            } else
> +                state = DP_S_MOD;
> +            break;
> +        case DP_S_MAX:
> +            if (ossl_isdigit(ch)) {
> +                if (max < 0)
> +                    max = 0;
> +                max = 10 * max + char_to_int(ch);
> +                ch = *format++;
> +            } else if (ch == '*') {
> +                max = va_arg(args, int);
> +                ch = *format++;
> +                state = DP_S_MOD;
> +            } else
> +                state = DP_S_MOD;
> +            break;
> +        case DP_S_MOD:
> +            switch (ch) {
> +            case 'h':
> +                cflags = DP_C_SHORT;
> +                ch = *format++;
> +                break;
> +            case 'l':
> +                if (*format == 'l') {
> +                    cflags = DP_C_LLONG;
> +                    format++;
> +                } else
> +                    cflags = DP_C_LONG;
> +                ch = *format++;
> +                break;
> +            case 'q':
> +            case 'j':
> +                cflags = DP_C_LLONG;
> +                ch = *format++;
> +                break;
> +            case 'L':
> +                //Unsupported fmt in UEFI
> +                return -1;
> +            case 'z':
> +                cflags = DP_C_SIZE;
> +                ch = *format++;
> +                break;
> +            default:
> +                break;
> +            }
> +            state = DP_S_CONV;
> +            break;
> +        case DP_S_CONV:
> +            switch (ch) {
> +            case 'd':
> +            case 'i':
> +                switch (cflags) {
> +                case DP_C_SHORT:
> +                    value = (short int)va_arg(args, int);
> +                    break;
> +                case DP_C_LONG:
> +                    value = va_arg(args, long int);
> +                    break;
> +                case DP_C_LLONG:
> +                    value = va_arg(args, int64_t);
> +                    break;
> +                case DP_C_SIZE:
> +                    value = va_arg(args, ossl_ssize_t);
> +                    break;
> +                default:
> +                    value = va_arg(args, int);
> +                    break;
> +                }
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
> +                            max, flags))
> +                    return 0;
> +                break;
> +            case 'X':
> +                flags |= DP_F_UP;
> +                /* FALLTHROUGH */
> +            case 'x':
> +            case 'o':
> +            case 'u':
> +                flags |= DP_F_UNSIGNED;
> +                switch (cflags) {
> +                case DP_C_SHORT:
> +                    value = (unsigned short int)va_arg(args, unsigned int);
> +                    break;
> +                case DP_C_LONG:
> +                    value = va_arg(args, unsigned long int);
> +                    break;
> +                case DP_C_LLONG:
> +                    value = va_arg(args, uint64_t);
> +                    break;
> +                case DP_C_SIZE:
> +                    value = va_arg(args, size_t);
> +                    break;
> +                default:
> +                    value = va_arg(args, unsigned int);
> +                    break;
> +                }
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
> +                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
> +                            min, max, flags))
> +                    return 0;
> +                break;
> +            case 'f':
> +            case 'E':
> +            case 'e':
> +            case 'G':
> +            case 'g':
> +                return -1;
> +            case 'c':
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
> +                                 va_arg(args, int)))
> +                    return 0;
> +                break;
> +            case 's':
> +                strvalue = va_arg(args, char *);
> +                if (max < 0) {
> +                    if (buffer)
> +                        max = INT_MAX;
> +                    else
> +                        max = *maxlen;
> +                }
> +                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
> +                            flags, min, max))
> +                    return 0;
> +                break;
> +            case 'p':
> +                value = (size_t)va_arg(args, void *);
> +                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
> +                            value, 16, min, max, flags | DP_F_NUM))
> +                    return 0;
> +                break;
> +            case 'n':
> +                {
> +                    int *num;
> +                    num = va_arg(args, int *);
> +                    *num = currlen;
> +                }
> +                break;
> +            case '%':
> +                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
> +                    return 0;
> +                break;
> +            case 'w':
> +                /* not supported yet, treat as next char */
> +                ch = *format++;
> +                break;
> +            default:
> +                /* unknown, skip */
> +                break;
> +            }
> +            ch = *format++;
> +            state = DP_S_DEFAULT;
> +            flags = cflags = min = 0;
> +            max = -1;
> +            break;
> +        case DP_S_DONE:
> +            break;
> +        default:
> +            break;
> +        }
> +    }
> +    /*
> +     * We have to truncate if there is no dynamic buffer and we have 
> + filled
> the
> +     * static buffer.
> +     */
> +    if (buffer == NULL) {
> +        *truncated = (currlen > *maxlen - 1);
> +        if (*truncated)
> +            currlen = *maxlen - 1;
> +    }
> +    if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
> +        return 0;
> +    *retlen = currlen - 1;
> +    return 1;
> +}
> +
> +static int
> +fmtstr(char **sbuffer,
> +       char **buffer,
> +       size_t *currlen,
> +       size_t *maxlen, const char *value, int flags, int min, int 
> +max) {
> +    int padlen;
> +    size_t strln;
> +    int cnt = 0;
> +
> +    if (value == 0)
> +        value = "<NULL>";
> +
> +    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
> +
> +    padlen = min - strln;
> +    if (min < 0 || padlen < 0)
> +        padlen = 0;
> +    if (max >= 0) {
> +        /*
> +         * Calculate the maximum output including padding.
> +         * Make sure max doesn't overflow into negativity
> +         */
> +        if (max < INT_MAX - padlen)
> +            max += padlen;
> +        else
> +            max = INT_MAX;
> +    }
> +    if (flags & DP_F_MINUS)
> +        padlen = -padlen;
> +
> +    while ((padlen > 0) && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        --padlen;
> +        ++cnt;
> +    }
> +    while (strln > 0 && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
> +            return 0;
> +        --strln;
> +        ++cnt;
> +    }
> +    while ((padlen < 0) && (max < 0 || cnt < max)) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        ++padlen;
> +        ++cnt;
> +    }
> +    return 1;
> +}
> +
> +static int
> +fmtint(char **sbuffer,
> +       char **buffer,
> +       size_t *currlen,
> +       size_t *maxlen, int64_t value, int base, int min, int max, int
> +flags) {
> +    int signvalue = 0;
> +    const char *prefix = "";
> +    uint64_t uvalue;
> +    char convert[DECIMAL_SIZE(value) + 3];
> +    int place = 0;
> +    int spadlen = 0;
> +    int zpadlen = 0;
> +    int caps = 0;
> +    uint32_t uremainder = 0;
> +
> +    if (max < 0)
> +        max = 0;
> +    uvalue = value;
> +    if (!(flags & DP_F_UNSIGNED)) {
> +        if (value < 0) {
> +            signvalue = '-';
> +            uvalue = 0 - (uint64_t)value;
> +        } else if (flags & DP_F_PLUS)
> +            signvalue = '+';
> +        else if (flags & DP_F_SPACE)
> +            signvalue = ' ';
> +    }
> +    if (flags & DP_F_NUM) {
> +        if (base == 8)
> +            prefix = "0";
> +        if (base == 16)
> +            prefix = "0x";
> +    }
> +    if (flags & DP_F_UP)
> +        caps = 1;
> +    do {
> +        uvalue = DivU64x32Remainder(uvalue, (unsigned)base, &uremainder);
> +        convert[place++] = (caps ? "0123456789ABCDEF" :
> "0123456789abcdef")
> +            [uremainder];
> +    } while (uvalue && (place < (int)sizeof(convert)));
> +    if (place == sizeof(convert))
> +        place--;
> +    convert[place] = 0;
> +
> +    zpadlen = max - place;
> +    spadlen =
> +        min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
> +    if (zpadlen < 0)
> +        zpadlen = 0;
> +    if (spadlen < 0)
> +        spadlen = 0;
> +    if (flags & DP_F_ZERO) {
> +        zpadlen = OSSL_MAX(zpadlen, spadlen);
> +        spadlen = 0;
> +    }
> +    if (flags & DP_F_MINUS)
> +        spadlen = -spadlen;
> +
> +    /* spaces */
> +    while (spadlen > 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        --spadlen;
> +    }
> +
> +    /* sign */
> +    if (signvalue)
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
> +            return 0;
> +
> +    /* prefix */
> +    while (*prefix) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
> +            return 0;
> +        prefix++;
> +    }
> +
> +    /* zeros */
> +    if (zpadlen > 0) {
> +        while (zpadlen > 0) {
> +            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
> +                return 0;
> +            --zpadlen;
> +        }
> +    }
> +    /* digits */
> +    while (place > 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
> +            return 0;
> +    }
> +
> +    /* left justified spaces */
> +    while (spadlen < 0) {
> +        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
> +            return 0;
> +        ++spadlen;
> +    }
> +    return 1;
> +}
> +
> +#define BUFFER_INC  1024
> +
> +static int
> +doapr_outch(char **sbuffer,
> +            char **buffer, size_t *currlen, size_t *maxlen, int c) {
> +    /* If we haven't at least one buffer, someone has done a big booboo */
> +    if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
> +        return 0;
> +
> +    /* |currlen| must always be <= |*maxlen| */
> +    if (!ossl_assert(*currlen <= *maxlen))
> +        return 0;
> +
> +    if (buffer && *currlen == *maxlen) {
> +        if (*maxlen > INT_MAX - BUFFER_INC)
> +            return 0;
> +
> +        *maxlen += BUFFER_INC;
> +        if (*buffer == NULL) {
> +            if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
> +                BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
> +                return 0;
> +            }
> +            if (*currlen > 0) {
> +                if (!ossl_assert(*sbuffer != NULL))
> +                    return 0;
> +                memcpy(*buffer, *sbuffer, *currlen);
> +            }
> +            *sbuffer = NULL;
> +        } else {
> +            char *tmpbuf;
> +            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
> +            if (tmpbuf == NULL)
> +                return 0;
> +            *buffer = tmpbuf;
> +        }
> +    }
> +
> +    if (*currlen < *maxlen) {
> +        if (*sbuffer)
> +            (*sbuffer)[(*currlen)++] = (char)c;
> +        else
> +            (*buffer)[(*currlen)++] = (char)c;
> +    }
> +
> +    return 1;
> +}
> +
> +/*********************************************************
> *************
> +*****/
> +
> +int BIO_printf(BIO *bio, const char *format, ...) {
> +    va_list args;
> +    int ret;
> +
> +    va_start(args, format);
> +
> +    ret = BIO_vprintf(bio, format, args);
> +
> +    va_end(args);
> +    return ret;
> +}
> +
> +int BIO_vprintf(BIO *bio, const char *format, va_list args) {
> +    int ret;
> +    size_t retlen;
> +    char hugebuf[1024 * 2];     /* Was previously 10k, which is
> unreasonable
> +                                 * in small-stack environments, like threads
> +                                 * or DOS programs. */
> +    char *hugebufp = hugebuf;
> +    size_t hugebufsize = sizeof(hugebuf);
> +    char *dynbuf = NULL;
> +    int ignored;
> +
> +    dynbuf = NULL;
> +    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored,
> format,
> +                args)) {
> +        OPENSSL_free(dynbuf);
> +        return -1;
> +    }
> +    if (dynbuf) {
> +        ret = BIO_write(bio, dynbuf, (int)retlen);
> +        OPENSSL_free(dynbuf);
> +    } else {
> +        ret = BIO_write(bio, hugebuf, (int)retlen);
> +    }
> +    return ret;
> +}
> +
> +/*
> + * As snprintf is not available everywhere, we provide our own
> + * implementation. This function has nothing to do with BIOs, but 
> +it's
> + * closely related to BIO_printf, and we need *some* name prefix ...
> +(XXX the
> + * function should be renamed, but to what?)  */ int 
> +BIO_snprintf(char *buf, size_t n, const char *format, ...) {
> +    va_list args;
> +    int ret;
> +
> +    va_start(args, format);
> +
> +    ret = BIO_vsnprintf(buf, n, format, args);
> +
> +    va_end(args);
> +    return ret;
> +}
> +
> +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list
> +args) {
> +    size_t retlen;
> +    int truncated;
> +
> +    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
> +        return -1;
> +
> +    if (truncated)
> +        /*
> +         * In case of truncation, return -1 like traditional snprintf.
> +         * (Current drafts for ISO/IEC 9899 say snprintf should return the
> +         * number of characters that would have been written, had the buffer
> +         * been large enough.)
> +         */
> +        return -1;
> +    else
> +        return (retlen <= INT_MAX) ? (int)retlen : -1; }
> --
> 2.31.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96506): https://edk2.groups.io/g/devel/message/96506
Mute This Topic: https://groups.io/mt/95135786/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-