I'm using HPUX 11.23, Itanium,  openssl-0.9.8d, cc 6.10

I seem to have found a contradiction in the build environment and I
don't think it is specific to HPUX, but rather to platforms who have a
64bit 'long long' and require a "%ll" to print them.

What we want to build is a 32bit binary build using 64bit longs -- i.e.,
long long.  The build actually passes the make test, but a simple test
program exercising bn2dec() fails with what looks like a 64bit value
truncated to 32bit.  We're using the default build flags for
hpux-ia64-cc

This test program shows that the 64bit value is truncated in the string
generation:

Output --

Input bytes: 255,255,255,255,255,
Input size (bytes): 5
BIGNUM top: 1
BIGNUM dmax: 1
BIGNUM neg: 0
BIGNUM flags: 1
BIGNUM bit chunks: 0x000000ffffffffff,
String Format: 4294967295

Source --

#include <openssl/crypto.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <openssl/dh.h>
 
#include <string.h>
 
int main(int argc, char* argv[])
{
#define NUM_LENGTH sizeof(num)
        const unsigned char num[5] = {255, 255, 255, 255, 255}; 
 
        printf("Input bytes: ");
        for (int i = 0; i < NUM_LENGTH; ++i)
        {
            printf("%d,", num[i]);
        }
        printf("\n");
        printf("Input size (bytes): %d\n", NUM_LENGTH);
 
 
        BIGNUM* keyNum = BN_bin2bn(num, NUM_LENGTH, 0);
        printf("BIGNUM top: %d\n", keyNum->top);
        printf("BIGNUM dmax: %d\n", keyNum->dmax);
        printf("BIGNUM neg: %d\n", keyNum->neg);
        printf("BIGNUM flags: %d\n", keyNum->flags);
        printf("BIGNUM bit chunks: ");
        for (int k = 0; k < keyNum->top; ++k)
        {
            printf("0x%016llx,", keyNum->d[k]);
        }
        printf("\n");
 
 
        char* decBuf = 0;
        decBuf = BN_bn2dec(keyNum);
        printf("String Format: %s\n", decBuf);
 
        return 0;
}

Tracing through the openssl code I found that BIO_snprintf() is the
problem (substituting libc's native vsnprintf() fixes the problem):

b_print.c's _dopr() uses a 32bit variable (called value) as the lvalue
to the var_arg(args, long long) call causing the truncation.  But
'value' is declared as a LLONG.  Backtracing through the code, LLONG is
defined as 'long long' if BN_LLONG is defined (otherwise it is simply a
long).  But when you define SIXTY_FOUR_BIT, BN_LLONG is explicitly
UNDEFINED.  And as far as I can tell, SIXTY_FOUR_BIT is required in
order to get BN_DEC_FMT1/FMT2 to be defined as %ll's and not %l.  Hence
a contradiction...

The safest workaround for now seems to just have BI_snprintf() call the
native vsnprintf().  

If someone needs a test system, one can usually be accessed via
http://www.testdrive.hp.com/.  I can try to help expedite the
application process if necessary.

------------------------- snippets from b_print.c
[...]
#ifdef BN_LLONG
# ifndef HAVE_LONG_LONG
#  define HAVE_LONG_LONG 1
# endif
#endif
[...]
#if HAVE_LONG_LONG
# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
# define LLONG _int64
# else
# define LLONG long long
# endif
#else
#define LLONG long
#endif
[...]
static void
_dopr(
    char **sbuffer,
    char **buffer,
    size_t *maxlen,
    size_t *retlen,
    int *truncated,
    const char *format,
    va_list args)
{
    char ch;
    LLONG value; <<<<<<<<<<
    LDOUBLE fvalue;
    char *strvalue;
    int min;
    int max;
    int state;
    int flags;
    int cflags;
    size_t currlen;
[...]
                case DP_C_LLONG:
                    value = va_arg(args, unsigned LLONG); <<<<<<<<<
                    break;
                default:


-------------------------  bn.h
/* This is where the long long data type is 64 bits, but long is 32.
 * For machines where there are 64bit registers, this is the mode to use.
 * IRIX, on R4000 and above should use this mode, along with the relevant
 * assembler code :-).  Do NOT define BN_LLONG.
 */
#ifdef SIXTY_FOUR_BIT
#undef BN_LLONG           <<<<<<<<<<<<<<<<<<<<<<<
#undef BN_ULLONG
#define BN_ULONG        unsigned long long
#define BN_LONG         long long
#define BN_BITS         128
#define BN_BYTES        8
#define BN_BITS2        64
#define BN_BITS4        32
#define BN_MASK2        (0xffffffffffffffffLL)
#define BN_MASK2l       (0xffffffffL)
#define BN_MASK2h       (0xffffffff00000000LL)
#define BN_MASK2h1      (0xffffffff80000000LL)
#define BN_TBIT         (0x8000000000000000LL)
#define BN_DEC_CONV     (10000000000000000000ULL)
#define BN_DEC_FMT1     "%llu"
#define BN_DEC_FMT2     "%019llu"
#define BN_DEC_NUM      19
#endif

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to