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 59b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <assert.h> 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <ctype.h> 61b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <limits.h> 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdio.h> 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bio.h> 654139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#include <openssl/bytestring.h> 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h> 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 698ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan#include "../fipsmodule/bn/internal.h" 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 724139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) { 734139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley uint8_t *ptr; 744139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in); 754139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley} 764139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char hextable[] = "0123456789abcdef"; 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langleychar *BN_bn2hex(const BIGNUM *bn) { 80c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ + 81c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin bn->top * BN_BYTES * 2 + 1 /* trailing NUL */); 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (buf == NULL) { 83b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 87c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin char *p = buf; 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bn->neg) { 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = '-'; 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(bn)) { 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = '0'; 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 96c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin int z = 0; 97c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin for (int i = bn->top - 1; i >= 0; i--) { 98c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin for (int j = BN_BITS2 - 8; j >= 0; j -= 8) { 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* strip leading zeros */ 100c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin int v = ((int)(bn->d[i] >> (long)j)) & 0xff; 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (z || v != 0) { 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = hextable[v >> 4]; 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *(p++) = hextable[v & 0x0f]; 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley z = 1; 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *p = '\0'; 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return buf; 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 113b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root/* decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|. */ 114b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic int decode_hex(BIGNUM *bn, const char *in, int in_len) { 115b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (in_len > INT_MAX/4) { 116b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG); 117b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 0; 118b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 119b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root /* |in_len| is the number of hex digits. */ 1209254e681d446a8105bd66f08bae1252d4d89a139Robert Sloan if (!bn_expand(bn, in_len * 4)) { 121b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 0; 122b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 124b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root int i = 0; 125b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root while (in_len > 0) { 126b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root /* Decode one |BN_ULONG| at a time. */ 127b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root int todo = BN_BYTES * 2; 128b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (todo > in_len) { 129b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root todo = in_len; 130b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 132b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root BN_ULONG word = 0; 133b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root int j; 134b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root for (j = todo; j > 0; j--) { 135b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root char c = in[in_len - j]; 136b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 137b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root BN_ULONG hex; 138b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (c >= '0' && c <= '9') { 139b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root hex = c - '0'; 140b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } else if (c >= 'a' && c <= 'f') { 141b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root hex = c - 'a' + 10; 142b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } else if (c >= 'A' && c <= 'F') { 143b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root hex = c - 'A' + 10; 144b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } else { 145b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root hex = 0; 146b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root /* This shouldn't happen. The caller checks |isxdigit|. */ 147b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root assert(0); 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 149b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root word = (word << 4) | hex; 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 152b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root bn->d[i++] = word; 153b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root in_len -= todo; 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 155b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root assert(i <= bn->dmax); 156b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root bn->top = i; 157b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 1; 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 160d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley/* decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|. */ 161b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic int decode_dec(BIGNUM *bn, const char *in, int in_len) { 162d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley int i, j; 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_ULONG l = 0; 164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 165b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root /* Decode |BN_DEC_NUM| digits at a time. */ 166d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley j = BN_DEC_NUM - (in_len % BN_DEC_NUM); 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (j == BN_DEC_NUM) { 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley j = 0; 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = 0; 171d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley for (i = 0; i < in_len; i++) { 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l *= 10; 173d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley l += in[i] - '0'; 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (++j == BN_DEC_NUM) { 175b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!BN_mul_word(bn, BN_DEC_CONV) || 176b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root !BN_add_word(bn, l)) { 177b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 0; 178b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley l = 0; 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley j = 0; 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 183b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 1; 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 186b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Roottypedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len); 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langleytypedef int (*char_test_func) (int c); 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 189d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) { 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *ret = NULL; 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int neg = 0, i; 192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int num; 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in == NULL || *in == 0) { 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*in == '-') { 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley neg = 1; 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in++; 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 203b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {} 204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley num = i + neg; 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (outp == NULL) { 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return num; 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* in is the start of the hex digits, and it is 'i' long */ 211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*outp == NULL) { 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = BN_new(); 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret == NULL) { 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = *outp; 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_zero(ret); 219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 221b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!decode(ret, in, i)) { 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bn_correct_top(ret); 226d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley if (!BN_is_zero(ret)) { 227d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley ret->neg = neg; 228d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley } 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *outp = ret; 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return num; 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*outp == NULL) { 235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_free(ret); 236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 241d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_hex2bn(BIGNUM **outp, const char *in) { 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bn_x2bn(outp, in, decode_hex, isxdigit); 243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langleychar *BN_bn2dec(const BIGNUM *a) { 246f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin /* It is easier to print strings little-endian, so we assemble it in reverse 247f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin * and fix at the end. */ 248f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin BIGNUM *copy = NULL; 249f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin CBB cbb; 250f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (!CBB_init(&cbb, 16) || 251f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin !CBB_add_u8(&cbb, 0 /* trailing NUL */)) { 252f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin goto cbb_err; 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 255f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (BN_is_zero(a)) { 256f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (!CBB_add_u8(&cbb, '0')) { 257f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin goto cbb_err; 258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 259f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } else { 260f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin copy = BN_dup(a); 261f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (copy == NULL) { 262f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin goto err; 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 264f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 265f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin while (!BN_is_zero(copy)) { 266f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin BN_ULONG word = BN_div_word(copy, BN_DEC_CONV); 267f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (word == (BN_ULONG)-1) { 268f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin goto err; 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 270f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 271f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin const int add_leading_zeros = !BN_is_zero(copy); 272f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) { 273f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (!CBB_add_u8(&cbb, '0' + word % 10)) { 274f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin goto cbb_err; 275f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 276f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin word /= 10; 277f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 278f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin assert(word == 0); 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 282f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (BN_is_negative(a) && 283f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin !CBB_add_u8(&cbb, '-')) { 284f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin goto cbb_err; 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 287f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin uint8_t *data; 288f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin size_t len; 289f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin if (!CBB_finish(&cbb, &data, &len)) { 290f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin goto cbb_err; 291f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 292f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 293f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin /* Reverse the buffer. */ 294f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin for (size_t i = 0; i < len/2; i++) { 295f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin uint8_t tmp = data[i]; 296f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin data[i] = data[len - 1 - i]; 297f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin data[len - 1 - i] = tmp; 298f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin } 299f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 300f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin BN_free(copy); 301f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return (char *)data; 302f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin 303f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamincbb_err: 304f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); 305f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjaminerr: 306f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin BN_free(copy); 307f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin CBB_cleanup(&cbb); 308f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin return NULL; 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 311d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_dec2bn(BIGNUM **outp, const char *in) { 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bn_x2bn(outp, in, decode_dec, isdigit); 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_asc2bn(BIGNUM **outp, const char *in) { 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const char *const orig_in = in; 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (*in == '-') { 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley in++; 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) { 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_hex2bn(outp, in+2)) { 323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_dec2bn(outp, in)) { 327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 331d82ab38ca2b63638a2cb0b5d8a2c76d90c86dd31Adam Langley if (*orig_in == '-' && !BN_is_zero(*outp)) { 332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (*outp)->neg = 1; 333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 338d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_print(BIO *bp, const BIGNUM *a) { 339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int i, j, v, z = 0; 340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (a->neg && BIO_write(bp, "-", 1) != 1) { 343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto end; 344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) { 347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto end; 348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (i = a->top - 1; i >= 0; i--) { 351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (j = BN_BITS2 - 4; j >= 0; j -= 4) { 352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* strip leading zeros */ 353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley v = ((int)(a->d[i] >> (long)j)) & 0x0f; 354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (z || v != 0) { 355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BIO_write(bp, &hextable[v], 1) != 1) { 356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto end; 357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley z = 1; 359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyend: 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BN_print_fp(FILE *fp, const BIGNUM *a) { 369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO *b; 370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret; 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley b = BIO_new(BIO_s_file()); 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (b == NULL) { 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_set_fp(b, fp, BIO_NOCLOSE); 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = BN_print(b, a); 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_free(b); 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 38369939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan 384b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootsize_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) { 385b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root const size_t bits = BN_num_bits(in); 386b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root const size_t bytes = (bits + 7) / 8; 387b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root /* If the number of bits is a multiple of 8, i.e. if the MSB is set, 388b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * prefix with a zero byte. */ 389b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root int extend = 0; 390b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (bytes != 0 && (bits & 0x07) == 0) { 391b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root extend = 1; 392b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 393b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 394b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root const size_t len = bytes + extend; 395b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (len < bytes || 396b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 4 + len < len || 397b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root (len & 0xffffffff) != len) { 398b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root /* If we cannot represent the number then we emit zero as the interface 399b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * doesn't allow an error to be signalled. */ 400b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (out) { 40169939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan OPENSSL_memset(out, 0, 4); 402b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 403b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 4; 404b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 405b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 406b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (out == NULL) { 407b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return 4 + len; 408b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 409b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 410b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root out[0] = len >> 24; 411b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root out[1] = len >> 16; 412b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root out[2] = len >> 8; 413b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root out[3] = len; 414b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (extend) { 415b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root out[4] = 0; 416b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 417b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root BN_bn2bin(in, out + 4 + extend); 418b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (in->neg && len > 0) { 419b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root out[4] |= 0x80; 420b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 421b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return len + 4; 422b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root} 423b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 424b8494591d1b1a143f3b192d845c238bbf3bc629dKenny RootBIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) { 425b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (len < 4) { 426b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); 427b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return NULL; 428b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 429b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root const size_t in_len = ((size_t)in[0] << 24) | 430b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root ((size_t)in[1] << 16) | 431b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root ((size_t)in[2] << 8) | 432b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root ((size_t)in[3]); 433b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (in_len != len - 4) { 434b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING); 435b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return NULL; 436b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 437b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 4384969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin int out_is_alloced = 0; 439b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (out == NULL) { 440b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root out = BN_new(); 4414969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (out == NULL) { 4424969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); 4434969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return NULL; 4444969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin } 4454969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin out_is_alloced = 1; 446b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 447b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 448b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (in_len == 0) { 449b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root BN_zero(out); 450b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return out; 451b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 452b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 453b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root in += 4; 454b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (BN_bin2bn(in, in_len, out) == NULL) { 4554969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (out_is_alloced) { 4564969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin BN_free(out); 4574969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin } 458b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return NULL; 459b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 460b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root out->neg = ((*in) & 0x80) != 0; 461b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (out->neg) { 462b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root BN_clear_bit(out, BN_num_bits(out) - 1); 463b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 464b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return out; 465b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root} 466