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