xref: /openbsd-src/lib/libcrypto/objects/obj_dat.c (revision 5b37fcf34e412bf0b6ad32ddb294e900d64c5855)
1 /* crypto/objects/obj_dat.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 <ctype.h>
61 #include "cryptlib.h"
62 #include "lhash.h"
63 #include "asn1.h"
64 #include "objects.h"
65 
66 /* obj_dat.h is generated from objects.h by obj_dat.pl */
67 #include "obj_dat.h"
68 
69 #ifndef NOPROTO
70 static int sn_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b);
71 static int ln_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b);
72 static int obj_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b);
73 #else
74 static int sn_cmp();
75 static int ln_cmp();
76 static int obj_cmp();
77 #endif
78 
79 #define ADDED_DATA	0
80 #define ADDED_SNAME	1
81 #define ADDED_LNAME	2
82 #define ADDED_NID	3
83 
84 typedef struct added_obj_st
85 	{
86 	int type;
87 	ASN1_OBJECT *obj;
88 	} ADDED_OBJ;
89 
90 static int new_nid=NUM_NID;
91 static LHASH *added=NULL;
92 
93 static int sn_cmp(ap,bp)
94 ASN1_OBJECT **ap;
95 ASN1_OBJECT **bp;
96 	{ return(strcmp((*ap)->sn,(*bp)->sn)); }
97 
98 static int ln_cmp(ap,bp)
99 ASN1_OBJECT **ap;
100 ASN1_OBJECT **bp;
101 	{ return(strcmp((*ap)->ln,(*bp)->ln)); }
102 
103 static unsigned long add_hash(ca)
104 ADDED_OBJ *ca;
105 	{
106 	ASN1_OBJECT *a;
107 	int i;
108 	unsigned long ret=0;
109 	unsigned char *p;
110 
111 	a=ca->obj;
112 	switch (ca->type)
113 		{
114 	case ADDED_DATA:
115 		ret=a->length<<20L;
116 		p=(unsigned char *)a->data;
117 		for (i=0; i<a->length; i++)
118 			ret^=p[i]<<((i*3)%24);
119 		break;
120 	case ADDED_SNAME:
121 		ret=lh_strhash(a->sn);
122 		break;
123 	case ADDED_LNAME:
124 		ret=lh_strhash(a->ln);
125 		break;
126 	case ADDED_NID:
127 		ret=a->nid;
128 		break;
129 	default:
130 		abort();
131 		}
132 	ret&=0x3fffffffL;
133 	ret|=ca->type<<30L;
134 	return(ret);
135 	}
136 
137 static int add_cmp(ca,cb)
138 ADDED_OBJ *ca,*cb;
139 	{
140 	ASN1_OBJECT *a,*b;
141 	int i;
142 
143 	i=ca->type-cb->type;
144 	if (i) return(i);
145 	a=ca->obj;
146 	b=cb->obj;
147 	switch (ca->type)
148 		{
149 	case ADDED_DATA:
150 		i=(a->length - b->length);
151 		if (i) return(i);
152 		return(memcmp(a->data,b->data,a->length));
153 	case ADDED_SNAME:
154 		if (a->sn == NULL) return(-1);
155 		else if (b->sn == NULL) return(1);
156 		else return(strcmp(a->sn,b->sn));
157 	case ADDED_LNAME:
158 		if (a->ln == NULL) return(-1);
159 		else if (b->ln == NULL) return(1);
160 		else return(strcmp(a->ln,b->ln));
161 	case ADDED_NID:
162 		return(a->nid-b->nid);
163 	default:
164 		abort();
165 		}
166 	}
167 
168 static int init_added()
169 	{
170 	if (added != NULL) return(1);
171 	added=lh_new(add_hash,add_cmp);
172 	return(added != NULL);
173 	}
174 
175 static void cleanup1(a)
176 ADDED_OBJ *a;
177 	{
178 	a->obj->nid=0;
179 	a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC|
180 	                ASN1_OBJECT_FLAG_DYNAMIC_STRINGS;
181 	}
182 
183 static void cleanup2(a)
184 ADDED_OBJ *a;
185 	{ a->obj->nid++; }
186 
187 static void cleanup3(a)
188 ADDED_OBJ *a;
189 	{
190 	if (--a->obj->nid == 0)
191 		ASN1_OBJECT_free(a->obj);
192 	Free(a);
193 	}
194 
195 void OBJ_cleanup()
196 	{
197 	if (added == NULL) return;
198 	added->down_load=0;
199 	lh_doall(added,cleanup1); /* zero counters */
200 	lh_doall(added,cleanup2); /* set counters */
201 	lh_doall(added,cleanup3); /* free objects */
202 	lh_free(added);
203 	added=NULL;
204 	}
205 
206 int OBJ_new_nid(num)
207 int num;
208 	{
209 	int i;
210 
211 	i=new_nid;
212 	new_nid+=num;
213 	return(i);
214 	}
215 
216 int OBJ_add_object(obj)
217 ASN1_OBJECT *obj;
218 	{
219 	ASN1_OBJECT *o;
220 	ADDED_OBJ *ao[4],*aop;
221 	int i;
222 
223 	if (added == NULL)
224 		if (!init_added()) return(0);
225 	if ((o=OBJ_dup(obj)) == NULL) goto err;
226 	ao[ADDED_DATA]=NULL;
227 	ao[ADDED_SNAME]=NULL;
228 	ao[ADDED_LNAME]=NULL;
229 	ao[ADDED_NID]=NULL;
230 	ao[ADDED_NID]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ));
231 	if ((o->length != 0) && (obj->data != NULL))
232 		ao[ADDED_DATA]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ));
233 	if (o->sn != NULL)
234 		ao[ADDED_SNAME]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ));
235 	if (o->ln != NULL)
236 		ao[ADDED_LNAME]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ));
237 
238 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
239 		{
240 		if (ao[i] != NULL)
241 			{
242 			ao[i]->type=i;
243 			ao[i]->obj=o;
244 			aop=(ADDED_OBJ *)lh_insert(added,(char *)ao[i]);
245 			/* memory leak, buit should not normally matter */
246 			if (aop != NULL)
247 				Free(aop);
248 			}
249 		}
250 	o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS);
251 	return(o->nid);
252 err:
253 	for (i=ADDED_DATA; i<=ADDED_NID; i++)
254 		if (ao[i] != NULL) Free(ao[i]);
255 	if (o != NULL) Free(o);
256 	return(NID_undef);
257 	}
258 
259 ASN1_OBJECT *OBJ_nid2obj(n)
260 int n;
261 	{
262 	ADDED_OBJ ad,*adp;
263 	ASN1_OBJECT ob;
264 
265 	if ((n >= 0) && (n < NUM_NID))
266 		{
267 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
268 			{
269 			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
270 			return(NULL);
271 			}
272 		return((ASN1_OBJECT *)&(nid_objs[n]));
273 		}
274 	else if (added == NULL)
275 		return(NULL);
276 	else
277 		{
278 		ad.type=ADDED_NID;
279 		ad.obj= &ob;
280 		ob.nid=n;
281 		adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad);
282 		if (adp != NULL)
283 			return(adp->obj);
284 		else
285 			{
286 			OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID);
287 			return(NULL);
288 			}
289 		}
290 	}
291 
292 char *OBJ_nid2sn(n)
293 int n;
294 	{
295 	ADDED_OBJ ad,*adp;
296 	ASN1_OBJECT ob;
297 
298 	if ((n >= 0) && (n < NUM_NID))
299 		{
300 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
301 			{
302 			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
303 			return(NULL);
304 			}
305 		return(nid_objs[n].sn);
306 		}
307 	else if (added == NULL)
308 		return(NULL);
309 	else
310 		{
311 		ad.type=ADDED_NID;
312 		ad.obj= &ob;
313 		ob.nid=n;
314 		adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad);
315 		if (adp != NULL)
316 			return(adp->obj->sn);
317 		else
318 			{
319 			OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID);
320 			return(NULL);
321 			}
322 		}
323 	}
324 
325 char *OBJ_nid2ln(n)
326 int n;
327 	{
328 	ADDED_OBJ ad,*adp;
329 	ASN1_OBJECT ob;
330 
331 	if ((n >= 0) && (n < NUM_NID))
332 		{
333 		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef))
334 			{
335 			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
336 			return(NULL);
337 			}
338 		return(nid_objs[n].ln);
339 		}
340 	else if (added == NULL)
341 		return(NULL);
342 	else
343 		{
344 		ad.type=ADDED_NID;
345 		ad.obj= &ob;
346 		ob.nid=n;
347 		adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad);
348 		if (adp != NULL)
349 			return(adp->obj->ln);
350 		else
351 			{
352 			OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID);
353 			return(NULL);
354 			}
355 		}
356 	}
357 
358 int OBJ_obj2nid(a)
359 ASN1_OBJECT *a;
360 	{
361 	ASN1_OBJECT **op;
362 	ADDED_OBJ ad,*adp;
363 
364 	if (a == NULL)
365 		return(NID_undef);
366 	if (a->nid != 0)
367 		return(a->nid);
368 
369 	if (added != NULL)
370 		{
371 		ad.type=ADDED_DATA;
372 		ad.obj=a;
373 		adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad);
374 		if (adp != NULL) return (adp->obj->nid);
375 		}
376 	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&a,(char *)obj_objs,NUM_OBJ,
377 		sizeof(ASN1_OBJECT *),(int (*)())obj_cmp);
378 	if (op == NULL)
379 		return(NID_undef);
380 	return((*op)->nid);
381 	}
382 
383 int OBJ_txt2nid(s)
384 char *s;
385 	{
386 	int ret;
387 
388 	ret=OBJ_sn2nid(s);
389 	if (ret == NID_undef)
390 		{
391 		ret=OBJ_ln2nid(s);
392 		if (ret == NID_undef)
393 			{
394 			ASN1_OBJECT *op=NULL;
395 			unsigned char *buf,*p;
396 			int i;
397 
398 			i=a2d_ASN1_OBJECT(NULL,0,s,-1);
399 			if (i <= 0)
400 				{
401 				/* clear the error */
402 				ERR_get_error();
403 				return(0);
404 				}
405 
406 			if ((buf=(unsigned char *)Malloc(i)) == NULL)
407 				return(NID_undef);
408 			a2d_ASN1_OBJECT(buf,i,s,-1);
409 			p=buf;
410 			op=d2i_ASN1_OBJECT(NULL,&p,i);
411 			if (op == NULL) return(NID_undef);
412 			ret=OBJ_obj2nid(op);
413 			ASN1_OBJECT_free(op);
414 			Free(buf);
415 			}
416 		}
417 	return(ret);
418 	}
419 
420 int OBJ_ln2nid(s)
421 char *s;
422 	{
423 	ASN1_OBJECT o,*oo= &o,**op;
424 	ADDED_OBJ ad,*adp;
425 
426 	o.ln=s;
427 	if (added != NULL)
428 		{
429 		ad.type=ADDED_LNAME;
430 		ad.obj= &o;
431 		adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad);
432 		if (adp != NULL) return (adp->obj->nid);
433 		}
434 	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)ln_objs,NUM_LN,
435 		sizeof(ASN1_OBJECT *),(int (*)())ln_cmp);
436 	if (op == NULL) return(NID_undef);
437 	return((*op)->nid);
438 	}
439 
440 int OBJ_sn2nid(s)
441 char *s;
442 	{
443 	ASN1_OBJECT o,*oo= &o,**op;
444 	ADDED_OBJ ad,*adp;
445 
446 	o.sn=s;
447 	if (added != NULL)
448 		{
449 		ad.type=ADDED_SNAME;
450 		ad.obj= &o;
451 		adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad);
452 		if (adp != NULL) return (adp->obj->nid);
453 		}
454 	op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)sn_objs,NUM_SN,
455 		sizeof(ASN1_OBJECT *),(int (*)())sn_cmp);
456 	if (op == NULL) return(NID_undef);
457 	return((*op)->nid);
458 	}
459 
460 static int obj_cmp(ap, bp)
461 ASN1_OBJECT **ap;
462 ASN1_OBJECT **bp;
463 	{
464 	int j;
465 	ASN1_OBJECT *a= *ap;
466 	ASN1_OBJECT *b= *bp;
467 
468 	j=(a->length - b->length);
469         if (j) return(j);
470 	return(memcmp(a->data,b->data,a->length));
471         }
472 
473 char *OBJ_bsearch(key,base,num,size,cmp)
474 char *key;
475 char *base;
476 int num;
477 int size;
478 int (*cmp)();
479 	{
480 	int l,h,i,c;
481 	char *p;
482 
483 	if (num == 0) return(NULL);
484 	l=0;
485 	h=num;
486 	while (l < h)
487 		{
488 		i=(l+h)/2;
489 		p= &(base[i*size]);
490 		c=(*cmp)(key,p);
491 		if (c < 0)
492 			h=i;
493 		else if (c > 0)
494 			l=i+1;
495 		else
496 			return(p);
497 		}
498 	return(NULL);
499 	}
500 
501 int OBJ_create_objects(in)
502 BIO *in;
503 	{
504 	MS_STATIC char buf[512];
505 	int i,num= -1;
506 	char *o,*s,*l=NULL;
507 
508 	for (;;)
509 		{
510 		s=o=NULL;
511 		i=BIO_gets(in,buf,512);
512 		if (i <= 0) return(num);
513 		buf[i-1]='\0';
514 		if (!isalnum(buf[0])) return(num);
515 		o=s=buf;
516 		while (isdigit(*s) || (*s == '.'))
517 			s++;
518 		if (*s != '\0')
519 			{
520 			*(s++)='\0';
521 			while (isspace(*s))
522 				s++;
523 			if (*s == '\0')
524 				s=NULL;
525 			else
526 				{
527 				l=s;
528 				while ((*l != '\0') && !isspace(*l))
529 					l++;
530 				if (*l != '\0')
531 					{
532 					*(l++)='\0';
533 					while (isspace(*l))
534 						l++;
535 					if (*l == '\0') l=NULL;
536 					}
537 				else
538 					l=NULL;
539 				}
540 			}
541 		else
542 			s=NULL;
543 		if ((o == NULL) || (*o == '\0')) return(num);
544 		if (!OBJ_create(o,s,l)) return(num);
545 		num++;
546 		}
547 	return(num);
548 	}
549 
550 int OBJ_create(oid,sn,ln)
551 char *oid;
552 char *sn;
553 char *ln;
554 	{
555 	int ok=0;
556 	ASN1_OBJECT *op=NULL;
557 	unsigned char *buf;
558 	int i;
559 
560 	i=a2d_ASN1_OBJECT(NULL,0,oid,-1);
561 	if (i <= 0) return(0);
562 
563 	if ((buf=(unsigned char *)Malloc(i)) == NULL)
564 		{
565 		OBJerr(OBJ_F_OBJ_CREATE,OBJ_R_MALLOC_FAILURE);
566 		return(0);
567 		}
568 	i=a2d_ASN1_OBJECT(buf,i,oid,-1);
569 	op=(ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1),buf,i,sn,ln);
570 	if (op == NULL)
571 		goto err;
572 	ok=OBJ_add_object(op);
573 err:
574 	ASN1_OBJECT_free(op);
575 	Free((char *)buf);
576 	return(ok);
577 	}
578 
579