1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include "../testutil.h" 11e1051a39Sopenharmony_ci#include "output.h" 12e1051a39Sopenharmony_ci#include "tu_local.h" 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#include <string.h> 15e1051a39Sopenharmony_ci#include <ctype.h> 16e1051a39Sopenharmony_ci#include "internal/nelem.h" 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci/* The size of memory buffers to display on failure */ 19e1051a39Sopenharmony_ci#define MEM_BUFFER_SIZE (2000) 20e1051a39Sopenharmony_ci#define MAX_STRING_WIDTH (80) 21e1051a39Sopenharmony_ci#define BN_OUTPUT_SIZE (8) 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_ci/* Output a diff header */ 24e1051a39Sopenharmony_cistatic void test_diff_header(const char *left, const char *right) 25e1051a39Sopenharmony_ci{ 26e1051a39Sopenharmony_ci test_printf_stderr("--- %s\n", left); 27e1051a39Sopenharmony_ci test_printf_stderr("+++ %s\n", right); 28e1051a39Sopenharmony_ci} 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci/* Formatted string output routines */ 31e1051a39Sopenharmony_cistatic void test_string_null_empty(const char *m, char c) 32e1051a39Sopenharmony_ci{ 33e1051a39Sopenharmony_ci if (m == NULL) 34e1051a39Sopenharmony_ci test_printf_stderr("%4s %c NULL\n", "", c); 35e1051a39Sopenharmony_ci else 36e1051a39Sopenharmony_ci test_printf_stderr("%4u:%c ''\n", 0u, c); 37e1051a39Sopenharmony_ci} 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_cistatic void test_fail_string_common(const char *prefix, const char *file, 40e1051a39Sopenharmony_ci int line, const char *type, 41e1051a39Sopenharmony_ci const char *left, const char *right, 42e1051a39Sopenharmony_ci const char *op, const char *m1, size_t l1, 43e1051a39Sopenharmony_ci const char *m2, size_t l2) 44e1051a39Sopenharmony_ci{ 45e1051a39Sopenharmony_ci const size_t width = 46e1051a39Sopenharmony_ci (MAX_STRING_WIDTH - BIO_get_indent(bio_err) - 12) / 16 * 16; 47e1051a39Sopenharmony_ci char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; 48e1051a39Sopenharmony_ci char bdiff[MAX_STRING_WIDTH + 1]; 49e1051a39Sopenharmony_ci size_t n1, n2, i; 50e1051a39Sopenharmony_ci unsigned int cnt = 0, diff; 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ci test_fail_message_prefix(prefix, file, line, type, left, right, op); 53e1051a39Sopenharmony_ci if (m1 == NULL) 54e1051a39Sopenharmony_ci l1 = 0; 55e1051a39Sopenharmony_ci if (m2 == NULL) 56e1051a39Sopenharmony_ci l2 = 0; 57e1051a39Sopenharmony_ci if (l1 == 0 && l2 == 0) { 58e1051a39Sopenharmony_ci if ((m1 == NULL) == (m2 == NULL)) { 59e1051a39Sopenharmony_ci test_string_null_empty(m1, ' '); 60e1051a39Sopenharmony_ci } else { 61e1051a39Sopenharmony_ci test_diff_header(left, right); 62e1051a39Sopenharmony_ci test_string_null_empty(m1, '-'); 63e1051a39Sopenharmony_ci test_string_null_empty(m2, '+'); 64e1051a39Sopenharmony_ci } 65e1051a39Sopenharmony_ci goto fin; 66e1051a39Sopenharmony_ci } 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ci if (l1 != l2 || strncmp(m1, m2, l1) != 0) 69e1051a39Sopenharmony_ci test_diff_header(left, right); 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci while (l1 > 0 || l2 > 0) { 72e1051a39Sopenharmony_ci n1 = n2 = 0; 73e1051a39Sopenharmony_ci if (l1 > 0) { 74e1051a39Sopenharmony_ci b1[n1 = l1 > width ? width : l1] = 0; 75e1051a39Sopenharmony_ci for (i = 0; i < n1; i++) 76e1051a39Sopenharmony_ci b1[i] = isprint((unsigned char)m1[i]) ? m1[i] : '.'; 77e1051a39Sopenharmony_ci } 78e1051a39Sopenharmony_ci if (l2 > 0) { 79e1051a39Sopenharmony_ci b2[n2 = l2 > width ? width : l2] = 0; 80e1051a39Sopenharmony_ci for (i = 0; i < n2; i++) 81e1051a39Sopenharmony_ci b2[i] = isprint((unsigned char)m2[i]) ? m2[i] : '.'; 82e1051a39Sopenharmony_ci } 83e1051a39Sopenharmony_ci diff = 0; 84e1051a39Sopenharmony_ci i = 0; 85e1051a39Sopenharmony_ci if (n1 > 0 && n2 > 0) { 86e1051a39Sopenharmony_ci const size_t j = n1 < n2 ? n1 : n2; 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci for (; i < j; i++) 89e1051a39Sopenharmony_ci if (m1[i] == m2[i]) { 90e1051a39Sopenharmony_ci bdiff[i] = ' '; 91e1051a39Sopenharmony_ci } else { 92e1051a39Sopenharmony_ci bdiff[i] = '^'; 93e1051a39Sopenharmony_ci diff = 1; 94e1051a39Sopenharmony_ci } 95e1051a39Sopenharmony_ci bdiff[i] = '\0'; 96e1051a39Sopenharmony_ci } 97e1051a39Sopenharmony_ci if (n1 == n2 && !diff) { 98e1051a39Sopenharmony_ci test_printf_stderr("%4u: '%s'\n", cnt, n2 > n1 ? b2 : b1); 99e1051a39Sopenharmony_ci } else { 100e1051a39Sopenharmony_ci if (cnt == 0 && (m1 == NULL || *m1 == '\0')) 101e1051a39Sopenharmony_ci test_string_null_empty(m1, '-'); 102e1051a39Sopenharmony_ci else if (n1 > 0) 103e1051a39Sopenharmony_ci test_printf_stderr("%4u:- '%s'\n", cnt, b1); 104e1051a39Sopenharmony_ci if (cnt == 0 && (m2 == NULL || *m2 == '\0')) 105e1051a39Sopenharmony_ci test_string_null_empty(m2, '+'); 106e1051a39Sopenharmony_ci else if (n2 > 0) 107e1051a39Sopenharmony_ci test_printf_stderr("%4u:+ '%s'\n", cnt, b2); 108e1051a39Sopenharmony_ci if (diff && i > 0) 109e1051a39Sopenharmony_ci test_printf_stderr("%4s %s\n", "", bdiff); 110e1051a39Sopenharmony_ci } 111e1051a39Sopenharmony_ci if (m1 != NULL) 112e1051a39Sopenharmony_ci m1 += n1; 113e1051a39Sopenharmony_ci if (m2 != NULL) 114e1051a39Sopenharmony_ci m2 += n2; 115e1051a39Sopenharmony_ci l1 -= n1; 116e1051a39Sopenharmony_ci l2 -= n2; 117e1051a39Sopenharmony_ci cnt += width; 118e1051a39Sopenharmony_ci } 119e1051a39Sopenharmony_cifin: 120e1051a39Sopenharmony_ci test_flush_stderr(); 121e1051a39Sopenharmony_ci} 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci/* 124e1051a39Sopenharmony_ci * Wrapper routines so that the underlying code can be shared. 125e1051a39Sopenharmony_ci * The first is the call from inside the test utilities when a conditional 126e1051a39Sopenharmony_ci * fails. The second is the user's call to dump a string. 127e1051a39Sopenharmony_ci */ 128e1051a39Sopenharmony_civoid test_fail_string_message(const char *prefix, const char *file, 129e1051a39Sopenharmony_ci int line, const char *type, 130e1051a39Sopenharmony_ci const char *left, const char *right, 131e1051a39Sopenharmony_ci const char *op, const char *m1, size_t l1, 132e1051a39Sopenharmony_ci const char *m2, size_t l2) 133e1051a39Sopenharmony_ci{ 134e1051a39Sopenharmony_ci test_fail_string_common(prefix, file, line, type, left, right, op, 135e1051a39Sopenharmony_ci m1, l1, m2, l2); 136e1051a39Sopenharmony_ci test_printf_stderr("\n"); 137e1051a39Sopenharmony_ci} 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_civoid test_output_string(const char *name, const char *m, size_t l) 140e1051a39Sopenharmony_ci{ 141e1051a39Sopenharmony_ci test_fail_string_common("string", NULL, 0, NULL, NULL, NULL, name, 142e1051a39Sopenharmony_ci m, l, m, l); 143e1051a39Sopenharmony_ci} 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci/* BIGNUM formatted output routines */ 146e1051a39Sopenharmony_ci 147e1051a39Sopenharmony_ci/* 148e1051a39Sopenharmony_ci * A basic memory byte to hex digit converter with allowance for spacing 149e1051a39Sopenharmony_ci * every so often. 150e1051a39Sopenharmony_ci */ 151e1051a39Sopenharmony_cistatic void hex_convert_memory(const unsigned char *m, size_t n, char *b, 152e1051a39Sopenharmony_ci size_t width) 153e1051a39Sopenharmony_ci{ 154e1051a39Sopenharmony_ci size_t i; 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_ci for (i = 0; i < n; i++) { 157e1051a39Sopenharmony_ci const unsigned char c = *m++; 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ci *b++ = "0123456789abcdef"[c >> 4]; 160e1051a39Sopenharmony_ci *b++ = "0123456789abcdef"[c & 15]; 161e1051a39Sopenharmony_ci if (i % width == width - 1 && i != n - 1) 162e1051a39Sopenharmony_ci *b++ = ' '; 163e1051a39Sopenharmony_ci } 164e1051a39Sopenharmony_ci *b = '\0'; 165e1051a39Sopenharmony_ci} 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ci/* 168e1051a39Sopenharmony_ci * Constants to define the number of bytes to display per line and the number 169e1051a39Sopenharmony_ci * of characters these take. 170e1051a39Sopenharmony_ci */ 171e1051a39Sopenharmony_cistatic const int bn_bytes = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1) 172e1051a39Sopenharmony_ci * BN_OUTPUT_SIZE; 173e1051a39Sopenharmony_cistatic const int bn_chars = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1) 174e1051a39Sopenharmony_ci * (BN_OUTPUT_SIZE * 2 + 1) - 1; 175e1051a39Sopenharmony_ci 176e1051a39Sopenharmony_ci/* 177e1051a39Sopenharmony_ci * Output the header line for the bignum 178e1051a39Sopenharmony_ci */ 179e1051a39Sopenharmony_cistatic void test_bignum_header_line(void) 180e1051a39Sopenharmony_ci{ 181e1051a39Sopenharmony_ci test_printf_stderr(" %*s\n", bn_chars + 6, "bit position"); 182e1051a39Sopenharmony_ci} 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_cistatic const char *test_bignum_zero_null(const BIGNUM *bn) 185e1051a39Sopenharmony_ci{ 186e1051a39Sopenharmony_ci if (bn != NULL) 187e1051a39Sopenharmony_ci return BN_is_negative(bn) ? "-0" : "0"; 188e1051a39Sopenharmony_ci return "NULL"; 189e1051a39Sopenharmony_ci} 190e1051a39Sopenharmony_ci 191e1051a39Sopenharmony_ci/* 192e1051a39Sopenharmony_ci * Print a bignum zero taking care to include the correct sign. 193e1051a39Sopenharmony_ci * This routine correctly deals with a NULL bignum pointer as input. 194e1051a39Sopenharmony_ci */ 195e1051a39Sopenharmony_cistatic void test_bignum_zero_print(const BIGNUM *bn, char sep) 196e1051a39Sopenharmony_ci{ 197e1051a39Sopenharmony_ci const char *v = test_bignum_zero_null(bn); 198e1051a39Sopenharmony_ci const char *suf = bn != NULL ? ": 0" : ""; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci test_printf_stderr("%c%*s%s\n", sep, bn_chars, v, suf); 201e1051a39Sopenharmony_ci} 202e1051a39Sopenharmony_ci 203e1051a39Sopenharmony_ci/* 204e1051a39Sopenharmony_ci * Convert a section of memory from inside a bignum into a displayable 205e1051a39Sopenharmony_ci * string with appropriate visual aid spaces inserted. 206e1051a39Sopenharmony_ci */ 207e1051a39Sopenharmony_cistatic int convert_bn_memory(const unsigned char *in, size_t bytes, 208e1051a39Sopenharmony_ci char *out, int *lz, const BIGNUM *bn) 209e1051a39Sopenharmony_ci{ 210e1051a39Sopenharmony_ci int n = bytes * 2, i; 211e1051a39Sopenharmony_ci char *p = out, *q = NULL; 212e1051a39Sopenharmony_ci const char *r; 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci if (bn != NULL && !BN_is_zero(bn)) { 215e1051a39Sopenharmony_ci hex_convert_memory(in, bytes, out, BN_OUTPUT_SIZE); 216e1051a39Sopenharmony_ci if (*lz) { 217e1051a39Sopenharmony_ci for (; *p == '0' || *p == ' '; p++) 218e1051a39Sopenharmony_ci if (*p == '0') { 219e1051a39Sopenharmony_ci q = p; 220e1051a39Sopenharmony_ci *p = ' '; 221e1051a39Sopenharmony_ci n--; 222e1051a39Sopenharmony_ci } 223e1051a39Sopenharmony_ci if (*p == '\0') { 224e1051a39Sopenharmony_ci /* 225e1051a39Sopenharmony_ci * in[bytes] is defined because we're converting a non-zero 226e1051a39Sopenharmony_ci * number and we've not seen a non-zero yet. 227e1051a39Sopenharmony_ci */ 228e1051a39Sopenharmony_ci if ((in[bytes] & 0xf0) != 0 && BN_is_negative(bn)) { 229e1051a39Sopenharmony_ci *lz = 0; 230e1051a39Sopenharmony_ci *q = '-'; 231e1051a39Sopenharmony_ci n++; 232e1051a39Sopenharmony_ci } 233e1051a39Sopenharmony_ci } else { 234e1051a39Sopenharmony_ci *lz = 0; 235e1051a39Sopenharmony_ci if (BN_is_negative(bn)) { 236e1051a39Sopenharmony_ci /* 237e1051a39Sopenharmony_ci * This is valid because we always convert more digits than 238e1051a39Sopenharmony_ci * the number holds. 239e1051a39Sopenharmony_ci */ 240e1051a39Sopenharmony_ci *q = '-'; 241e1051a39Sopenharmony_ci n++; 242e1051a39Sopenharmony_ci } 243e1051a39Sopenharmony_ci } 244e1051a39Sopenharmony_ci } 245e1051a39Sopenharmony_ci return n; 246e1051a39Sopenharmony_ci } 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ci for (i = 0; i < n; i++) { 249e1051a39Sopenharmony_ci *p++ = ' '; 250e1051a39Sopenharmony_ci if (i % (2 * BN_OUTPUT_SIZE) == 2 * BN_OUTPUT_SIZE - 1 && i != n - 1) 251e1051a39Sopenharmony_ci *p++ = ' '; 252e1051a39Sopenharmony_ci } 253e1051a39Sopenharmony_ci *p = '\0'; 254e1051a39Sopenharmony_ci if (bn == NULL) 255e1051a39Sopenharmony_ci r = "NULL"; 256e1051a39Sopenharmony_ci else 257e1051a39Sopenharmony_ci r = BN_is_negative(bn) ? "-0" : "0"; 258e1051a39Sopenharmony_ci strcpy(p - strlen(r), r); 259e1051a39Sopenharmony_ci return 0; 260e1051a39Sopenharmony_ci} 261e1051a39Sopenharmony_ci 262e1051a39Sopenharmony_ci/* 263e1051a39Sopenharmony_ci * Common code to display either one or two bignums, including the diff 264e1051a39Sopenharmony_ci * pointers for changes (only when there are two). 265e1051a39Sopenharmony_ci */ 266e1051a39Sopenharmony_cistatic void test_fail_bignum_common(const char *prefix, const char *file, 267e1051a39Sopenharmony_ci int line, const char *type, 268e1051a39Sopenharmony_ci const char *left, const char *right, 269e1051a39Sopenharmony_ci const char *op, 270e1051a39Sopenharmony_ci const BIGNUM *bn1, const BIGNUM *bn2) 271e1051a39Sopenharmony_ci{ 272e1051a39Sopenharmony_ci const size_t bytes = bn_bytes; 273e1051a39Sopenharmony_ci char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; 274e1051a39Sopenharmony_ci char *p, bdiff[MAX_STRING_WIDTH + 1]; 275e1051a39Sopenharmony_ci size_t l1, l2, n1, n2, i, len; 276e1051a39Sopenharmony_ci unsigned int cnt, diff, real_diff; 277e1051a39Sopenharmony_ci unsigned char *m1 = NULL, *m2 = NULL; 278e1051a39Sopenharmony_ci int lz1 = 1, lz2 = 1; 279e1051a39Sopenharmony_ci unsigned char buffer[MEM_BUFFER_SIZE * 2], *bufp = buffer; 280e1051a39Sopenharmony_ci 281e1051a39Sopenharmony_ci test_fail_message_prefix(prefix, file, line, type, left, right, op); 282e1051a39Sopenharmony_ci l1 = bn1 == NULL ? 0 : (BN_num_bytes(bn1) + (BN_is_negative(bn1) ? 1 : 0)); 283e1051a39Sopenharmony_ci l2 = bn2 == NULL ? 0 : (BN_num_bytes(bn2) + (BN_is_negative(bn2) ? 1 : 0)); 284e1051a39Sopenharmony_ci if (l1 == 0 && l2 == 0) { 285e1051a39Sopenharmony_ci if ((bn1 == NULL) == (bn2 == NULL)) { 286e1051a39Sopenharmony_ci test_bignum_header_line(); 287e1051a39Sopenharmony_ci test_bignum_zero_print(bn1, ' '); 288e1051a39Sopenharmony_ci } else { 289e1051a39Sopenharmony_ci test_diff_header(left, right); 290e1051a39Sopenharmony_ci test_bignum_header_line(); 291e1051a39Sopenharmony_ci test_bignum_zero_print(bn1, '-'); 292e1051a39Sopenharmony_ci test_bignum_zero_print(bn2, '+'); 293e1051a39Sopenharmony_ci } 294e1051a39Sopenharmony_ci goto fin; 295e1051a39Sopenharmony_ci } 296e1051a39Sopenharmony_ci 297e1051a39Sopenharmony_ci if (l1 != l2 || bn1 == NULL || bn2 == NULL || BN_cmp(bn1, bn2) != 0) 298e1051a39Sopenharmony_ci test_diff_header(left, right); 299e1051a39Sopenharmony_ci test_bignum_header_line(); 300e1051a39Sopenharmony_ci 301e1051a39Sopenharmony_ci len = ((l1 > l2 ? l1 : l2) + bytes - 1) / bytes * bytes; 302e1051a39Sopenharmony_ci 303e1051a39Sopenharmony_ci if (len > MEM_BUFFER_SIZE && (bufp = OPENSSL_malloc(len * 2)) == NULL) { 304e1051a39Sopenharmony_ci bufp = buffer; 305e1051a39Sopenharmony_ci len = MEM_BUFFER_SIZE; 306e1051a39Sopenharmony_ci test_printf_stderr("WARNING: these BIGNUMs have been truncated\n"); 307e1051a39Sopenharmony_ci } 308e1051a39Sopenharmony_ci 309e1051a39Sopenharmony_ci if (bn1 != NULL) { 310e1051a39Sopenharmony_ci m1 = bufp; 311e1051a39Sopenharmony_ci BN_bn2binpad(bn1, m1, len); 312e1051a39Sopenharmony_ci } 313e1051a39Sopenharmony_ci if (bn2 != NULL) { 314e1051a39Sopenharmony_ci m2 = bufp + len; 315e1051a39Sopenharmony_ci BN_bn2binpad(bn2, m2, len); 316e1051a39Sopenharmony_ci } 317e1051a39Sopenharmony_ci 318e1051a39Sopenharmony_ci while (len > 0) { 319e1051a39Sopenharmony_ci cnt = 8 * (len - bytes); 320e1051a39Sopenharmony_ci n1 = convert_bn_memory(m1, bytes, b1, &lz1, bn1); 321e1051a39Sopenharmony_ci n2 = convert_bn_memory(m2, bytes, b2, &lz2, bn2); 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ci diff = real_diff = 0; 324e1051a39Sopenharmony_ci i = 0; 325e1051a39Sopenharmony_ci p = bdiff; 326e1051a39Sopenharmony_ci for (i=0; b1[i] != '\0'; i++) 327e1051a39Sopenharmony_ci if (b1[i] == b2[i] || b1[i] == ' ' || b2[i] == ' ') { 328e1051a39Sopenharmony_ci *p++ = ' '; 329e1051a39Sopenharmony_ci diff |= b1[i] != b2[i]; 330e1051a39Sopenharmony_ci } else { 331e1051a39Sopenharmony_ci *p++ = '^'; 332e1051a39Sopenharmony_ci real_diff = diff = 1; 333e1051a39Sopenharmony_ci } 334e1051a39Sopenharmony_ci *p++ = '\0'; 335e1051a39Sopenharmony_ci if (!diff) { 336e1051a39Sopenharmony_ci test_printf_stderr(" %s:% 5d\n", n2 > n1 ? b2 : b1, cnt); 337e1051a39Sopenharmony_ci } else { 338e1051a39Sopenharmony_ci if (cnt == 0 && bn1 == NULL) 339e1051a39Sopenharmony_ci test_printf_stderr("-%s\n", b1); 340e1051a39Sopenharmony_ci else if (cnt == 0 || n1 > 0) 341e1051a39Sopenharmony_ci test_printf_stderr("-%s:% 5d\n", b1, cnt); 342e1051a39Sopenharmony_ci if (cnt == 0 && bn2 == NULL) 343e1051a39Sopenharmony_ci test_printf_stderr("+%s\n", b2); 344e1051a39Sopenharmony_ci else if (cnt == 0 || n2 > 0) 345e1051a39Sopenharmony_ci test_printf_stderr("+%s:% 5d\n", b2, cnt); 346e1051a39Sopenharmony_ci if (real_diff && (cnt == 0 || (n1 > 0 && n2 > 0)) 347e1051a39Sopenharmony_ci && bn1 != NULL && bn2 != NULL) 348e1051a39Sopenharmony_ci test_printf_stderr(" %s\n", bdiff); 349e1051a39Sopenharmony_ci } 350e1051a39Sopenharmony_ci if (m1 != NULL) 351e1051a39Sopenharmony_ci m1 += bytes; 352e1051a39Sopenharmony_ci if (m2 != NULL) 353e1051a39Sopenharmony_ci m2 += bytes; 354e1051a39Sopenharmony_ci len -= bytes; 355e1051a39Sopenharmony_ci } 356e1051a39Sopenharmony_cifin: 357e1051a39Sopenharmony_ci test_flush_stderr(); 358e1051a39Sopenharmony_ci if (bufp != buffer) 359e1051a39Sopenharmony_ci OPENSSL_free(bufp); 360e1051a39Sopenharmony_ci} 361e1051a39Sopenharmony_ci 362e1051a39Sopenharmony_ci/* 363e1051a39Sopenharmony_ci * Wrapper routines so that the underlying code can be shared. 364e1051a39Sopenharmony_ci * The first two are calls from inside the test utilities when a conditional 365e1051a39Sopenharmony_ci * fails. The third is the user's call to dump a bignum. 366e1051a39Sopenharmony_ci */ 367e1051a39Sopenharmony_civoid test_fail_bignum_message(const char *prefix, const char *file, 368e1051a39Sopenharmony_ci int line, const char *type, 369e1051a39Sopenharmony_ci const char *left, const char *right, 370e1051a39Sopenharmony_ci const char *op, 371e1051a39Sopenharmony_ci const BIGNUM *bn1, const BIGNUM *bn2) 372e1051a39Sopenharmony_ci{ 373e1051a39Sopenharmony_ci test_fail_bignum_common(prefix, file, line, type, left, right, op, bn1, bn2); 374e1051a39Sopenharmony_ci test_printf_stderr("\n"); 375e1051a39Sopenharmony_ci} 376e1051a39Sopenharmony_ci 377e1051a39Sopenharmony_civoid test_fail_bignum_mono_message(const char *prefix, const char *file, 378e1051a39Sopenharmony_ci int line, const char *type, 379e1051a39Sopenharmony_ci const char *left, const char *right, 380e1051a39Sopenharmony_ci const char *op, const BIGNUM *bn) 381e1051a39Sopenharmony_ci{ 382e1051a39Sopenharmony_ci test_fail_bignum_common(prefix, file, line, type, left, right, op, bn, bn); 383e1051a39Sopenharmony_ci test_printf_stderr("\n"); 384e1051a39Sopenharmony_ci} 385e1051a39Sopenharmony_ci 386e1051a39Sopenharmony_civoid test_output_bignum(const char *name, const BIGNUM *bn) 387e1051a39Sopenharmony_ci{ 388e1051a39Sopenharmony_ci if (bn == NULL || BN_is_zero(bn)) { 389e1051a39Sopenharmony_ci test_printf_stderr("bignum: '%s' = %s\n", name, 390e1051a39Sopenharmony_ci test_bignum_zero_null(bn)); 391e1051a39Sopenharmony_ci } else if (BN_num_bytes(bn) <= BN_OUTPUT_SIZE) { 392e1051a39Sopenharmony_ci unsigned char buf[BN_OUTPUT_SIZE]; 393e1051a39Sopenharmony_ci char out[2 * sizeof(buf) + 1]; 394e1051a39Sopenharmony_ci char *p = out; 395e1051a39Sopenharmony_ci int n = BN_bn2bin(bn, buf); 396e1051a39Sopenharmony_ci 397e1051a39Sopenharmony_ci hex_convert_memory(buf, n, p, BN_OUTPUT_SIZE); 398e1051a39Sopenharmony_ci while (*p == '0' && *++p != '\0') 399e1051a39Sopenharmony_ci ; 400e1051a39Sopenharmony_ci test_printf_stderr("bignum: '%s' = %s0x%s\n", name, 401e1051a39Sopenharmony_ci BN_is_negative(bn) ? "-" : "", p); 402e1051a39Sopenharmony_ci } else { 403e1051a39Sopenharmony_ci test_fail_bignum_common("bignum", NULL, 0, NULL, NULL, NULL, name, 404e1051a39Sopenharmony_ci bn, bn); 405e1051a39Sopenharmony_ci } 406e1051a39Sopenharmony_ci} 407e1051a39Sopenharmony_ci 408e1051a39Sopenharmony_ci/* Memory output routines */ 409e1051a39Sopenharmony_ci 410e1051a39Sopenharmony_ci/* 411e1051a39Sopenharmony_ci * Handle zero length blocks of memory or NULL pointers to memory 412e1051a39Sopenharmony_ci */ 413e1051a39Sopenharmony_cistatic void test_memory_null_empty(const unsigned char *m, char c) 414e1051a39Sopenharmony_ci{ 415e1051a39Sopenharmony_ci if (m == NULL) 416e1051a39Sopenharmony_ci test_printf_stderr("%4s %c%s\n", "", c, "NULL"); 417e1051a39Sopenharmony_ci else 418e1051a39Sopenharmony_ci test_printf_stderr("%04x %c%s\n", 0u, c, "empty"); 419e1051a39Sopenharmony_ci} 420e1051a39Sopenharmony_ci 421e1051a39Sopenharmony_ci/* 422e1051a39Sopenharmony_ci * Common code to display one or two blocks of memory. 423e1051a39Sopenharmony_ci */ 424e1051a39Sopenharmony_cistatic void test_fail_memory_common(const char *prefix, const char *file, 425e1051a39Sopenharmony_ci int line, const char *type, 426e1051a39Sopenharmony_ci const char *left, const char *right, 427e1051a39Sopenharmony_ci const char *op, 428e1051a39Sopenharmony_ci const unsigned char *m1, size_t l1, 429e1051a39Sopenharmony_ci const unsigned char *m2, size_t l2) 430e1051a39Sopenharmony_ci{ 431e1051a39Sopenharmony_ci const size_t bytes = (MAX_STRING_WIDTH - 9) / 17 * 8; 432e1051a39Sopenharmony_ci char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; 433e1051a39Sopenharmony_ci char *p, bdiff[MAX_STRING_WIDTH + 1]; 434e1051a39Sopenharmony_ci size_t n1, n2, i; 435e1051a39Sopenharmony_ci unsigned int cnt = 0, diff; 436e1051a39Sopenharmony_ci 437e1051a39Sopenharmony_ci test_fail_message_prefix(prefix, file, line, type, left, right, op); 438e1051a39Sopenharmony_ci if (m1 == NULL) 439e1051a39Sopenharmony_ci l1 = 0; 440e1051a39Sopenharmony_ci if (m2 == NULL) 441e1051a39Sopenharmony_ci l2 = 0; 442e1051a39Sopenharmony_ci if (l1 == 0 && l2 == 0) { 443e1051a39Sopenharmony_ci if ((m1 == NULL) == (m2 == NULL)) { 444e1051a39Sopenharmony_ci test_memory_null_empty(m1, ' '); 445e1051a39Sopenharmony_ci } else { 446e1051a39Sopenharmony_ci test_diff_header(left, right); 447e1051a39Sopenharmony_ci test_memory_null_empty(m1, '-'); 448e1051a39Sopenharmony_ci test_memory_null_empty(m2, '+'); 449e1051a39Sopenharmony_ci } 450e1051a39Sopenharmony_ci goto fin; 451e1051a39Sopenharmony_ci } 452e1051a39Sopenharmony_ci 453e1051a39Sopenharmony_ci if (l1 != l2 || (m1 != m2 && memcmp(m1, m2, l1) != 0)) 454e1051a39Sopenharmony_ci test_diff_header(left, right); 455e1051a39Sopenharmony_ci 456e1051a39Sopenharmony_ci while (l1 > 0 || l2 > 0) { 457e1051a39Sopenharmony_ci n1 = n2 = 0; 458e1051a39Sopenharmony_ci if (l1 > 0) { 459e1051a39Sopenharmony_ci n1 = l1 > bytes ? bytes : l1; 460e1051a39Sopenharmony_ci hex_convert_memory(m1, n1, b1, 8); 461e1051a39Sopenharmony_ci } 462e1051a39Sopenharmony_ci if (l2 > 0) { 463e1051a39Sopenharmony_ci n2 = l2 > bytes ? bytes : l2; 464e1051a39Sopenharmony_ci hex_convert_memory(m2, n2, b2, 8); 465e1051a39Sopenharmony_ci } 466e1051a39Sopenharmony_ci 467e1051a39Sopenharmony_ci diff = 0; 468e1051a39Sopenharmony_ci i = 0; 469e1051a39Sopenharmony_ci p = bdiff; 470e1051a39Sopenharmony_ci if (n1 > 0 && n2 > 0) { 471e1051a39Sopenharmony_ci const size_t j = n1 < n2 ? n1 : n2; 472e1051a39Sopenharmony_ci 473e1051a39Sopenharmony_ci for (; i < j; i++) { 474e1051a39Sopenharmony_ci if (m1[i] == m2[i]) { 475e1051a39Sopenharmony_ci *p++ = ' '; 476e1051a39Sopenharmony_ci *p++ = ' '; 477e1051a39Sopenharmony_ci } else { 478e1051a39Sopenharmony_ci *p++ = '^'; 479e1051a39Sopenharmony_ci *p++ = '^'; 480e1051a39Sopenharmony_ci diff = 1; 481e1051a39Sopenharmony_ci } 482e1051a39Sopenharmony_ci if (i % 8 == 7 && i != j - 1) 483e1051a39Sopenharmony_ci *p++ = ' '; 484e1051a39Sopenharmony_ci } 485e1051a39Sopenharmony_ci *p++ = '\0'; 486e1051a39Sopenharmony_ci } 487e1051a39Sopenharmony_ci 488e1051a39Sopenharmony_ci if (n1 == n2 && !diff) { 489e1051a39Sopenharmony_ci test_printf_stderr("%04x: %s\n", cnt, b1); 490e1051a39Sopenharmony_ci } else { 491e1051a39Sopenharmony_ci if (cnt == 0 && (m1 == NULL || l1 == 0)) 492e1051a39Sopenharmony_ci test_memory_null_empty(m1, '-'); 493e1051a39Sopenharmony_ci else if (n1 > 0) 494e1051a39Sopenharmony_ci test_printf_stderr("%04x:-%s\n", cnt, b1); 495e1051a39Sopenharmony_ci if (cnt == 0 && (m2 == NULL || l2 == 0)) 496e1051a39Sopenharmony_ci test_memory_null_empty(m2, '+'); 497e1051a39Sopenharmony_ci else if (n2 > 0) 498e1051a39Sopenharmony_ci test_printf_stderr("%04x:+%s\n", cnt, b2); 499e1051a39Sopenharmony_ci if (diff && i > 0) 500e1051a39Sopenharmony_ci test_printf_stderr("%4s %s\n", "", bdiff); 501e1051a39Sopenharmony_ci } 502e1051a39Sopenharmony_ci if (m1 != NULL) 503e1051a39Sopenharmony_ci m1 += n1; 504e1051a39Sopenharmony_ci if (m2 != NULL) 505e1051a39Sopenharmony_ci m2 += n2; 506e1051a39Sopenharmony_ci l1 -= n1; 507e1051a39Sopenharmony_ci l2 -= n2; 508e1051a39Sopenharmony_ci cnt += bytes; 509e1051a39Sopenharmony_ci } 510e1051a39Sopenharmony_cifin: 511e1051a39Sopenharmony_ci test_flush_stderr(); 512e1051a39Sopenharmony_ci} 513e1051a39Sopenharmony_ci 514e1051a39Sopenharmony_ci/* 515e1051a39Sopenharmony_ci * Wrapper routines so that the underlying code can be shared. 516e1051a39Sopenharmony_ci * The first is the call from inside the test utilities when a conditional 517e1051a39Sopenharmony_ci * fails. The second is the user's call to dump memory. 518e1051a39Sopenharmony_ci */ 519e1051a39Sopenharmony_civoid test_fail_memory_message(const char *prefix, const char *file, 520e1051a39Sopenharmony_ci int line, const char *type, 521e1051a39Sopenharmony_ci const char *left, const char *right, 522e1051a39Sopenharmony_ci const char *op, 523e1051a39Sopenharmony_ci const unsigned char *m1, size_t l1, 524e1051a39Sopenharmony_ci const unsigned char *m2, size_t l2) 525e1051a39Sopenharmony_ci{ 526e1051a39Sopenharmony_ci test_fail_memory_common(prefix, file, line, type, left, right, op, 527e1051a39Sopenharmony_ci m1, l1, m2, l2); 528e1051a39Sopenharmony_ci test_printf_stderr("\n"); 529e1051a39Sopenharmony_ci} 530e1051a39Sopenharmony_ci 531e1051a39Sopenharmony_civoid test_output_memory(const char *name, const unsigned char *m, size_t l) 532e1051a39Sopenharmony_ci{ 533e1051a39Sopenharmony_ci test_fail_memory_common("memory", NULL, 0, NULL, NULL, NULL, name, 534e1051a39Sopenharmony_ci m, l, m, l); 535e1051a39Sopenharmony_ci} 536