Line data Source code
1 : /* crypto/asn1/a_set.c */
2 : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 : * All rights reserved.
4 : *
5 : * This package is an SSL implementation written
6 : * by Eric Young (eay@cryptsoft.com).
7 : * The implementation was written so as to conform with Netscapes SSL.
8 : *
9 : * This library is free for commercial and non-commercial use as long as
10 : * the following conditions are aheared to. The following conditions
11 : * apply to all code found in this distribution, be it the RC4, RSA,
12 : * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 : * included with this distribution is covered by the same copyright terms
14 : * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 : *
16 : * Copyright remains Eric Young's, and as such any Copyright notices in
17 : * the code are not to be removed.
18 : * If this package is used in a product, Eric Young should be given attribution
19 : * as the author of the parts of the library used.
20 : * This can be in the form of a textual message at program startup or
21 : * in documentation (online or textual) provided with the package.
22 : *
23 : * Redistribution and use in source and binary forms, with or without
24 : * modification, are permitted provided that the following conditions
25 : * are met:
26 : * 1. Redistributions of source code must retain the copyright
27 : * notice, this list of conditions and the following disclaimer.
28 : * 2. Redistributions in binary form must reproduce the above copyright
29 : * notice, this list of conditions and the following disclaimer in the
30 : * documentation and/or other materials provided with the distribution.
31 : * 3. All advertising materials mentioning features or use of this software
32 : * must display the following acknowledgement:
33 : * "This product includes cryptographic software written by
34 : * Eric Young (eay@cryptsoft.com)"
35 : * The word 'cryptographic' can be left out if the rouines from the library
36 : * being used are not cryptographic related :-).
37 : * 4. If you include any Windows specific code (or a derivative thereof) from
38 : * the apps directory (application code) you must include an acknowledgement:
39 : * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 : *
41 : * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 : * SUCH DAMAGE.
52 : *
53 : * The licence and distribution terms for any publically available version or
54 : * derivative of this code cannot be changed. i.e. this code cannot simply be
55 : * copied and put under another distribution licence
56 : * [including the GNU Public Licence.]
57 : */
58 :
59 : #include <stdio.h>
60 : #include "cryptlib.h"
61 : #include <openssl/asn1_mac.h>
62 :
63 : #ifndef NO_ASN1_OLD
64 :
65 : typedef struct {
66 : unsigned char *pbData;
67 : int cbData;
68 : } MYBLOB;
69 :
70 : /*
71 : * SetBlobCmp This function compares two elements of SET_OF block
72 : */
73 0 : static int SetBlobCmp(const void *elem1, const void *elem2)
74 : {
75 : const MYBLOB *b1 = (const MYBLOB *)elem1;
76 : const MYBLOB *b2 = (const MYBLOB *)elem2;
77 : int r;
78 :
79 0 : r = memcmp(b1->pbData, b2->pbData,
80 0 : b1->cbData < b2->cbData ? b1->cbData : b2->cbData);
81 0 : if (r != 0)
82 : return r;
83 0 : return b1->cbData - b2->cbData;
84 : }
85 :
86 : /*
87 : * int is_set: if TRUE, then sort the contents (i.e. it isn't a SEQUENCE)
88 : */
89 0 : int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp,
90 : i2d_of_void *i2d, int ex_tag, int ex_class, int is_set)
91 : {
92 : int ret = 0, r;
93 : int i;
94 : unsigned char *p;
95 : unsigned char *pStart, *pTempMem;
96 : MYBLOB *rgSetBlob;
97 : int totSize;
98 :
99 0 : if (a == NULL)
100 : return (0);
101 0 : for (i = sk_OPENSSL_BLOCK_num(a) - 1; i >= 0; i--)
102 0 : ret += i2d(sk_OPENSSL_BLOCK_value(a, i), NULL);
103 0 : r = ASN1_object_size(1, ret, ex_tag);
104 0 : if (pp == NULL)
105 : return (r);
106 :
107 0 : p = *pp;
108 0 : ASN1_put_object(&p, 1, ret, ex_tag, ex_class);
109 :
110 : /* Modified by gp@nsj.co.jp */
111 : /* And then again by Ben */
112 : /* And again by Steve */
113 :
114 0 : if (!is_set || (sk_OPENSSL_BLOCK_num(a) < 2)) {
115 0 : for (i = 0; i < sk_OPENSSL_BLOCK_num(a); i++)
116 0 : i2d(sk_OPENSSL_BLOCK_value(a, i), &p);
117 :
118 0 : *pp = p;
119 0 : return (r);
120 : }
121 :
122 0 : pStart = p; /* Catch the beg of Setblobs */
123 : /* In this array we will store the SET blobs */
124 0 : rgSetBlob = OPENSSL_malloc(sk_OPENSSL_BLOCK_num(a) * sizeof(MYBLOB));
125 0 : if (rgSetBlob == NULL) {
126 0 : ASN1err(ASN1_F_I2D_ASN1_SET, ERR_R_MALLOC_FAILURE);
127 0 : return (0);
128 : }
129 :
130 0 : for (i = 0; i < sk_OPENSSL_BLOCK_num(a); i++) {
131 0 : rgSetBlob[i].pbData = p; /* catch each set encode blob */
132 0 : i2d(sk_OPENSSL_BLOCK_value(a, i), &p);
133 0 : rgSetBlob[i].cbData = p - rgSetBlob[i].pbData; /* Length of this
134 : * SetBlob */
135 : }
136 0 : *pp = p;
137 0 : totSize = p - pStart; /* This is the total size of all set blobs */
138 :
139 : /*
140 : * Now we have to sort the blobs. I am using a simple algo. *Sort ptrs
141 : * *Copy to temp-mem *Copy from temp-mem to user-mem
142 : */
143 0 : qsort(rgSetBlob, sk_OPENSSL_BLOCK_num(a), sizeof(MYBLOB), SetBlobCmp);
144 0 : if (!(pTempMem = OPENSSL_malloc(totSize))) {
145 0 : ASN1err(ASN1_F_I2D_ASN1_SET, ERR_R_MALLOC_FAILURE);
146 0 : return (0);
147 : }
148 :
149 : /* Copy to temp mem */
150 0 : p = pTempMem;
151 0 : for (i = 0; i < sk_OPENSSL_BLOCK_num(a); ++i) {
152 0 : memcpy(p, rgSetBlob[i].pbData, rgSetBlob[i].cbData);
153 0 : p += rgSetBlob[i].cbData;
154 : }
155 :
156 : /* Copy back to user mem*/
157 0 : memcpy(pStart, pTempMem, totSize);
158 0 : OPENSSL_free(pTempMem);
159 0 : OPENSSL_free(rgSetBlob);
160 :
161 0 : return (r);
162 : }
163 :
164 0 : STACK_OF(OPENSSL_BLOCK) *d2i_ASN1_SET(STACK_OF(OPENSSL_BLOCK) **a,
165 : const unsigned char **pp,
166 : long length, d2i_of_void *d2i,
167 : void (*free_func) (OPENSSL_BLOCK),
168 : int ex_tag, int ex_class)
169 : {
170 : ASN1_const_CTX c;
171 : STACK_OF(OPENSSL_BLOCK) *ret = NULL;
172 :
173 0 : if ((a == NULL) || ((*a) == NULL)) {
174 0 : if ((ret = sk_OPENSSL_BLOCK_new_null()) == NULL) {
175 0 : ASN1err(ASN1_F_D2I_ASN1_SET, ERR_R_MALLOC_FAILURE);
176 0 : goto err;
177 : }
178 : } else
179 : ret = (*a);
180 :
181 0 : c.p = *pp;
182 0 : c.max = (length == 0) ? 0 : (c.p + length);
183 :
184 0 : c.inf = ASN1_get_object(&c.p, &c.slen, &c.tag, &c.xclass, c.max - c.p);
185 0 : if (c.inf & 0x80)
186 : goto err;
187 0 : if (ex_class != c.xclass) {
188 0 : ASN1err(ASN1_F_D2I_ASN1_SET, ASN1_R_BAD_CLASS);
189 0 : goto err;
190 : }
191 0 : if (ex_tag != c.tag) {
192 0 : ASN1err(ASN1_F_D2I_ASN1_SET, ASN1_R_BAD_TAG);
193 0 : goto err;
194 : }
195 0 : if ((c.slen + c.p) > c.max) {
196 0 : ASN1err(ASN1_F_D2I_ASN1_SET, ASN1_R_LENGTH_ERROR);
197 0 : goto err;
198 : }
199 : /*
200 : * check for infinite constructed - it can be as long as the amount of
201 : * data passed to us
202 : */
203 0 : if (c.inf == (V_ASN1_CONSTRUCTED + 1))
204 0 : c.slen = length + *pp - c.p;
205 0 : c.max = c.p + c.slen;
206 :
207 0 : while (c.p < c.max) {
208 : char *s;
209 :
210 0 : if (M_ASN1_D2I_end_sequence())
211 : break;
212 : /*
213 : * XXX: This was called with 4 arguments, incorrectly, it seems if
214 : * ((s=func(NULL,&c.p,c.slen,c.max-c.p)) == NULL)
215 : */
216 0 : if ((s = d2i(NULL, &c.p, c.slen)) == NULL) {
217 0 : ASN1err(ASN1_F_D2I_ASN1_SET, ASN1_R_ERROR_PARSING_SET_ELEMENT);
218 0 : asn1_add_error(*pp, (int)(c.p - *pp));
219 0 : goto err;
220 : }
221 0 : if (!sk_OPENSSL_BLOCK_push(ret, s))
222 : goto err;
223 : }
224 0 : if (a != NULL)
225 0 : (*a) = ret;
226 0 : *pp = c.p;
227 0 : return (ret);
228 : err:
229 0 : if ((ret != NULL) && ((a == NULL) || (*a != ret))) {
230 0 : if (free_func != NULL)
231 0 : sk_OPENSSL_BLOCK_pop_free(ret, free_func);
232 : else
233 0 : sk_OPENSSL_BLOCK_free(ret);
234 : }
235 : return (NULL);
236 : }
237 :
238 : #endif
|