1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * All rights reserved. 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This package is an SSL implementation written 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * by Eric Young (eay@cryptsoft.com). 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The implementation was written so as to conform with Netscapes SSL. 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This library is free for commercial and non-commercial use as long as 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the following conditions are aheared to. The following conditions 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * apply to all code found in this distribution, be it the RC4, RSA, 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * included with this distribution is covered by the same copyright terms 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com). 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the code are not to be removed. 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If this package is used in a product, Eric Young should be given attribution 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * as the author of the parts of the library used. 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This can be in the form of a textual message at program startup or 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in documentation (online or textual) provided with the package. 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met: 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the copyright 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer. 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer in the 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * documentation and/or other materials provided with the distribution. 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this software 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * must display the following acknowledgement: 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes cryptographic software written by 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Eric Young (eay@cryptsoft.com)" 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The word 'cryptographic' can be left out if the rouines from the library 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * being used are not cryptographic related :-). 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the apps directory (application code) you must include an acknowledgement: 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUCH DAMAGE. 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The licence and distribution terms for any publically available version or 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * derivative of this code cannot be changed. i.e. this code cannot simply be 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copied and put under another distribution licence 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * [including the GNU Public Licence.] */ 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bn.h> 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <ctype.h> 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdio.h> 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bio.h> 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h> 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h" 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 69d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) { 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unsigned num_words, m; 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG word = 0; 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *bn = NULL; 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret == NULL) { 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = bn = BN_new(); 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret == NULL) { 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (len == 0) { 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret->top = 0; 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley num_words = ((len - 1) / BN_BYTES) + 1; 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley m = (len - 1) % BN_BYTES; 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bn_wexpand(ret, num_words) == NULL) { 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bn) { 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_free(bn); 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret->top = num_words; 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret->neg = 0; 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (len--) { 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley word = (word << 8) | *(in++); 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (m-- == 0) { 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret->d[--num_words] = word; 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley word = 0; 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley m = BN_BYTES - 1; 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* need to call this due to clear byte at top if avoiding having the top bit 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * set (-ve number) */ 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bn_correct_top(ret); 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langleysize_t BN_bn2bin(const BIGNUM *in, uint8_t *out) { 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t n, i; 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG l; 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley n = i = BN_num_bytes(in); 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (i--) { 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = in->d[i / BN_BYTES]; 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(out++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return n; 124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * behavior is undefined if |v| takes any other value. */ 128d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) { 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG mask = v; 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley mask--; 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return (~mask & x) | (mask & y); 133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y| 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * must not have their MSBs set. */ 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int constant_time_le_size_t(size_t x, size_t y) { 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1; 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* read_word_padded returns the |i|'th word of |in|, if it is not out of 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * bounds. Otherwise, it returns 0. It does so without branches on the size of 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * |in|, however it necessarily does not have the same memory access pattern. If 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the access would be out of bounds, it reads the last word of |in|. |in| must 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * not be zero. */ 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic BN_ULONG read_word_padded(const BIGNUM *in, size_t i) { 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Read |in->d[i]| if valid. Otherwise, read the last word. */ 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG l = in->d[constant_time_select_ulong( 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)]; 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Clamp to zero if above |d->top|. */ 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l); 153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) { 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t i; 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG l; 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Special case for |in| = 0. Just branch as the probability is negligible. */ 160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(in)) { 161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley memset(out, 0, len); 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Check if the integer is too big. This case can exit early in non-constant 166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * time. */ 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) { 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((len % BN_BYTES) != 0) { 171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = read_word_padded(in, len / BN_BYTES); 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (l >> (8 * (len % BN_BYTES)) != 0) { 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Write the bytes out one by one. Serialization is done without branching on 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the bits of |in| or on |in->top|, but if the routine would otherwise read 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * out of bounds, the memory access pattern can't be fixed. However, for an 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * RSA key of size a multiple of the word size, the probability of BN_BYTES 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * leading zero octets is low. 182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. */ 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i = len; 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (i--) { 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = read_word_padded(in, i / BN_BYTES); 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff; 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 192d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char hextable[] = "0123456789abcdef"; 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langleychar *BN_bn2hex(const BIGNUM *bn) { 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int i, j, v, z = 0; 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley char *buf; 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley char *p; 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley buf = (char *)OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2); 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (buf == NULL) { 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(BN, BN_bn2hex, ERR_R_MALLOC_FAILURE); 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley p = buf; 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bn->neg) { 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = '-'; 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(bn)) { 211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = '0'; 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (i = bn->top - 1; i >= 0; i--) { 215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (j = BN_BITS2 - 8; j >= 0; j -= 8) { 216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* strip leading zeros */ 217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley v = ((int)(bn->d[i] >> (long)j)) & 0xff; 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (z || v != 0) { 219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = hextable[v >> 4]; 220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = hextable[v & 0x0f]; 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley z = 1; 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *p = '\0'; 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return buf; 228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* decode_hex decodes |i| bytes of hex data from |in| and updates |bn|. */ 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void decode_hex(BIGNUM *bn, const char *in, int i) { 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int h, m, j, k, c; 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG l=0; 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley j = i; /* least significant 'hex' */ 236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley h = 0; 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (j > 0) { 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j; 239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = 0; 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (;;) { 241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley c = in[j - m]; 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((c >= '0') && (c <= '9')) { 243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley k = c - '0'; 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else if ((c >= 'a') && (c <= 'f')) { 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley k = c - 'a' + 10; 246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else if ((c >= 'A') && (c <= 'F')) { 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley k = c - 'A' + 10; 248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley k = 0; /* paranoia */ 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = (l << 4) | k; 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (--m <= 0) { 255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bn->d[h++] = l; 256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley break; 257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley j -= (BN_BYTES * 2); 261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bn->top = h; 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 266d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley/* decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|. */ 267d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langleystatic void decode_dec(BIGNUM *bn, const char *in, int in_len) { 268d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley int i, j; 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG l = 0; 270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 271d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley j = BN_DEC_NUM - (in_len % BN_DEC_NUM); 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (j == BN_DEC_NUM) { 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley j = 0; 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = 0; 276d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley for (i = 0; i < in_len; i++) { 277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l *= 10; 278d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley l += in[i] - '0'; 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (++j == BN_DEC_NUM) { 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_mul_word(bn, BN_DEC_CONV); 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_add_word(bn, l); 282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = 0; 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley j = 0; 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langleytypedef void (*decode_func) (BIGNUM *bn, const char *in, int i); 289d9e397b599b13d642138480a28c14db7a136bf0Adam Langleytypedef int (*char_test_func) (int c); 290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) { 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *ret = NULL; 293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int neg = 0, i; 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int num; 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in == NULL || *in == 0) { 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*in == '-') { 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley neg = 1; 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in++; 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (i = 0; want_char((unsigned char)in[i]); i++) {} 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley num = i + neg; 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (outp == NULL) { 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return num; 310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* in is the start of the hex digits, and it is 'i' long */ 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*outp == NULL) { 314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = BN_new(); 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret == NULL) { 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = *outp; 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_zero(ret); 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* i is the number of hex digests; */ 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bn_expand(ret, i * 4) == NULL) { 325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley decode(ret, in, i); 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bn_correct_top(ret); 331d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley if (!BN_is_zero(ret)) { 332d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley ret->neg = neg; 333d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley } 334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *outp = ret; 336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return num; 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 338d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*outp == NULL) { 340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_free(ret); 341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 346d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_hex2bn(BIGNUM **outp, const char *in) { 347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bn_x2bn(outp, in, decode_hex, isxdigit); 348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 350d9e397b599b13d642138480a28c14db7a136bf0Adam Langleychar *BN_bn2dec(const BIGNUM *a) { 351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int i = 0, num, ok = 0; 352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley char *buf = NULL; 353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley char *p; 354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *t = NULL; 355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG *bn_data = NULL, *lp; 356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* get an upper bound for the length of the decimal integer 358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * num <= (BN_num_bits(a) + 1) * log(2) 359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1 (rounding error) 360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1 361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i = BN_num_bits(a) * 3; 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley num = i / 10 + i / 1000 + 1 + 1; 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bn_data = 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG)); 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley buf = (char *)OPENSSL_malloc(num + 3); 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((buf == NULL) || (bn_data == NULL)) { 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(BN, BN_bn2dec, ERR_R_MALLOC_FAILURE); 369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley t = BN_dup(a); 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (t == NULL) { 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define BUF_REMAIN (num + 3 - (size_t)(p - buf)) 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley p = buf; 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley lp = bn_data; 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(t)) { 380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = '0'; 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = '\0'; 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_negative(t)) { 384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *p++ = '-'; 385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (!BN_is_zero(t)) { 388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *lp = BN_div_word(t, BN_DEC_CONV); 389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley lp++; 390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley lp--; 392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* We now have a series of blocks, BN_DEC_NUM chars 393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in length, where the last one needs truncation. 394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The blocks need to be reversed in order. */ 395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT1, *lp); 396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (*p) { 397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley p++; 398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (lp != bn_data) { 400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley lp--; 401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT2, *lp); 402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (*p) { 403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley p++; 404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ok = 1; 408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 409d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 410e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley OPENSSL_free(bn_data); 411e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_free(t); 412e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!ok) { 413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(buf); 414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley buf = NULL; 415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return buf; 418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 420d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_dec2bn(BIGNUM **outp, const char *in) { 421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bn_x2bn(outp, in, decode_dec, isdigit); 422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 424d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_asc2bn(BIGNUM **outp, const char *in) { 425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const char *const orig_in = in; 426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*in == '-') { 427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in++; 428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) { 431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_hex2bn(outp, in+2)) { 432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_dec2bn(outp, in)) { 436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 440d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley if (*orig_in == '-' && !BN_is_zero(*outp)) { 441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*outp)->neg = 1; 442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 447d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_print(BIO *bp, const BIGNUM *a) { 448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int i, j, v, z = 0; 449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 450d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 451d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (a->neg && BIO_write(bp, "-", 1) != 1) { 452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto end; 453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) { 456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto end; 457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (i = a->top - 1; i >= 0; i--) { 460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (j = BN_BITS2 - 4; j >= 0; j -= 4) { 461d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* strip leading zeros */ 462d9e397b599b13d642138480a28c14db7a136bf0Adam Langley v = ((int)(a->d[i] >> (long)j)) & 0x0f; 463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (z || v != 0) { 464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BIO_write(bp, &hextable[v], 1) != 1) { 465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto end; 466d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley z = 1; 468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 470d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 473d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyend: 474d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 475d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 476d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 477d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_print_fp(FILE *fp, const BIGNUM *a) { 478d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO *b; 479d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret; 480d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 481d9e397b599b13d642138480a28c14db7a136bf0Adam Langley b = BIO_new(BIO_s_file()); 482d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (b == NULL) { 483d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 484d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 485d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_set_fp(b, fp, BIO_NOCLOSE); 486d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = BN_print(b, a); 487d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_free(b); 488d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 489d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 490d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 491d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 492d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBN_ULONG BN_get_word(const BIGNUM *bn) { 493d9e397b599b13d642138480a28c14db7a136bf0Adam Langley switch (bn->top) { 494d9e397b599b13d642138480a28c14db7a136bf0Adam Langley case 0: 495d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 496d9e397b599b13d642138480a28c14db7a136bf0Adam Langley case 1: 497d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bn->d[0]; 498d9e397b599b13d642138480a28c14db7a136bf0Adam Langley default: 499d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BN_MASK2; 500d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 501d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 502