155714Skris/* crypto/asn1/a_bytes.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> 6055714Skris#include "cryptlib.h" 61109998Smarkm#include <openssl/asn1.h> 6255714Skris 63306195Sjkimstatic int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c, 64306195Sjkim int depth); 65306195Sjkimstatic ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a, 66306195Sjkim const unsigned char **pp, long length, 67306195Sjkim int Ptag, int Pclass, int depth, 68306195Sjkim int *perr); 69280297Sjkim/* 70280297Sjkim * type is a 'bitmap' of acceptable string types. 7155714Skris */ 72160814SsimonASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp, 73280297Sjkim long length, int type) 74280297Sjkim{ 75280297Sjkim ASN1_STRING *ret = NULL; 76280297Sjkim const unsigned char *p; 77280297Sjkim unsigned char *s; 78280297Sjkim long len; 79280297Sjkim int inf, tag, xclass; 80280297Sjkim int i = 0; 8155714Skris 82280297Sjkim p = *pp; 83280297Sjkim inf = ASN1_get_object(&p, &len, &tag, &xclass, length); 84280297Sjkim if (inf & 0x80) 85280297Sjkim goto err; 8655714Skris 87280297Sjkim if (tag >= 32) { 88280297Sjkim i = ASN1_R_TAG_VALUE_TOO_HIGH; 89280297Sjkim goto err; 90280297Sjkim } 91280297Sjkim if (!(ASN1_tag2bit(tag) & type)) { 92280297Sjkim i = ASN1_R_WRONG_TYPE; 93280297Sjkim goto err; 94280297Sjkim } 9555714Skris 96280297Sjkim /* If a bit-string, exit early */ 97280297Sjkim if (tag == V_ASN1_BIT_STRING) 98280297Sjkim return (d2i_ASN1_BIT_STRING(a, pp, length)); 9955714Skris 100280297Sjkim if ((a == NULL) || ((*a) == NULL)) { 101280297Sjkim if ((ret = ASN1_STRING_new()) == NULL) 102280297Sjkim return (NULL); 103280297Sjkim } else 104280297Sjkim ret = (*a); 10555714Skris 106280297Sjkim if (len != 0) { 107306195Sjkim s = OPENSSL_malloc((int)len + 1); 108280297Sjkim if (s == NULL) { 109280297Sjkim i = ERR_R_MALLOC_FAILURE; 110280297Sjkim goto err; 111280297Sjkim } 112280297Sjkim memcpy(s, p, (int)len); 113280297Sjkim s[len] = '\0'; 114280297Sjkim p += len; 115280297Sjkim } else 116280297Sjkim s = NULL; 11755714Skris 118280297Sjkim if (ret->data != NULL) 119280297Sjkim OPENSSL_free(ret->data); 120280297Sjkim ret->length = (int)len; 121280297Sjkim ret->data = s; 122280297Sjkim ret->type = tag; 123280297Sjkim if (a != NULL) 124280297Sjkim (*a) = ret; 125280297Sjkim *pp = p; 126280297Sjkim return (ret); 127280297Sjkim err: 128280297Sjkim ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES, i); 129280297Sjkim if ((ret != NULL) && ((a == NULL) || (*a != ret))) 130280297Sjkim ASN1_STRING_free(ret); 131280297Sjkim return (NULL); 132280297Sjkim} 13355714Skris 13455714Skrisint i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass) 135280297Sjkim{ 136280297Sjkim int ret, r, constructed; 137280297Sjkim unsigned char *p; 13855714Skris 139280297Sjkim if (a == NULL) 140280297Sjkim return (0); 14155714Skris 142280297Sjkim if (tag == V_ASN1_BIT_STRING) 143280297Sjkim return (i2d_ASN1_BIT_STRING(a, pp)); 14455714Skris 145280297Sjkim ret = a->length; 146280297Sjkim r = ASN1_object_size(0, ret, tag); 147280297Sjkim if (pp == NULL) 148280297Sjkim return (r); 149280297Sjkim p = *pp; 15055714Skris 151280297Sjkim if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET)) 152280297Sjkim constructed = 1; 153280297Sjkim else 154280297Sjkim constructed = 0; 155280297Sjkim ASN1_put_object(&p, constructed, ret, tag, xclass); 156280297Sjkim memcpy(p, a->data, a->length); 157280297Sjkim p += a->length; 158280297Sjkim *pp = p; 159280297Sjkim return (r); 160280297Sjkim} 161280297Sjkim 162306195Sjkim/* 163306195Sjkim * Maximum recursion depth of d2i_ASN1_bytes(): much more than should be 164306195Sjkim * encountered in pratice. 165306195Sjkim */ 166306195Sjkim 167306195Sjkim#define ASN1_BYTES_MAXDEPTH 20 168306195Sjkim 169160814SsimonASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, 170280297Sjkim long length, int Ptag, int Pclass) 171280297Sjkim{ 172306195Sjkim int err = 0; 173306195Sjkim ASN1_STRING *s = int_d2i_ASN1_bytes(a, pp, length, Ptag, Pclass, 0, &err); 174306195Sjkim if (err != 0) 175306195Sjkim ASN1err(ASN1_F_D2I_ASN1_BYTES, err); 176306195Sjkim return s; 177306195Sjkim} 178306195Sjkim 179306195Sjkimstatic ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a, 180306195Sjkim const unsigned char **pp, long length, 181306195Sjkim int Ptag, int Pclass, 182306195Sjkim int depth, int *perr) 183306195Sjkim{ 184280297Sjkim ASN1_STRING *ret = NULL; 185280297Sjkim const unsigned char *p; 186280297Sjkim unsigned char *s; 187280297Sjkim long len; 188280297Sjkim int inf, tag, xclass; 18955714Skris 190306195Sjkim if (depth > ASN1_BYTES_MAXDEPTH) { 191306195Sjkim *perr = ASN1_R_NESTED_ASN1_STRING; 192306195Sjkim return NULL; 193306195Sjkim } 194306195Sjkim 195280297Sjkim if ((a == NULL) || ((*a) == NULL)) { 196280297Sjkim if ((ret = ASN1_STRING_new()) == NULL) 197280297Sjkim return (NULL); 198280297Sjkim } else 199280297Sjkim ret = (*a); 20055714Skris 201280297Sjkim p = *pp; 202280297Sjkim inf = ASN1_get_object(&p, &len, &tag, &xclass, length); 203280297Sjkim if (inf & 0x80) { 204306195Sjkim *perr = ASN1_R_BAD_OBJECT_HEADER; 205280297Sjkim goto err; 206280297Sjkim } 20755714Skris 208280297Sjkim if (tag != Ptag) { 209306195Sjkim *perr = ASN1_R_WRONG_TAG; 210280297Sjkim goto err; 211280297Sjkim } 21255714Skris 213280297Sjkim if (inf & V_ASN1_CONSTRUCTED) { 214280297Sjkim ASN1_const_CTX c; 21555714Skris 216306195Sjkim c.error = 0; 217280297Sjkim c.pp = pp; 218280297Sjkim c.p = p; 219280297Sjkim c.inf = inf; 220280297Sjkim c.slen = len; 221280297Sjkim c.tag = Ptag; 222280297Sjkim c.xclass = Pclass; 223280297Sjkim c.max = (length == 0) ? 0 : (p + length); 224306195Sjkim if (!asn1_collate_primitive(ret, &c, depth)) { 225306195Sjkim *perr = c.error; 226280297Sjkim goto err; 227306195Sjkim } else { 228280297Sjkim p = c.p; 229280297Sjkim } 230280297Sjkim } else { 231280297Sjkim if (len != 0) { 232280297Sjkim if ((ret->length < len) || (ret->data == NULL)) { 233306195Sjkim s = OPENSSL_malloc((int)len + 1); 234280297Sjkim if (s == NULL) { 235306195Sjkim *perr = ERR_R_MALLOC_FAILURE; 236280297Sjkim goto err; 237280297Sjkim } 238298998Sjkim if (ret->data != NULL) 239298998Sjkim OPENSSL_free(ret->data); 240280297Sjkim } else 241280297Sjkim s = ret->data; 242280297Sjkim memcpy(s, p, (int)len); 243280297Sjkim s[len] = '\0'; 244280297Sjkim p += len; 245280297Sjkim } else { 246280297Sjkim s = NULL; 247280297Sjkim if (ret->data != NULL) 248280297Sjkim OPENSSL_free(ret->data); 249280297Sjkim } 25055714Skris 251280297Sjkim ret->length = (int)len; 252280297Sjkim ret->data = s; 253280297Sjkim ret->type = Ptag; 254280297Sjkim } 25555714Skris 256280297Sjkim if (a != NULL) 257280297Sjkim (*a) = ret; 258280297Sjkim *pp = p; 259280297Sjkim return (ret); 260280297Sjkim err: 261280297Sjkim if ((ret != NULL) && ((a == NULL) || (*a != ret))) 262280297Sjkim ASN1_STRING_free(ret); 263280297Sjkim return (NULL); 264280297Sjkim} 26555714Skris 266280297Sjkim/* 267280297Sjkim * We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse them 268280297Sjkim * into the one structure that is then returned 269280297Sjkim */ 270280297Sjkim/* 271280297Sjkim * There have been a few bug fixes for this function from Paul Keogh 272280297Sjkim * <paul.keogh@sse.ie>, many thanks to him 273280297Sjkim */ 274306195Sjkimstatic int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c, 275306195Sjkim int depth) 276280297Sjkim{ 277280297Sjkim ASN1_STRING *os = NULL; 278280297Sjkim BUF_MEM b; 279280297Sjkim int num; 28055714Skris 281280297Sjkim b.length = 0; 282280297Sjkim b.max = 0; 283280297Sjkim b.data = NULL; 28455714Skris 285280297Sjkim if (a == NULL) { 286280297Sjkim c->error = ERR_R_PASSED_NULL_PARAMETER; 287280297Sjkim goto err; 288280297Sjkim } 28955714Skris 290280297Sjkim num = 0; 291280297Sjkim for (;;) { 292280297Sjkim if (c->inf & 1) { 293280297Sjkim c->eos = ASN1_const_check_infinite_end(&c->p, 294280297Sjkim (long)(c->max - c->p)); 295280297Sjkim if (c->eos) 296280297Sjkim break; 297280297Sjkim } else { 298280297Sjkim if (c->slen <= 0) 299280297Sjkim break; 300280297Sjkim } 30155714Skris 302280297Sjkim c->q = c->p; 303306195Sjkim if (int_d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass, 304306195Sjkim depth + 1, &c->error) == NULL) { 305280297Sjkim goto err; 306280297Sjkim } 30755714Skris 308280297Sjkim if (!BUF_MEM_grow_clean(&b, num + os->length)) { 309280297Sjkim c->error = ERR_R_BUF_LIB; 310280297Sjkim goto err; 311280297Sjkim } 312280297Sjkim memcpy(&(b.data[num]), os->data, os->length); 313280297Sjkim if (!(c->inf & 1)) 314280297Sjkim c->slen -= (c->p - c->q); 315280297Sjkim num += os->length; 316280297Sjkim } 31755714Skris 318280297Sjkim if (!asn1_const_Finish(c)) 319280297Sjkim goto err; 32055714Skris 321280297Sjkim a->length = num; 322280297Sjkim if (a->data != NULL) 323280297Sjkim OPENSSL_free(a->data); 324280297Sjkim a->data = (unsigned char *)b.data; 325280297Sjkim if (os != NULL) 326280297Sjkim ASN1_STRING_free(os); 327280297Sjkim return (1); 328280297Sjkim err: 329280297Sjkim if (os != NULL) 330280297Sjkim ASN1_STRING_free(os); 331280297Sjkim if (b.data != NULL) 332280297Sjkim OPENSSL_free(b.data); 333280297Sjkim return (0); 334280297Sjkim} 335