155714Skris/* crypto/asn1/a_object.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.
8280304Sjkim *
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).
15280304Sjkim *
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.
22280304Sjkim *
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 :-).
37280304Sjkim * 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)"
40280304Sjkim *
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.
52280304Sjkim *
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>
60160814Ssimon#include <limits.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/buffer.h>
6355714Skris#include <openssl/asn1.h>
6455714Skris#include <openssl/objects.h>
65194206Ssimon#include <openssl/bn.h>
6655714Skris
6755714Skrisint i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
68280304Sjkim{
69280304Sjkim    unsigned char *p;
70280304Sjkim    int objsize;
7155714Skris
72280304Sjkim    if ((a == NULL) || (a->data == NULL))
73280304Sjkim        return (0);
7455714Skris
75280304Sjkim    objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
76306196Sjkim    if (pp == NULL || objsize == -1)
77280304Sjkim        return objsize;
7855714Skris
79280304Sjkim    p = *pp;
80280304Sjkim    ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
81280304Sjkim    memcpy(p, a->data, a->length);
82280304Sjkim    p += a->length;
8355714Skris
84280304Sjkim    *pp = p;
85280304Sjkim    return (objsize);
86280304Sjkim}
8755714Skris
8855714Skrisint a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
89280304Sjkim{
90280304Sjkim    int i, first, len = 0, c, use_bn;
91280304Sjkim    char ftmp[24], *tmp = ftmp;
92280304Sjkim    int tmpsize = sizeof ftmp;
93280304Sjkim    const char *p;
94280304Sjkim    unsigned long l;
95280304Sjkim    BIGNUM *bl = NULL;
9655714Skris
97280304Sjkim    if (num == 0)
98280304Sjkim        return (0);
99280304Sjkim    else if (num == -1)
100280304Sjkim        num = strlen(buf);
10155714Skris
102280304Sjkim    p = buf;
103280304Sjkim    c = *(p++);
104280304Sjkim    num--;
105280304Sjkim    if ((c >= '0') && (c <= '2')) {
106280304Sjkim        first = c - '0';
107280304Sjkim    } else {
108280304Sjkim        ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
109280304Sjkim        goto err;
110280304Sjkim    }
11155714Skris
112280304Sjkim    if (num <= 0) {
113280304Sjkim        ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
114280304Sjkim        goto err;
115280304Sjkim    }
116280304Sjkim    c = *(p++);
117280304Sjkim    num--;
118280304Sjkim    for (;;) {
119280304Sjkim        if (num <= 0)
120280304Sjkim            break;
121280304Sjkim        if ((c != '.') && (c != ' ')) {
122280304Sjkim            ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR);
123280304Sjkim            goto err;
124280304Sjkim        }
125280304Sjkim        l = 0;
126280304Sjkim        use_bn = 0;
127280304Sjkim        for (;;) {
128280304Sjkim            if (num <= 0)
129280304Sjkim                break;
130280304Sjkim            num--;
131280304Sjkim            c = *(p++);
132280304Sjkim            if ((c == ' ') || (c == '.'))
133280304Sjkim                break;
134280304Sjkim            if ((c < '0') || (c > '9')) {
135280304Sjkim                ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
136280304Sjkim                goto err;
137280304Sjkim            }
138280304Sjkim            if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
139280304Sjkim                use_bn = 1;
140280304Sjkim                if (!bl)
141280304Sjkim                    bl = BN_new();
142280304Sjkim                if (!bl || !BN_set_word(bl, l))
143280304Sjkim                    goto err;
144280304Sjkim            }
145280304Sjkim            if (use_bn) {
146280304Sjkim                if (!BN_mul_word(bl, 10L)
147280304Sjkim                    || !BN_add_word(bl, c - '0'))
148280304Sjkim                    goto err;
149280304Sjkim            } else
150280304Sjkim                l = l * 10L + (long)(c - '0');
151280304Sjkim        }
152280304Sjkim        if (len == 0) {
153280304Sjkim            if ((first < 2) && (l >= 40)) {
154280304Sjkim                ASN1err(ASN1_F_A2D_ASN1_OBJECT,
155280304Sjkim                        ASN1_R_SECOND_NUMBER_TOO_LARGE);
156280304Sjkim                goto err;
157280304Sjkim            }
158280304Sjkim            if (use_bn) {
159280304Sjkim                if (!BN_add_word(bl, first * 40))
160280304Sjkim                    goto err;
161280304Sjkim            } else
162280304Sjkim                l += (long)first *40;
163280304Sjkim        }
164280304Sjkim        i = 0;
165280304Sjkim        if (use_bn) {
166280304Sjkim            int blsize;
167280304Sjkim            blsize = BN_num_bits(bl);
168280304Sjkim            blsize = (blsize + 6) / 7;
169280304Sjkim            if (blsize > tmpsize) {
170280304Sjkim                if (tmp != ftmp)
171280304Sjkim                    OPENSSL_free(tmp);
172280304Sjkim                tmpsize = blsize + 32;
173280304Sjkim                tmp = OPENSSL_malloc(tmpsize);
174280304Sjkim                if (!tmp)
175280304Sjkim                    goto err;
176280304Sjkim            }
177306196Sjkim            while (blsize--) {
178306196Sjkim                BN_ULONG t = BN_div_word(bl, 0x80L);
179306196Sjkim                if (t == (BN_ULONG)-1)
180306196Sjkim                    goto err;
181306196Sjkim                tmp[i++] = (unsigned char)t;
182306196Sjkim            }
183280304Sjkim        } else {
184160814Ssimon
185280304Sjkim            for (;;) {
186280304Sjkim                tmp[i++] = (unsigned char)l & 0x7f;
187280304Sjkim                l >>= 7L;
188280304Sjkim                if (l == 0L)
189280304Sjkim                    break;
190280304Sjkim            }
19155714Skris
192280304Sjkim        }
193280304Sjkim        if (out != NULL) {
194280304Sjkim            if (len + i > olen) {
195280304Sjkim                ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL);
196280304Sjkim                goto err;
197280304Sjkim            }
198280304Sjkim            while (--i > 0)
199280304Sjkim                out[len++] = tmp[i] | 0x80;
200280304Sjkim            out[len++] = tmp[0];
201280304Sjkim        } else
202280304Sjkim            len += i;
203280304Sjkim    }
204280304Sjkim    if (tmp != ftmp)
205280304Sjkim        OPENSSL_free(tmp);
206280304Sjkim    if (bl)
207280304Sjkim        BN_free(bl);
208280304Sjkim    return (len);
209280304Sjkim err:
210280304Sjkim    if (tmp != ftmp)
211280304Sjkim        OPENSSL_free(tmp);
212280304Sjkim    if (bl)
213280304Sjkim        BN_free(bl);
214280304Sjkim    return (0);
215280304Sjkim}
216280304Sjkim
21755714Skrisint i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
21855714Skris{
219280304Sjkim    return OBJ_obj2txt(buf, buf_len, a, 0);
22055714Skris}
22155714Skris
22255714Skrisint i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
223280304Sjkim{
224280304Sjkim    char buf[80], *p = buf;
225280304Sjkim    int i;
22655714Skris
227280304Sjkim    if ((a == NULL) || (a->data == NULL))
228280304Sjkim        return (BIO_write(bp, "NULL", 4));
229280304Sjkim    i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
230280304Sjkim    if (i > (int)(sizeof(buf) - 1)) {
231280304Sjkim        p = OPENSSL_malloc(i + 1);
232280304Sjkim        if (!p)
233280304Sjkim            return -1;
234280304Sjkim        i2t_ASN1_OBJECT(p, i + 1, a);
235280304Sjkim    }
236280304Sjkim    if (i <= 0)
237280304Sjkim        return BIO_write(bp, "<INVALID>", 9);
238280304Sjkim    BIO_write(bp, p, i);
239280304Sjkim    if (p != buf)
240280304Sjkim        OPENSSL_free(p);
241280304Sjkim    return (i);
242280304Sjkim}
24355714Skris
244160814SsimonASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
245280304Sjkim                             long length)
24668651Skris{
247280304Sjkim    const unsigned char *p;
248280304Sjkim    long len;
249280304Sjkim    int tag, xclass;
250280304Sjkim    int inf, i;
251280304Sjkim    ASN1_OBJECT *ret = NULL;
252280304Sjkim    p = *pp;
253280304Sjkim    inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
254280304Sjkim    if (inf & 0x80) {
255280304Sjkim        i = ASN1_R_BAD_OBJECT_HEADER;
256280304Sjkim        goto err;
257280304Sjkim    }
25855714Skris
259280304Sjkim    if (tag != V_ASN1_OBJECT) {
260280304Sjkim        i = ASN1_R_EXPECTING_AN_OBJECT;
261280304Sjkim        goto err;
262280304Sjkim    }
263280304Sjkim    ret = c2i_ASN1_OBJECT(a, &p, len);
264280304Sjkim    if (ret)
265280304Sjkim        *pp = p;
266280304Sjkim    return ret;
267280304Sjkim err:
268280304Sjkim    ASN1err(ASN1_F_D2I_ASN1_OBJECT, i);
269280304Sjkim    return (NULL);
27068651Skris}
271269686Sjkim
272160814SsimonASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
273280304Sjkim                             long len)
274280304Sjkim{
275280304Sjkim    ASN1_OBJECT *ret = NULL;
276280304Sjkim    const unsigned char *p;
277280304Sjkim    unsigned char *data;
278280304Sjkim    int i, length;
279269686Sjkim
280280304Sjkim    /*
281280304Sjkim     * Sanity check OID encoding. Need at least one content octet. MSB must
282280304Sjkim     * be clear in the last octet. can't have leading 0x80 in subidentifiers,
283280304Sjkim     * see: X.690 8.19.2
284280304Sjkim     */
285280304Sjkim    if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
286280304Sjkim        p[len - 1] & 0x80) {
287280304Sjkim        ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
288280304Sjkim        return NULL;
289280304Sjkim    }
290280304Sjkim    /* Now 0 < len <= INT_MAX, so the cast is safe. */
291280304Sjkim    length = (int)len;
292280304Sjkim    for (i = 0; i < length; i++, p++) {
293280304Sjkim        if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
294280304Sjkim            ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
295280304Sjkim            return NULL;
296280304Sjkim        }
297280304Sjkim    }
29868651Skris
299280304Sjkim    /*
300280304Sjkim     * only the ASN1_OBJECTs from the 'table' will have values for ->sn or
301280304Sjkim     * ->ln
302280304Sjkim     */
303280304Sjkim    if ((a == NULL) || ((*a) == NULL) ||
304280304Sjkim        !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
305280304Sjkim        if ((ret = ASN1_OBJECT_new()) == NULL)
306280304Sjkim            return (NULL);
307280304Sjkim    } else
308280304Sjkim        ret = (*a);
30968651Skris
310280304Sjkim    p = *pp;
311280304Sjkim    /* detach data from object */
312280304Sjkim    data = (unsigned char *)ret->data;
313280304Sjkim    ret->data = NULL;
314280304Sjkim    /* once detached we can change it */
315280304Sjkim    if ((data == NULL) || (ret->length < length)) {
316280304Sjkim        ret->length = 0;
317280304Sjkim        if (data != NULL)
318280304Sjkim            OPENSSL_free(data);
319280304Sjkim        data = (unsigned char *)OPENSSL_malloc(length);
320280304Sjkim        if (data == NULL) {
321280304Sjkim            i = ERR_R_MALLOC_FAILURE;
322280304Sjkim            goto err;
323280304Sjkim        }
324280304Sjkim        ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
325280304Sjkim    }
326280304Sjkim    memcpy(data, p, length);
327280304Sjkim    /* reattach data to object, after which it remains const */
328280304Sjkim    ret->data = data;
329280304Sjkim    ret->length = length;
330280304Sjkim    ret->sn = NULL;
331280304Sjkim    ret->ln = NULL;
332280304Sjkim    /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
333280304Sjkim    p += length;
33455714Skris
335280304Sjkim    if (a != NULL)
336280304Sjkim        (*a) = ret;
337280304Sjkim    *pp = p;
338280304Sjkim    return (ret);
339280304Sjkim err:
340280304Sjkim    ASN1err(ASN1_F_C2I_ASN1_OBJECT, i);
341280304Sjkim    if ((ret != NULL) && ((a == NULL) || (*a != ret)))
342280304Sjkim        ASN1_OBJECT_free(ret);
343280304Sjkim    return (NULL);
344280304Sjkim}
34555714Skris
34655714SkrisASN1_OBJECT *ASN1_OBJECT_new(void)
347280304Sjkim{
348280304Sjkim    ASN1_OBJECT *ret;
34955714Skris
350280304Sjkim    ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
351280304Sjkim    if (ret == NULL) {
352280304Sjkim        ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
353280304Sjkim        return (NULL);
354280304Sjkim    }
355280304Sjkim    ret->length = 0;
356280304Sjkim    ret->data = NULL;
357280304Sjkim    ret->nid = 0;
358280304Sjkim    ret->sn = NULL;
359280304Sjkim    ret->ln = NULL;
360280304Sjkim    ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
361280304Sjkim    return (ret);
362280304Sjkim}
36355714Skris
36455714Skrisvoid ASN1_OBJECT_free(ASN1_OBJECT *a)
365280304Sjkim{
366280304Sjkim    if (a == NULL)
367280304Sjkim        return;
368280304Sjkim    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
369280304Sjkim#ifndef CONST_STRICT            /* disable purely for compile-time strict
370280304Sjkim                                 * const checking. Doing this on a "real"
371280304Sjkim                                 * compile will cause memory leaks */
372280304Sjkim        if (a->sn != NULL)
373280304Sjkim            OPENSSL_free((void *)a->sn);
374280304Sjkim        if (a->ln != NULL)
375280304Sjkim            OPENSSL_free((void *)a->ln);
37655714Skris#endif
377280304Sjkim        a->sn = a->ln = NULL;
378280304Sjkim    }
379280304Sjkim    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
380280304Sjkim        if (a->data != NULL)
381280304Sjkim            OPENSSL_free((void *)a->data);
382280304Sjkim        a->data = NULL;
383280304Sjkim        a->length = 0;
384280304Sjkim    }
385280304Sjkim    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
386280304Sjkim        OPENSSL_free(a);
387280304Sjkim}
38855714Skris
38955714SkrisASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
390280304Sjkim                                const char *sn, const char *ln)
391280304Sjkim{
392280304Sjkim    ASN1_OBJECT o;
39355714Skris
394280304Sjkim    o.sn = sn;
395280304Sjkim    o.ln = ln;
396280304Sjkim    o.data = data;
397280304Sjkim    o.nid = nid;
398280304Sjkim    o.length = len;
399280304Sjkim    o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
400280304Sjkim        ASN1_OBJECT_FLAG_DYNAMIC_DATA;
401280304Sjkim    return (OBJ_dup(&o));
402280304Sjkim}
40355714Skris
40455714SkrisIMPLEMENT_STACK_OF(ASN1_OBJECT)
405280304Sjkim
40655714SkrisIMPLEMENT_ASN1_SET_OF(ASN1_OBJECT)
407