172c33676SMaxim Ag /* $OpenBSD: a_int.c,v 1.33 2019/03/26 09:15:07 jsing Exp $ */ 2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3f5b1c8a1SJohn Marino * All rights reserved. 4f5b1c8a1SJohn Marino * 5f5b1c8a1SJohn Marino * This package is an SSL implementation written 6f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com). 7f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL. 8f5b1c8a1SJohn Marino * 9f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as 10f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions 11f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA, 12f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms 14f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15f5b1c8a1SJohn Marino * 16f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in 17f5b1c8a1SJohn Marino * the code are not to be removed. 18f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution 19f5b1c8a1SJohn Marino * as the author of the parts of the library used. 20f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or 21f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package. 22f5b1c8a1SJohn Marino * 23f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 24f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 25f5b1c8a1SJohn Marino * are met: 26f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright 27f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 28f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 29f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the 30f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution. 31f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software 32f5b1c8a1SJohn Marino * must display the following acknowledgement: 33f5b1c8a1SJohn Marino * "This product includes cryptographic software written by 34f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)" 35f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library 36f5b1c8a1SJohn Marino * being used are not cryptographic related :-). 37f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from 38f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement: 39f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40f5b1c8a1SJohn Marino * 41f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51f5b1c8a1SJohn Marino * SUCH DAMAGE. 52f5b1c8a1SJohn Marino * 53f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or 54f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be 55f5b1c8a1SJohn Marino * copied and put under another distribution licence 56f5b1c8a1SJohn Marino * [including the GNU Public Licence.] 57f5b1c8a1SJohn Marino */ 58f5b1c8a1SJohn Marino 5972c33676SMaxim Ag #include <limits.h> 60f5b1c8a1SJohn Marino #include <stdio.h> 61f5b1c8a1SJohn Marino #include <string.h> 62f5b1c8a1SJohn Marino 63f5b1c8a1SJohn Marino #include <openssl/asn1.h> 64f5b1c8a1SJohn Marino #include <openssl/bn.h> 65f5b1c8a1SJohn Marino #include <openssl/err.h> 66f5b1c8a1SJohn Marino 6772c33676SMaxim Ag static int 6872c33676SMaxim Ag ASN1_INTEGER_valid(const ASN1_INTEGER *a) 6972c33676SMaxim Ag { 7072c33676SMaxim Ag return (a != NULL && a->length >= 0); 7172c33676SMaxim Ag } 7272c33676SMaxim Ag 73f5b1c8a1SJohn Marino ASN1_INTEGER * 74f5b1c8a1SJohn Marino ASN1_INTEGER_dup(const ASN1_INTEGER *x) 75f5b1c8a1SJohn Marino { 7672c33676SMaxim Ag if (!ASN1_INTEGER_valid(x)) 7772c33676SMaxim Ag return NULL; 7872c33676SMaxim Ag 79f5b1c8a1SJohn Marino return ASN1_STRING_dup(x); 80f5b1c8a1SJohn Marino } 81f5b1c8a1SJohn Marino 82f5b1c8a1SJohn Marino int 83f5b1c8a1SJohn Marino ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) 84f5b1c8a1SJohn Marino { 85f5b1c8a1SJohn Marino int neg, ret; 86f5b1c8a1SJohn Marino 87f5b1c8a1SJohn Marino /* Compare signs */ 88f5b1c8a1SJohn Marino neg = x->type & V_ASN1_NEG; 89f5b1c8a1SJohn Marino if (neg != (y->type & V_ASN1_NEG)) { 90f5b1c8a1SJohn Marino if (neg) 91f5b1c8a1SJohn Marino return -1; 92f5b1c8a1SJohn Marino else 93f5b1c8a1SJohn Marino return 1; 94f5b1c8a1SJohn Marino } 95f5b1c8a1SJohn Marino 96f5b1c8a1SJohn Marino ret = ASN1_STRING_cmp(x, y); 97f5b1c8a1SJohn Marino 98f5b1c8a1SJohn Marino if (neg) 99f5b1c8a1SJohn Marino return -ret; 100f5b1c8a1SJohn Marino else 101f5b1c8a1SJohn Marino return ret; 102f5b1c8a1SJohn Marino } 103f5b1c8a1SJohn Marino 104f5b1c8a1SJohn Marino 105f5b1c8a1SJohn Marino /* 106f5b1c8a1SJohn Marino * This converts an ASN1 INTEGER into its content encoding. 107f5b1c8a1SJohn Marino * The internal representation is an ASN1_STRING whose data is a big endian 108f5b1c8a1SJohn Marino * representation of the value, ignoring the sign. The sign is determined by 109f5b1c8a1SJohn Marino * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative. 110f5b1c8a1SJohn Marino * 111f5b1c8a1SJohn Marino * Positive integers are no problem: they are almost the same as the DER 112f5b1c8a1SJohn Marino * encoding, except if the first byte is >= 0x80 we need to add a zero pad. 113f5b1c8a1SJohn Marino * 114f5b1c8a1SJohn Marino * Negative integers are a bit trickier... 115f5b1c8a1SJohn Marino * The DER representation of negative integers is in 2s complement form. 116f5b1c8a1SJohn Marino * The internal form is converted by complementing each octet and finally 117f5b1c8a1SJohn Marino * adding one to the result. This can be done less messily with a little trick. 118f5b1c8a1SJohn Marino * If the internal form has trailing zeroes then they will become FF by the 119f5b1c8a1SJohn Marino * complement and 0 by the add one (due to carry) so just copy as many trailing 120f5b1c8a1SJohn Marino * zeros to the destination as there are in the source. The carry will add one 121f5b1c8a1SJohn Marino * to the last none zero octet: so complement this octet and add one and finally 122f5b1c8a1SJohn Marino * complement any left over until you get to the start of the string. 123f5b1c8a1SJohn Marino * 124f5b1c8a1SJohn Marino * Padding is a little trickier too. If the first bytes is > 0x80 then we pad 125f5b1c8a1SJohn Marino * with 0xff. However if the first byte is 0x80 and one of the following bytes 126f5b1c8a1SJohn Marino * is non-zero we pad with 0xff. The reason for this distinction is that 0x80 127f5b1c8a1SJohn Marino * followed by optional zeros isn't padded. 128f5b1c8a1SJohn Marino */ 129f5b1c8a1SJohn Marino 130f5b1c8a1SJohn Marino int 131f5b1c8a1SJohn Marino i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) 132f5b1c8a1SJohn Marino { 133f5b1c8a1SJohn Marino int pad = 0, ret, i, neg; 134f5b1c8a1SJohn Marino unsigned char *p, *n, pb = 0; 135f5b1c8a1SJohn Marino 13672c33676SMaxim Ag if (!ASN1_INTEGER_valid(a)) 13772c33676SMaxim Ag return 0; 13872c33676SMaxim Ag 139f5b1c8a1SJohn Marino neg = a->type & V_ASN1_NEG; 140f5b1c8a1SJohn Marino if (a->length == 0) 141f5b1c8a1SJohn Marino ret = 1; 142f5b1c8a1SJohn Marino else { 143f5b1c8a1SJohn Marino ret = a->length; 144f5b1c8a1SJohn Marino i = a->data[0]; 145f5b1c8a1SJohn Marino if (!neg && (i > 127)) { 146f5b1c8a1SJohn Marino pad = 1; 147f5b1c8a1SJohn Marino pb = 0; 148f5b1c8a1SJohn Marino } else if (neg) { 149f5b1c8a1SJohn Marino if (i > 128) { 150f5b1c8a1SJohn Marino pad = 1; 151f5b1c8a1SJohn Marino pb = 0xFF; 152f5b1c8a1SJohn Marino } else if (i == 128) { 153f5b1c8a1SJohn Marino /* 154f5b1c8a1SJohn Marino * Special case: if any other bytes non zero we pad: 155f5b1c8a1SJohn Marino * otherwise we don't. 156f5b1c8a1SJohn Marino */ 157f5b1c8a1SJohn Marino for (i = 1; i < a->length; i++) if (a->data[i]) { 158f5b1c8a1SJohn Marino pad = 1; 159f5b1c8a1SJohn Marino pb = 0xFF; 160f5b1c8a1SJohn Marino break; 161f5b1c8a1SJohn Marino } 162f5b1c8a1SJohn Marino } 163f5b1c8a1SJohn Marino } 164f5b1c8a1SJohn Marino ret += pad; 165f5b1c8a1SJohn Marino } 166f5b1c8a1SJohn Marino if (pp == NULL) 167f5b1c8a1SJohn Marino return (ret); 168f5b1c8a1SJohn Marino p= *pp; 169f5b1c8a1SJohn Marino 170f5b1c8a1SJohn Marino if (pad) 171f5b1c8a1SJohn Marino *(p++) = pb; 172f5b1c8a1SJohn Marino if (a->length == 0) 173f5b1c8a1SJohn Marino *(p++) = 0; 174f5b1c8a1SJohn Marino else if (!neg) 175f5b1c8a1SJohn Marino memcpy(p, a->data, a->length); 176f5b1c8a1SJohn Marino else { 177f5b1c8a1SJohn Marino /* Begin at the end of the encoding */ 178f5b1c8a1SJohn Marino n = a->data + a->length - 1; 179f5b1c8a1SJohn Marino p += a->length - 1; 180f5b1c8a1SJohn Marino i = a->length; 181f5b1c8a1SJohn Marino /* Copy zeros to destination as long as source is zero */ 182f5b1c8a1SJohn Marino while (!*n) { 183f5b1c8a1SJohn Marino *(p--) = 0; 184f5b1c8a1SJohn Marino n--; 185f5b1c8a1SJohn Marino i--; 186f5b1c8a1SJohn Marino } 187f5b1c8a1SJohn Marino /* Complement and increment next octet */ 188f5b1c8a1SJohn Marino *(p--) = ((*(n--)) ^ 0xff) + 1; 189f5b1c8a1SJohn Marino i--; 190f5b1c8a1SJohn Marino /* Complement any octets left */ 191f5b1c8a1SJohn Marino for (; i > 0; i--) 192f5b1c8a1SJohn Marino *(p--) = *(n--) ^ 0xff; 193f5b1c8a1SJohn Marino } 194f5b1c8a1SJohn Marino 195f5b1c8a1SJohn Marino *pp += ret; 196f5b1c8a1SJohn Marino return (ret); 197f5b1c8a1SJohn Marino } 198f5b1c8a1SJohn Marino 199f5b1c8a1SJohn Marino /* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */ 200f5b1c8a1SJohn Marino 201f5b1c8a1SJohn Marino ASN1_INTEGER * 202f5b1c8a1SJohn Marino c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, long len) 203f5b1c8a1SJohn Marino { 204f5b1c8a1SJohn Marino ASN1_INTEGER *ret = NULL; 205f5b1c8a1SJohn Marino const unsigned char *p, *pend; 206f5b1c8a1SJohn Marino unsigned char *to, *s; 207f5b1c8a1SJohn Marino int i; 208f5b1c8a1SJohn Marino 209f5b1c8a1SJohn Marino if ((a == NULL) || ((*a) == NULL)) { 210f5b1c8a1SJohn Marino if ((ret = ASN1_INTEGER_new()) == NULL) 211f5b1c8a1SJohn Marino return (NULL); 212f5b1c8a1SJohn Marino } else 213f5b1c8a1SJohn Marino ret = (*a); 214f5b1c8a1SJohn Marino 21572c33676SMaxim Ag if (!ASN1_INTEGER_valid(ret)) { 21672c33676SMaxim Ag /* 21772c33676SMaxim Ag * XXX using i for an alert is confusing, 21872c33676SMaxim Ag * we should call this al 21972c33676SMaxim Ag */ 22072c33676SMaxim Ag i = ERR_R_ASN1_LENGTH_MISMATCH; 22172c33676SMaxim Ag goto err; 22272c33676SMaxim Ag } 22372c33676SMaxim Ag 224f5b1c8a1SJohn Marino p = *pp; 225f5b1c8a1SJohn Marino pend = p + len; 226f5b1c8a1SJohn Marino 227f5b1c8a1SJohn Marino /* We must malloc stuff, even for 0 bytes otherwise it 228f5b1c8a1SJohn Marino * signifies a missing NULL parameter. */ 22972c33676SMaxim Ag if (len < 0 || len > INT_MAX) { 23072c33676SMaxim Ag i = ERR_R_ASN1_LENGTH_MISMATCH; 23172c33676SMaxim Ag goto err; 23272c33676SMaxim Ag } 233f5b1c8a1SJohn Marino s = malloc(len + 1); 234f5b1c8a1SJohn Marino if (s == NULL) { 235f5b1c8a1SJohn Marino i = ERR_R_MALLOC_FAILURE; 236f5b1c8a1SJohn Marino goto err; 237f5b1c8a1SJohn Marino } 238f5b1c8a1SJohn Marino to = s; 239f5b1c8a1SJohn Marino if (!len) { 240f5b1c8a1SJohn Marino /* Strictly speaking this is an illegal INTEGER but we 241f5b1c8a1SJohn Marino * tolerate it. 242f5b1c8a1SJohn Marino */ 243f5b1c8a1SJohn Marino ret->type = V_ASN1_INTEGER; 244f5b1c8a1SJohn Marino } else if (*p & 0x80) /* a negative number */ { 245f5b1c8a1SJohn Marino ret->type = V_ASN1_NEG_INTEGER; 246f5b1c8a1SJohn Marino if ((*p == 0xff) && (len != 1)) { 247f5b1c8a1SJohn Marino p++; 248f5b1c8a1SJohn Marino len--; 249f5b1c8a1SJohn Marino } 250f5b1c8a1SJohn Marino i = len; 251f5b1c8a1SJohn Marino p += i - 1; 252f5b1c8a1SJohn Marino to += i - 1; 253f5b1c8a1SJohn Marino while((!*p) && i) { 254f5b1c8a1SJohn Marino *(to--) = 0; 255f5b1c8a1SJohn Marino i--; 256f5b1c8a1SJohn Marino p--; 257f5b1c8a1SJohn Marino } 258f5b1c8a1SJohn Marino /* Special case: if all zeros then the number will be of 259f5b1c8a1SJohn Marino * the form FF followed by n zero bytes: this corresponds to 260f5b1c8a1SJohn Marino * 1 followed by n zero bytes. We've already written n zeros 261f5b1c8a1SJohn Marino * so we just append an extra one and set the first byte to 262f5b1c8a1SJohn Marino * a 1. This is treated separately because it is the only case 263f5b1c8a1SJohn Marino * where the number of bytes is larger than len. 264f5b1c8a1SJohn Marino */ 265f5b1c8a1SJohn Marino if (!i) { 266f5b1c8a1SJohn Marino *s = 1; 267f5b1c8a1SJohn Marino s[len] = 0; 268f5b1c8a1SJohn Marino len++; 269f5b1c8a1SJohn Marino } else { 270f5b1c8a1SJohn Marino *(to--) = (*(p--) ^ 0xff) + 1; 271f5b1c8a1SJohn Marino i--; 272f5b1c8a1SJohn Marino for (; i > 0; i--) 273f5b1c8a1SJohn Marino *(to--) = *(p--) ^ 0xff; 274f5b1c8a1SJohn Marino } 275f5b1c8a1SJohn Marino } else { 276f5b1c8a1SJohn Marino ret->type = V_ASN1_INTEGER; 277f5b1c8a1SJohn Marino if ((*p == 0) && (len != 1)) { 278f5b1c8a1SJohn Marino p++; 279f5b1c8a1SJohn Marino len--; 280f5b1c8a1SJohn Marino } 281f5b1c8a1SJohn Marino memcpy(s, p, len); 282f5b1c8a1SJohn Marino } 283f5b1c8a1SJohn Marino 284f5b1c8a1SJohn Marino free(ret->data); 285f5b1c8a1SJohn Marino ret->data = s; 286f5b1c8a1SJohn Marino ret->length = (int)len; 287f5b1c8a1SJohn Marino if (a != NULL) 288f5b1c8a1SJohn Marino (*a) = ret; 289f5b1c8a1SJohn Marino *pp = pend; 290f5b1c8a1SJohn Marino return (ret); 291f5b1c8a1SJohn Marino 292f5b1c8a1SJohn Marino err: 29372c33676SMaxim Ag ASN1error(i); 294f5b1c8a1SJohn Marino if (a == NULL || *a != ret) 295f5b1c8a1SJohn Marino ASN1_INTEGER_free(ret); 296f5b1c8a1SJohn Marino return (NULL); 297f5b1c8a1SJohn Marino } 298f5b1c8a1SJohn Marino 299f5b1c8a1SJohn Marino 300f5b1c8a1SJohn Marino /* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of 301f5b1c8a1SJohn Marino * ASN1 integers: some broken software can encode a positive INTEGER 302f5b1c8a1SJohn Marino * with its MSB set as negative (it doesn't add a padding zero). 303f5b1c8a1SJohn Marino */ 304f5b1c8a1SJohn Marino 305f5b1c8a1SJohn Marino ASN1_INTEGER * 306f5b1c8a1SJohn Marino d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) 307f5b1c8a1SJohn Marino { 308f5b1c8a1SJohn Marino ASN1_INTEGER *ret = NULL; 309f5b1c8a1SJohn Marino const unsigned char *p; 310f5b1c8a1SJohn Marino unsigned char *s; 311f5b1c8a1SJohn Marino long len; 312f5b1c8a1SJohn Marino int inf, tag, xclass; 313f5b1c8a1SJohn Marino int i; 314f5b1c8a1SJohn Marino 315f5b1c8a1SJohn Marino if ((a == NULL) || ((*a) == NULL)) { 316f5b1c8a1SJohn Marino if ((ret = ASN1_INTEGER_new()) == NULL) 317f5b1c8a1SJohn Marino return (NULL); 318f5b1c8a1SJohn Marino } else 319f5b1c8a1SJohn Marino ret = (*a); 320f5b1c8a1SJohn Marino 32172c33676SMaxim Ag if (!ASN1_INTEGER_valid(ret)) { 32272c33676SMaxim Ag i = ERR_R_ASN1_LENGTH_MISMATCH; 32372c33676SMaxim Ag goto err; 32472c33676SMaxim Ag } 32572c33676SMaxim Ag 326f5b1c8a1SJohn Marino p = *pp; 327f5b1c8a1SJohn Marino inf = ASN1_get_object(&p, &len, &tag, &xclass, length); 328f5b1c8a1SJohn Marino if (inf & 0x80) { 329f5b1c8a1SJohn Marino i = ASN1_R_BAD_OBJECT_HEADER; 330f5b1c8a1SJohn Marino goto err; 331f5b1c8a1SJohn Marino } 332f5b1c8a1SJohn Marino 333f5b1c8a1SJohn Marino if (tag != V_ASN1_INTEGER) { 334f5b1c8a1SJohn Marino i = ASN1_R_EXPECTING_AN_INTEGER; 335f5b1c8a1SJohn Marino goto err; 336f5b1c8a1SJohn Marino } 337f5b1c8a1SJohn Marino 338f5b1c8a1SJohn Marino /* We must malloc stuff, even for 0 bytes otherwise it 339f5b1c8a1SJohn Marino * signifies a missing NULL parameter. */ 34072c33676SMaxim Ag if (len < 0 || len > INT_MAX) { 34172c33676SMaxim Ag i = ERR_R_ASN1_LENGTH_MISMATCH; 34272c33676SMaxim Ag goto err; 34372c33676SMaxim Ag } 344f5b1c8a1SJohn Marino s = malloc(len + 1); 345f5b1c8a1SJohn Marino if (s == NULL) { 346f5b1c8a1SJohn Marino i = ERR_R_MALLOC_FAILURE; 347f5b1c8a1SJohn Marino goto err; 348f5b1c8a1SJohn Marino } 349f5b1c8a1SJohn Marino ret->type = V_ASN1_INTEGER; 350f5b1c8a1SJohn Marino if (len) { 351f5b1c8a1SJohn Marino if ((*p == 0) && (len != 1)) { 352f5b1c8a1SJohn Marino p++; 353f5b1c8a1SJohn Marino len--; 354f5b1c8a1SJohn Marino } 355f5b1c8a1SJohn Marino memcpy(s, p, len); 356f5b1c8a1SJohn Marino p += len; 357f5b1c8a1SJohn Marino } 358f5b1c8a1SJohn Marino 359f5b1c8a1SJohn Marino free(ret->data); 360f5b1c8a1SJohn Marino ret->data = s; 361f5b1c8a1SJohn Marino ret->length = (int)len; 362f5b1c8a1SJohn Marino if (a != NULL) 363f5b1c8a1SJohn Marino (*a) = ret; 364f5b1c8a1SJohn Marino *pp = p; 365f5b1c8a1SJohn Marino return (ret); 366f5b1c8a1SJohn Marino 367f5b1c8a1SJohn Marino err: 36872c33676SMaxim Ag ASN1error(i); 369f5b1c8a1SJohn Marino if (a == NULL || *a != ret) 370f5b1c8a1SJohn Marino ASN1_INTEGER_free(ret); 371f5b1c8a1SJohn Marino return (NULL); 372f5b1c8a1SJohn Marino } 373f5b1c8a1SJohn Marino 374f5b1c8a1SJohn Marino int 375f5b1c8a1SJohn Marino ASN1_INTEGER_set(ASN1_INTEGER *a, long v) 376f5b1c8a1SJohn Marino { 377f5b1c8a1SJohn Marino int j, k; 378f5b1c8a1SJohn Marino unsigned int i; 379f5b1c8a1SJohn Marino unsigned char buf[sizeof(long) + 1]; 380f5b1c8a1SJohn Marino long d; 381f5b1c8a1SJohn Marino 382f5b1c8a1SJohn Marino a->type = V_ASN1_INTEGER; 383f5b1c8a1SJohn Marino /* XXX ssl/ssl_asn1.c:i2d_SSL_SESSION() depends upon this bound vae */ 384f5b1c8a1SJohn Marino if (a->length < (int)(sizeof(long) + 1)) { 385f5b1c8a1SJohn Marino free(a->data); 386f5b1c8a1SJohn Marino a->data = calloc(1, sizeof(long) + 1); 387f5b1c8a1SJohn Marino } 388f5b1c8a1SJohn Marino if (a->data == NULL) { 38972c33676SMaxim Ag ASN1error(ERR_R_MALLOC_FAILURE); 390f5b1c8a1SJohn Marino return (0); 391f5b1c8a1SJohn Marino } 392f5b1c8a1SJohn Marino d = v; 393f5b1c8a1SJohn Marino if (d < 0) { 394f5b1c8a1SJohn Marino d = -d; 395f5b1c8a1SJohn Marino a->type = V_ASN1_NEG_INTEGER; 396f5b1c8a1SJohn Marino } 397f5b1c8a1SJohn Marino 398f5b1c8a1SJohn Marino for (i = 0; i < sizeof(long); i++) { 399f5b1c8a1SJohn Marino if (d == 0) 400f5b1c8a1SJohn Marino break; 401f5b1c8a1SJohn Marino buf[i] = (int)d & 0xff; 402f5b1c8a1SJohn Marino d >>= 8; 403f5b1c8a1SJohn Marino } 404f5b1c8a1SJohn Marino j = 0; 405f5b1c8a1SJohn Marino for (k = i - 1; k >= 0; k--) 406f5b1c8a1SJohn Marino a->data[j++] = buf[k]; 407f5b1c8a1SJohn Marino a->length = j; 408f5b1c8a1SJohn Marino return (1); 409f5b1c8a1SJohn Marino } 410f5b1c8a1SJohn Marino 41172c33676SMaxim Ag /* 41272c33676SMaxim Ag * XXX this particular API is a gibbering eidrich horror that makes it 41372c33676SMaxim Ag * impossible to determine valid return cases from errors.. "a bit 41472c33676SMaxim Ag * ugly" is preserved for posterity, unfortunately this is probably 41572c33676SMaxim Ag * unfixable without changing public API 41672c33676SMaxim Ag */ 417f5b1c8a1SJohn Marino long 418f5b1c8a1SJohn Marino ASN1_INTEGER_get(const ASN1_INTEGER *a) 419f5b1c8a1SJohn Marino { 420f5b1c8a1SJohn Marino int neg = 0, i; 421f5b1c8a1SJohn Marino long r = 0; 422f5b1c8a1SJohn Marino 423f5b1c8a1SJohn Marino if (a == NULL) 424f5b1c8a1SJohn Marino return (0L); 425f5b1c8a1SJohn Marino i = a->type; 426f5b1c8a1SJohn Marino if (i == V_ASN1_NEG_INTEGER) 427f5b1c8a1SJohn Marino neg = 1; 428f5b1c8a1SJohn Marino else if (i != V_ASN1_INTEGER) 429f5b1c8a1SJohn Marino return -1; 430f5b1c8a1SJohn Marino 43172c33676SMaxim Ag if (!ASN1_INTEGER_valid(a)) 43272c33676SMaxim Ag return -1; /* XXX best effort */ 43372c33676SMaxim Ag 434f5b1c8a1SJohn Marino if (a->length > (int)sizeof(long)) { 435f5b1c8a1SJohn Marino /* hmm... a bit ugly, return all ones */ 436f5b1c8a1SJohn Marino return -1; 437f5b1c8a1SJohn Marino } 438f5b1c8a1SJohn Marino if (a->data == NULL) 439f5b1c8a1SJohn Marino return 0; 440f5b1c8a1SJohn Marino 441f5b1c8a1SJohn Marino for (i = 0; i < a->length; i++) { 442f5b1c8a1SJohn Marino r <<= 8; 443f5b1c8a1SJohn Marino r |= (unsigned char)a->data[i]; 444f5b1c8a1SJohn Marino } 445f5b1c8a1SJohn Marino if (neg) 446f5b1c8a1SJohn Marino r = -r; 447f5b1c8a1SJohn Marino return (r); 448f5b1c8a1SJohn Marino } 449f5b1c8a1SJohn Marino 450f5b1c8a1SJohn Marino ASN1_INTEGER * 451f5b1c8a1SJohn Marino BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) 452f5b1c8a1SJohn Marino { 453f5b1c8a1SJohn Marino ASN1_INTEGER *ret; 454f5b1c8a1SJohn Marino int len, j; 455f5b1c8a1SJohn Marino 456f5b1c8a1SJohn Marino if (ai == NULL) 457f5b1c8a1SJohn Marino ret = ASN1_INTEGER_new(); 458f5b1c8a1SJohn Marino else 459f5b1c8a1SJohn Marino ret = ai; 460f5b1c8a1SJohn Marino if (ret == NULL) { 46172c33676SMaxim Ag ASN1error(ERR_R_NESTED_ASN1_ERROR); 462f5b1c8a1SJohn Marino goto err; 463f5b1c8a1SJohn Marino } 46472c33676SMaxim Ag 46572c33676SMaxim Ag if (!ASN1_INTEGER_valid(ret)) 46672c33676SMaxim Ag goto err; 46772c33676SMaxim Ag 468f5b1c8a1SJohn Marino if (BN_is_negative(bn)) 469f5b1c8a1SJohn Marino ret->type = V_ASN1_NEG_INTEGER; 470f5b1c8a1SJohn Marino else 471f5b1c8a1SJohn Marino ret->type = V_ASN1_INTEGER; 472f5b1c8a1SJohn Marino j = BN_num_bits(bn); 473f5b1c8a1SJohn Marino len = ((j == 0) ? 0 : ((j / 8) + 1)); 474f5b1c8a1SJohn Marino if (ret->length < len + 4) { 475f5b1c8a1SJohn Marino unsigned char *new_data = realloc(ret->data, len + 4); 476f5b1c8a1SJohn Marino if (!new_data) { 47772c33676SMaxim Ag ASN1error(ERR_R_MALLOC_FAILURE); 478f5b1c8a1SJohn Marino goto err; 479f5b1c8a1SJohn Marino } 480f5b1c8a1SJohn Marino ret->data = new_data; 481f5b1c8a1SJohn Marino } 482f5b1c8a1SJohn Marino ret->length = BN_bn2bin(bn, ret->data); 483f5b1c8a1SJohn Marino 484f5b1c8a1SJohn Marino /* Correct zero case */ 485f5b1c8a1SJohn Marino if (!ret->length) { 486f5b1c8a1SJohn Marino ret->data[0] = 0; 487f5b1c8a1SJohn Marino ret->length = 1; 488f5b1c8a1SJohn Marino } 489f5b1c8a1SJohn Marino return (ret); 490f5b1c8a1SJohn Marino 491f5b1c8a1SJohn Marino err: 492f5b1c8a1SJohn Marino if (ret != ai) 493f5b1c8a1SJohn Marino ASN1_INTEGER_free(ret); 494f5b1c8a1SJohn Marino return (NULL); 495f5b1c8a1SJohn Marino } 496f5b1c8a1SJohn Marino 497f5b1c8a1SJohn Marino BIGNUM * 498f5b1c8a1SJohn Marino ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) 499f5b1c8a1SJohn Marino { 500f5b1c8a1SJohn Marino BIGNUM *ret; 501f5b1c8a1SJohn Marino 50272c33676SMaxim Ag if (!ASN1_INTEGER_valid(ai)) 50372c33676SMaxim Ag return (NULL); 50472c33676SMaxim Ag 505f5b1c8a1SJohn Marino if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) 50672c33676SMaxim Ag ASN1error(ASN1_R_BN_LIB); 507f5b1c8a1SJohn Marino else if (ai->type == V_ASN1_NEG_INTEGER) 508f5b1c8a1SJohn Marino BN_set_negative(ret, 1); 509f5b1c8a1SJohn Marino return (ret); 510f5b1c8a1SJohn Marino } 511