155714Skris/* crypto/asn1/asn1_lib.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8280297Sjkim * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15280297Sjkim * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22280297Sjkim * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37280297Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40280297Sjkim * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52280297Sjkim * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 60101613Snectar#include <limits.h> 6155714Skris#include "cryptlib.h" 6255714Skris#include <openssl/asn1.h> 6355714Skris#include <openssl/asn1_mac.h> 6455714Skris 65280297Sjkimstatic int asn1_get_length(const unsigned char **pp, int *inf, long *rl, 66298998Sjkim long max); 6755714Skrisstatic void asn1_put_length(unsigned char **pp, int length); 68280297Sjkimconst char ASN1_version[] = "ASN.1" OPENSSL_VERSION_PTEXT; 6955714Skris 70160814Ssimonstatic int _asn1_check_infinite_end(const unsigned char **p, long len) 71280297Sjkim{ 72280297Sjkim /* 73280297Sjkim * If there is 0 or 1 byte left, the length check should pick things up 74280297Sjkim */ 75280297Sjkim if (len <= 0) 76280297Sjkim return (1); 77280297Sjkim else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) { 78280297Sjkim (*p) += 2; 79280297Sjkim return (1); 80280297Sjkim } 81280297Sjkim return (0); 82280297Sjkim} 8355714Skris 84160814Ssimonint ASN1_check_infinite_end(unsigned char **p, long len) 85280297Sjkim{ 86280297Sjkim return _asn1_check_infinite_end((const unsigned char **)p, len); 87280297Sjkim} 8855714Skris 89160814Ssimonint ASN1_const_check_infinite_end(const unsigned char **p, long len) 90280297Sjkim{ 91280297Sjkim return _asn1_check_infinite_end(p, len); 92280297Sjkim} 93160814Ssimon 94160814Ssimonint ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, 95280297Sjkim int *pclass, long omax) 96280297Sjkim{ 97280297Sjkim int i, ret; 98280297Sjkim long l; 99280297Sjkim const unsigned char *p = *pp; 100280297Sjkim int tag, xclass, inf; 101280297Sjkim long max = omax; 10255714Skris 103280297Sjkim if (!max) 104280297Sjkim goto err; 105280297Sjkim ret = (*p & V_ASN1_CONSTRUCTED); 106280297Sjkim xclass = (*p & V_ASN1_PRIVATE); 107280297Sjkim i = *p & V_ASN1_PRIMITIVE_TAG; 108280297Sjkim if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */ 109280297Sjkim p++; 110280297Sjkim if (--max == 0) 111280297Sjkim goto err; 112280297Sjkim l = 0; 113280297Sjkim while (*p & 0x80) { 114280297Sjkim l <<= 7L; 115280297Sjkim l |= *(p++) & 0x7f; 116280297Sjkim if (--max == 0) 117280297Sjkim goto err; 118280297Sjkim if (l > (INT_MAX >> 7L)) 119280297Sjkim goto err; 120280297Sjkim } 121280297Sjkim l <<= 7L; 122280297Sjkim l |= *(p++) & 0x7f; 123280297Sjkim tag = (int)l; 124280297Sjkim if (--max == 0) 125280297Sjkim goto err; 126280297Sjkim } else { 127280297Sjkim tag = i; 128280297Sjkim p++; 129280297Sjkim if (--max == 0) 130280297Sjkim goto err; 131280297Sjkim } 132280297Sjkim *ptag = tag; 133280297Sjkim *pclass = xclass; 134298998Sjkim if (!asn1_get_length(&p, &inf, plength, max)) 135280297Sjkim goto err; 13655714Skris 137280297Sjkim if (inf && !(ret & V_ASN1_CONSTRUCTED)) 138280297Sjkim goto err; 139269682Sjkim 14055714Skris#if 0 141280297Sjkim fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n", 142280297Sjkim (int)p, *plength, omax, (int)*pp, (int)(p + *plength), 143280297Sjkim (int)(omax + *pp)); 14455714Skris 14555714Skris#endif 146280297Sjkim if (*plength > (omax - (p - *pp))) { 147280297Sjkim ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG); 148280297Sjkim /* 149280297Sjkim * Set this so that even if things are not long enough the values are 150280297Sjkim * set correctly 151280297Sjkim */ 152280297Sjkim ret |= 0x80; 153280297Sjkim } 154280297Sjkim *pp = p; 155280297Sjkim return (ret | inf); 156280297Sjkim err: 157280297Sjkim ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG); 158280297Sjkim return (0x80); 159280297Sjkim} 16055714Skris 161280297Sjkimstatic int asn1_get_length(const unsigned char **pp, int *inf, long *rl, 162298998Sjkim long max) 163280297Sjkim{ 164280297Sjkim const unsigned char *p = *pp; 165280297Sjkim unsigned long ret = 0; 166298998Sjkim unsigned long i; 16755714Skris 168280297Sjkim if (max-- < 1) 169298998Sjkim return 0; 170280297Sjkim if (*p == 0x80) { 171280297Sjkim *inf = 1; 172280297Sjkim ret = 0; 173280297Sjkim p++; 174280297Sjkim } else { 175280297Sjkim *inf = 0; 176280297Sjkim i = *p & 0x7f; 177280297Sjkim if (*(p++) & 0x80) { 178298998Sjkim if (i > sizeof(ret) || max < (long)i) 179280297Sjkim return 0; 180280297Sjkim while (i-- > 0) { 181280297Sjkim ret <<= 8L; 182280297Sjkim ret |= *(p++); 183280297Sjkim } 184280297Sjkim } else 185280297Sjkim ret = i; 186280297Sjkim } 187280297Sjkim if (ret > LONG_MAX) 188280297Sjkim return 0; 189280297Sjkim *pp = p; 190280297Sjkim *rl = (long)ret; 191298998Sjkim return 1; 192280297Sjkim} 19355714Skris 194280297Sjkim/* 195280297Sjkim * class 0 is constructed constructed == 2 for indefinite length constructed 196280297Sjkim */ 19755714Skrisvoid ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, 198280297Sjkim int xclass) 199280297Sjkim{ 200280297Sjkim unsigned char *p = *pp; 201280297Sjkim int i, ttag; 20255714Skris 203280297Sjkim i = (constructed) ? V_ASN1_CONSTRUCTED : 0; 204280297Sjkim i |= (xclass & V_ASN1_PRIVATE); 205280297Sjkim if (tag < 31) 206280297Sjkim *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); 207280297Sjkim else { 208280297Sjkim *(p++) = i | V_ASN1_PRIMITIVE_TAG; 209280297Sjkim for (i = 0, ttag = tag; ttag > 0; i++) 210280297Sjkim ttag >>= 7; 211280297Sjkim ttag = i; 212280297Sjkim while (i-- > 0) { 213280297Sjkim p[i] = tag & 0x7f; 214280297Sjkim if (i != (ttag - 1)) 215280297Sjkim p[i] |= 0x80; 216280297Sjkim tag >>= 7; 217280297Sjkim } 218280297Sjkim p += ttag; 219280297Sjkim } 220280297Sjkim if (constructed == 2) 221280297Sjkim *(p++) = 0x80; 222280297Sjkim else 223280297Sjkim asn1_put_length(&p, length); 224280297Sjkim *pp = p; 225280297Sjkim} 22655714Skris 227160814Ssimonint ASN1_put_eoc(unsigned char **pp) 228280297Sjkim{ 229280297Sjkim unsigned char *p = *pp; 230280297Sjkim *p++ = 0; 231280297Sjkim *p++ = 0; 232280297Sjkim *pp = p; 233280297Sjkim return 2; 234280297Sjkim} 235160814Ssimon 23655714Skrisstatic void asn1_put_length(unsigned char **pp, int length) 237280297Sjkim{ 238280297Sjkim unsigned char *p = *pp; 239280297Sjkim int i, l; 240280297Sjkim if (length <= 127) 241280297Sjkim *(p++) = (unsigned char)length; 242280297Sjkim else { 243280297Sjkim l = length; 244280297Sjkim for (i = 0; l > 0; i++) 245280297Sjkim l >>= 8; 246280297Sjkim *(p++) = i | 0x80; 247280297Sjkim l = i; 248280297Sjkim while (i-- > 0) { 249280297Sjkim p[i] = length & 0xff; 250280297Sjkim length >>= 8; 251280297Sjkim } 252280297Sjkim p += l; 253280297Sjkim } 254280297Sjkim *pp = p; 255280297Sjkim} 25655714Skris 25755714Skrisint ASN1_object_size(int constructed, int length, int tag) 258280297Sjkim{ 259306195Sjkim int ret = 1; 260306195Sjkim if (length < 0) 261306195Sjkim return -1; 262280297Sjkim if (tag >= 31) { 263280297Sjkim while (tag > 0) { 264280297Sjkim tag >>= 7; 265280297Sjkim ret++; 266280297Sjkim } 267280297Sjkim } 268306195Sjkim if (constructed == 2) { 269306195Sjkim ret += 3; 270306195Sjkim } else { 271306195Sjkim ret++; 272306195Sjkim if (length > 127) { 273306195Sjkim int tmplen = length; 274306195Sjkim while (tmplen > 0) { 275306195Sjkim tmplen >>= 8; 276306195Sjkim ret++; 277306195Sjkim } 278280297Sjkim } 279280297Sjkim } 280306195Sjkim if (ret >= INT_MAX - length) 281306195Sjkim return -1; 282306195Sjkim return ret + length; 283280297Sjkim} 28455714Skris 285160814Ssimonstatic int _asn1_Finish(ASN1_const_CTX *c) 286280297Sjkim{ 287280297Sjkim if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) { 288280297Sjkim if (!ASN1_const_check_infinite_end(&c->p, c->slen)) { 289280297Sjkim c->error = ERR_R_MISSING_ASN1_EOS; 290280297Sjkim return (0); 291280297Sjkim } 292280297Sjkim } 293280297Sjkim if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) { 294280297Sjkim c->error = ERR_R_ASN1_LENGTH_MISMATCH; 295280297Sjkim return (0); 296280297Sjkim } 297280297Sjkim return (1); 298280297Sjkim} 29955714Skris 300160814Ssimonint asn1_Finish(ASN1_CTX *c) 301280297Sjkim{ 302280297Sjkim return _asn1_Finish((ASN1_const_CTX *)c); 303280297Sjkim} 30455714Skris 305160814Ssimonint asn1_const_Finish(ASN1_const_CTX *c) 306280297Sjkim{ 307280297Sjkim return _asn1_Finish(c); 308280297Sjkim} 309160814Ssimon 310160814Ssimonint asn1_GetSequence(ASN1_const_CTX *c, long *length) 311280297Sjkim{ 312280297Sjkim const unsigned char *q; 313160814Ssimon 314280297Sjkim q = c->p; 315280297Sjkim c->inf = ASN1_get_object(&(c->p), &(c->slen), &(c->tag), &(c->xclass), 316280297Sjkim *length); 317280297Sjkim if (c->inf & 0x80) { 318280297Sjkim c->error = ERR_R_BAD_GET_ASN1_OBJECT_CALL; 319280297Sjkim return (0); 320280297Sjkim } 321280297Sjkim if (c->tag != V_ASN1_SEQUENCE) { 322280297Sjkim c->error = ERR_R_EXPECTING_AN_ASN1_SEQUENCE; 323280297Sjkim return (0); 324280297Sjkim } 325280297Sjkim (*length) -= (c->p - q); 326280297Sjkim if (c->max && (*length < 0)) { 327280297Sjkim c->error = ERR_R_ASN1_LENGTH_MISMATCH; 328280297Sjkim return (0); 329280297Sjkim } 330280297Sjkim if (c->inf == (1 | V_ASN1_CONSTRUCTED)) 331306195Sjkim c->slen = *length; 332280297Sjkim c->eos = 0; 333280297Sjkim return (1); 334280297Sjkim} 33555714Skris 336238405Sjkimint ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) 337280297Sjkim{ 338280297Sjkim if (str == NULL) 339280297Sjkim return 0; 340280297Sjkim dst->type = str->type; 341280297Sjkim if (!ASN1_STRING_set(dst, str->data, str->length)) 342280297Sjkim return 0; 343280297Sjkim dst->flags = str->flags; 344280297Sjkim return 1; 345280297Sjkim} 346238405Sjkim 347238405SjkimASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) 348280297Sjkim{ 349280297Sjkim ASN1_STRING *ret; 350280297Sjkim if (!str) 351280297Sjkim return NULL; 352280297Sjkim ret = ASN1_STRING_new(); 353280297Sjkim if (!ret) 354280297Sjkim return NULL; 355280297Sjkim if (!ASN1_STRING_copy(ret, str)) { 356280297Sjkim ASN1_STRING_free(ret); 357280297Sjkim return NULL; 358280297Sjkim } 359280297Sjkim return ret; 360280297Sjkim} 36155714Skris 36255714Skrisint ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) 363280297Sjkim{ 364280297Sjkim unsigned char *c; 365280297Sjkim const char *data = _data; 36655714Skris 367280297Sjkim if (len < 0) { 368280297Sjkim if (data == NULL) 369280297Sjkim return (0); 370280297Sjkim else 371280297Sjkim len = strlen(data); 372280297Sjkim } 373306195Sjkim if ((str->length <= len) || (str->data == NULL)) { 374280297Sjkim c = str->data; 375280297Sjkim if (c == NULL) 376280297Sjkim str->data = OPENSSL_malloc(len + 1); 377280297Sjkim else 378280297Sjkim str->data = OPENSSL_realloc(c, len + 1); 37955714Skris 380280297Sjkim if (str->data == NULL) { 381280297Sjkim ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE); 382280297Sjkim str->data = c; 383280297Sjkim return (0); 384280297Sjkim } 385280297Sjkim } 386280297Sjkim str->length = len; 387280297Sjkim if (data != NULL) { 388280297Sjkim memcpy(str->data, data, len); 389280297Sjkim /* an allowance for strings :-) */ 390280297Sjkim str->data[len] = '\0'; 391280297Sjkim } 392280297Sjkim return (1); 393280297Sjkim} 39455714Skris 395194206Ssimonvoid ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) 396280297Sjkim{ 397280297Sjkim if (str->data) 398280297Sjkim OPENSSL_free(str->data); 399280297Sjkim str->data = data; 400280297Sjkim str->length = len; 401280297Sjkim} 402194206Ssimon 40355714SkrisASN1_STRING *ASN1_STRING_new(void) 404280297Sjkim{ 405280297Sjkim return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); 406280297Sjkim} 40755714Skris 40855714SkrisASN1_STRING *ASN1_STRING_type_new(int type) 409280297Sjkim{ 410280297Sjkim ASN1_STRING *ret; 41155714Skris 412280297Sjkim ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); 413280297Sjkim if (ret == NULL) { 414280297Sjkim ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE); 415280297Sjkim return (NULL); 416280297Sjkim } 417280297Sjkim ret->length = 0; 418280297Sjkim ret->type = type; 419280297Sjkim ret->data = NULL; 420280297Sjkim ret->flags = 0; 421280297Sjkim return (ret); 422280297Sjkim} 42355714Skris 42455714Skrisvoid ASN1_STRING_free(ASN1_STRING *a) 425280297Sjkim{ 426280297Sjkim if (a == NULL) 427280297Sjkim return; 428280297Sjkim if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF)) 429280297Sjkim OPENSSL_free(a->data); 430280297Sjkim OPENSSL_free(a); 431280297Sjkim} 43255714Skris 433280297Sjkimvoid ASN1_STRING_clear_free(ASN1_STRING *a) 434280297Sjkim{ 435280297Sjkim if (a && a->data && !(a->flags & ASN1_STRING_FLAG_NDEF)) 436280297Sjkim OPENSSL_cleanse(a->data, a->length); 437280297Sjkim ASN1_STRING_free(a); 438280297Sjkim} 439280297Sjkim 440238405Sjkimint ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) 441280297Sjkim{ 442280297Sjkim int i; 44355714Skris 444280297Sjkim i = (a->length - b->length); 445280297Sjkim if (i == 0) { 446280297Sjkim i = memcmp(a->data, b->data, a->length); 447280297Sjkim if (i == 0) 448280297Sjkim return (a->type - b->type); 449280297Sjkim else 450280297Sjkim return (i); 451280297Sjkim } else 452280297Sjkim return (i); 453280297Sjkim} 45455714Skris 455160814Ssimonvoid asn1_add_error(const unsigned char *address, int offset) 456280297Sjkim{ 457280297Sjkim char buf1[DECIMAL_SIZE(address) + 1], buf2[DECIMAL_SIZE(offset) + 1]; 45855714Skris 459331638Sjkim BIO_snprintf(buf1, sizeof(buf1), "%lu", (unsigned long)address); 460331638Sjkim BIO_snprintf(buf2, sizeof(buf2), "%d", offset); 461280297Sjkim ERR_add_error_data(4, "address=", buf1, " offset=", buf2); 462280297Sjkim} 46355714Skris 464238405Sjkimint ASN1_STRING_length(const ASN1_STRING *x) 465280297Sjkim{ 466280297Sjkim return M_ASN1_STRING_length(x); 467280297Sjkim} 46859191Skris 46959191Skrisvoid ASN1_STRING_length_set(ASN1_STRING *x, int len) 470280297Sjkim{ 471280297Sjkim M_ASN1_STRING_length_set(x, len); 472280297Sjkim return; 473280297Sjkim} 47459191Skris 47559191Skrisint ASN1_STRING_type(ASN1_STRING *x) 476280297Sjkim{ 477280297Sjkim return M_ASN1_STRING_type(x); 478280297Sjkim} 47959191Skris 480280297Sjkimunsigned char *ASN1_STRING_data(ASN1_STRING *x) 481280297Sjkim{ 482280297Sjkim return M_ASN1_STRING_data(x); 483280297Sjkim} 484