Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / boringssl / src / crypto / obj / obj.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.] */
56
57 #include <openssl/obj.h>
58
59 #include <limits.h>
60
61 #include <openssl/asn1.h>
62 #include <openssl/buf.h>
63 #include <openssl/bytestring.h>
64 #include <openssl/err.h>
65 #include <openssl/lhash.h>
66 #include <openssl/mem.h>
67 #include <openssl/thread.h>
68
69 #include "obj_dat.h"
70
71 /* These globals are protected by CRYPTO_LOCK_OBJ. */
72 static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
73 static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL;
74 static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL;
75 static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
76
77 static unsigned global_next_nid = NUM_NID;
78
79 static int obj_next_nid(void) {
80   int ret;
81
82   CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
83   ret = global_next_nid++;
84   CRYPTO_w_unlock(CRYPTO_LOCK_OBJ);
85
86   return ret;
87 }
88
89 ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
90   ASN1_OBJECT *r;
91   unsigned char *data = NULL;
92   char *sn = NULL, *ln = NULL;
93
94   if (o == NULL) {
95     return NULL;
96   }
97
98   if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
99     /* TODO(fork): this is a little dangerous. */
100     return (ASN1_OBJECT *)o;
101   }
102
103   r = ASN1_OBJECT_new();
104   if (r == NULL) {
105     OPENSSL_PUT_ERROR(OBJ, OBJ_dup, ERR_R_ASN1_LIB);
106     return NULL;
107   }
108   r->ln = r->sn = NULL;
109
110   data = OPENSSL_malloc(o->length);
111   if (data == NULL) {
112     goto err;
113   }
114   if (o->data != NULL) {
115     memcpy(data, o->data, o->length);
116   }
117
118   /* once data is attached to an object, it remains const */
119   r->data = data;
120   r->length = o->length;
121   r->nid = o->nid;
122
123   if (o->ln != NULL) {
124     ln = OPENSSL_strdup(o->ln);
125     if (ln == NULL) {
126       goto err;
127     }
128   }
129
130   if (o->sn != NULL) {
131     sn = OPENSSL_strdup(o->sn);
132     if (sn) {
133       goto err;
134     }
135   }
136
137   r->sn = sn;
138   r->ln = ln;
139
140   r->flags =
141       o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
142                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
143   return r;
144
145 err:
146   OPENSSL_PUT_ERROR(OBJ, OBJ_dup, ERR_R_MALLOC_FAILURE);
147   if (ln != NULL) {
148     OPENSSL_free(ln);
149   }
150   if (sn != NULL) {
151     OPENSSL_free(sn);
152   }
153   if (data != NULL) {
154     OPENSSL_free(data);
155   }
156   OPENSSL_free(r);
157   return NULL;
158 }
159
160 int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
161   int ret;
162
163   ret = a->length - b->length;
164   if (ret) {
165     return ret;
166   }
167   return memcmp(a->data, b->data, a->length);
168 }
169
170 /* nids_cmp is called to search the kNIDsInOIDOrder array. The |key| argument
171  * is an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
172  * unsigned int in the array. */
173 static int obj_cmp(const void *key, const void *element) {
174   int j;
175   unsigned nid = *((unsigned*) element);
176   const ASN1_OBJECT *a = key;
177   const ASN1_OBJECT *b = &kObjects[nid];
178
179   j = a->length - b->length;
180   if (j) {
181     return j;
182   }
183   return memcmp(a->data, b->data, a->length);
184 }
185
186 int OBJ_obj2nid(const ASN1_OBJECT *obj) {
187   const unsigned int *nid_ptr;
188
189   if (obj == NULL) {
190     return NID_undef;
191   }
192
193   if (obj->nid != 0) {
194     return obj->nid;
195   }
196
197   CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
198   if (global_added_by_data != NULL) {
199     ASN1_OBJECT *match;
200
201     match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
202     if (match != NULL) {
203       CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
204       return match->nid;
205     }
206   }
207   CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
208
209   nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp);
210   if (nid_ptr == NULL) {
211     return NID_undef;
212   }
213
214   return kObjects[*nid_ptr].nid;
215 }
216
217 int OBJ_cbs2nid(const CBS *cbs) {
218   ASN1_OBJECT obj;
219   memset(&obj, 0, sizeof(obj));
220   obj.data = CBS_data(cbs);
221   obj.length = CBS_len(cbs);
222
223   return OBJ_obj2nid(&obj);
224 }
225
226 /* short_name_cmp is called to search the kNIDsInShortNameOrder array. The
227  * |key| argument is name that we're looking for and |element| is a pointer to
228  * an unsigned int in the array. */
229 static int short_name_cmp(const void *key, const void *element) {
230   const char *name = (const char *) key;
231   unsigned nid = *((unsigned*) element);
232
233   return strcmp(name, kObjects[nid].sn);
234 }
235
236 int OBJ_sn2nid(const char *short_name) {
237   const unsigned int *nid_ptr;
238
239   CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
240   if (global_added_by_short_name != NULL) {
241     ASN1_OBJECT *match, template;
242
243     template.sn = short_name;
244     match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
245     if (match != NULL) {
246       CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
247       return match->nid;
248     }
249   }
250   CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
251
252   nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp);
253   if (nid_ptr == NULL) {
254     return NID_undef;
255   }
256
257   return kObjects[*nid_ptr].nid;
258 }
259
260 /* long_name_cmp is called to search the kNIDsInLongNameOrder array. The
261  * |key| argument is name that we're looking for and |element| is a pointer to
262  * an unsigned int in the array. */
263 static int long_name_cmp(const void *key, const void *element) {
264   const char *name = (const char *) key;
265   unsigned nid = *((unsigned*) element);
266
267   return strcmp(name, kObjects[nid].ln);
268 }
269
270 int OBJ_ln2nid(const char *long_name) {
271   const unsigned int *nid_ptr;
272
273   CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
274   if (global_added_by_long_name != NULL) {
275     ASN1_OBJECT *match, template;
276
277     template.ln = long_name;
278     match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
279     if (match != NULL) {
280       CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
281       return match->nid;
282     }
283   }
284   CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
285
286   nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp);
287   if (nid_ptr == NULL) {
288     return NID_undef;
289   }
290
291   return kObjects[*nid_ptr].nid;
292 }
293
294 int OBJ_txt2nid(const char *s) {
295   ASN1_OBJECT *obj;
296   int nid;
297
298   obj = OBJ_txt2obj(s, 0 /* search names */);
299   nid = OBJ_obj2nid(obj);
300   ASN1_OBJECT_free(obj);
301   return nid;
302 }
303
304 OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) {
305   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
306   CBB oid;
307
308   if (obj == NULL ||
309       !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) ||
310       !CBB_add_bytes(&oid, obj->data, obj->length) ||
311       !CBB_flush(out)) {
312     return 0;
313   }
314
315   return 1;
316 }
317
318 const ASN1_OBJECT *OBJ_nid2obj(int nid) {
319   if (nid >= 0 && nid < NUM_NID) {
320     if (nid != NID_undef && kObjects[nid].nid == NID_undef) {
321       goto err;
322     }
323     return &kObjects[nid];
324   }
325
326   CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
327   if (global_added_by_nid != NULL) {
328     ASN1_OBJECT *match, template;
329
330     template.nid = nid;
331     match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
332     if (match != NULL) {
333       CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
334       return match;
335     }
336   }
337   CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
338
339 err:
340   OPENSSL_PUT_ERROR(OBJ, OBJ_nid2obj, OBJ_R_UNKNOWN_NID);
341   return NULL;
342 }
343
344 const char *OBJ_nid2sn(int nid) {
345   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
346   if (obj == NULL) {
347     return NULL;
348   }
349
350   return obj->sn;
351 }
352
353 const char *OBJ_nid2ln(int nid) {
354   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
355   if (obj == NULL) {
356     return NULL;
357   }
358
359   return obj->ln;
360 }
361
362 ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) {
363   int nid = NID_undef;
364   ASN1_OBJECT *op = NULL;
365   unsigned char *buf;
366   unsigned char *p;
367   const unsigned char *bufp;
368   int contents_len, total_len;
369
370   if (!dont_search_names) {
371     nid = OBJ_sn2nid(s);
372     if (nid == NID_undef) {
373       nid = OBJ_ln2nid(s);
374     }
375
376     if (nid != NID_undef) {
377       return (ASN1_OBJECT*) OBJ_nid2obj(nid);
378     }
379   }
380
381   /* Work out size of content octets */
382   contents_len = a2d_ASN1_OBJECT(NULL, 0, s, -1);
383   if (contents_len <= 0) {
384     return NULL;
385   }
386   /* Work out total size */
387   total_len = ASN1_object_size(0, contents_len, V_ASN1_OBJECT);
388
389   buf = OPENSSL_malloc(total_len);
390   if (buf == NULL) {
391     OPENSSL_PUT_ERROR(OBJ, OBJ_txt2obj, ERR_R_MALLOC_FAILURE);
392     return NULL;
393   }
394
395   p = buf;
396   /* Write out tag+length */
397   ASN1_put_object(&p, 0, contents_len, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
398   /* Write out contents */
399   a2d_ASN1_OBJECT(p, contents_len, s, -1);
400
401   bufp = buf;
402   op = d2i_ASN1_OBJECT(NULL, &bufp, total_len);
403   OPENSSL_free(buf);
404
405   return op;
406 }
407
408 int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, int dont_return_name) {
409   int i, n = 0, len, nid, first, use_bn;
410   BIGNUM *bl;
411   unsigned long l;
412   const unsigned char *p;
413   char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
414
415   if (out && out_len > 0) {
416     out[0] = 0;
417   }
418
419   if (obj == NULL || obj->data == NULL) {
420     return 0;
421   }
422
423   if (!dont_return_name && (nid = OBJ_obj2nid(obj)) != NID_undef) {
424     const char *s;
425     s = OBJ_nid2ln(nid);
426     if (s == NULL) {
427       s = OBJ_nid2sn(nid);
428     }
429     if (s) {
430       if (out) {
431         BUF_strlcpy(out, s, out_len);
432       }
433       return strlen(s);
434     }
435   }
436
437   len = obj->length;
438   p = obj->data;
439
440   first = 1;
441   bl = NULL;
442
443   while (len > 0) {
444     l = 0;
445     use_bn = 0;
446     for (;;) {
447       unsigned char c = *p++;
448       len--;
449       if (len == 0 && (c & 0x80)) {
450         goto err;
451       }
452       if (use_bn) {
453         if (!BN_add_word(bl, c & 0x7f)) {
454           goto err;
455         }
456       } else {
457         l |= c & 0x7f;
458       }
459       if (!(c & 0x80)) {
460         break;
461       }
462       if (!use_bn && (l > (ULONG_MAX >> 7L))) {
463         if (!bl && !(bl = BN_new())) {
464           goto err;
465         }
466         if (!BN_set_word(bl, l)) {
467           goto err;
468         }
469         use_bn = 1;
470       }
471       if (use_bn) {
472         if (!BN_lshift(bl, bl, 7)) {
473           goto err;
474         }
475       } else {
476         l <<= 7L;
477       }
478     }
479
480     if (first) {
481       first = 0;
482       if (l >= 80) {
483         i = 2;
484         if (use_bn) {
485           if (!BN_sub_word(bl, 80)) {
486             goto err;
487           }
488         } else {
489           l -= 80;
490         }
491       } else {
492         i = (int)(l / 40);
493         l -= (long)(i * 40);
494       }
495       if (out && out_len > 1) {
496         *out++ = i + '0';
497         *out = '0';
498         out_len--;
499       }
500       n++;
501     }
502
503     if (use_bn) {
504       char *bndec;
505       bndec = BN_bn2dec(bl);
506       if (!bndec) {
507         goto err;
508       }
509       i = strlen(bndec);
510       if (out) {
511         if (out_len > 1) {
512           *out++ = '.';
513           *out = 0;
514           out_len--;
515         }
516         BUF_strlcpy(out, bndec, out_len);
517         if (i > out_len) {
518           out += out_len;
519           out_len = 0;
520         } else {
521           out += i;
522           out_len -= i;
523         }
524       }
525       n++;
526       n += i;
527       OPENSSL_free(bndec);
528     } else {
529       BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l);
530       i = strlen(tbuf);
531       if (out && out_len > 0) {
532         BUF_strlcpy(out, tbuf, out_len);
533         if (i > out_len) {
534           out += out_len;
535           out_len = 0;
536         } else {
537           out += i;
538           out_len -= i;
539         }
540       }
541       n += i;
542     }
543   }
544
545   if (bl) {
546     BN_free(bl);
547   }
548   return n;
549
550 err:
551   if (bl) {
552     BN_free(bl);
553   }
554   return -1;
555 }
556
557 static uint32_t hash_nid(const ASN1_OBJECT *obj) {
558   return obj->nid;
559 }
560
561 static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
562   return a->nid - b->nid;
563 }
564
565 static uint32_t hash_data(const ASN1_OBJECT *obj) {
566   return OPENSSL_hash32(obj->data, obj->length);
567 }
568
569 static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
570   int i = a->length - b->length;
571   if (i) {
572     return i;
573   }
574   return memcmp(a->data, b->data, a->length);
575 }
576
577 static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
578   return lh_strhash(obj->sn);
579 }
580
581 static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
582   return strcmp(a->sn, b->sn);
583 }
584
585 static uint32_t hash_long_name(const ASN1_OBJECT *obj) {
586   return lh_strhash(obj->ln);
587 }
588
589 static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
590   return strcmp(a->ln, b->ln);
591 }
592
593 /* obj_add_object inserts |obj| into the various global hashes for run-time
594  * added objects. It returns one on success or zero otherwise. */
595 static int obj_add_object(ASN1_OBJECT *obj) {
596   int ok;
597   ASN1_OBJECT *old_object;
598
599   obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
600                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
601
602   CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
603   if (global_added_by_nid == NULL) {
604     global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
605     global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data);
606     global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name);
607     global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name);
608   }
609
610   /* We don't pay attention to |old_object| (which contains any previous object
611    * that was evicted from the hashes) because we don't have a reference count
612    * on ASN1_OBJECT values. Also, we should never have duplicates nids and so
613    * should always have objects in |global_added_by_nid|. */
614
615   ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj);
616   if (obj->length != 0 && obj->data != NULL) {
617     ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj);
618   }
619   if (obj->sn != NULL) {
620     ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj);
621   }
622   if (obj->ln != NULL) {
623     ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
624   }
625   CRYPTO_w_unlock(CRYPTO_LOCK_OBJ);
626
627   return ok;
628 }
629
630 int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
631   int ret = NID_undef;
632   ASN1_OBJECT *op = NULL;
633   unsigned char *buf = NULL;
634   int len;
635
636   len = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
637   if (len <= 0) {
638     goto err;
639   }
640
641   buf = OPENSSL_malloc(len);
642   if (buf == NULL) {
643     OPENSSL_PUT_ERROR(OBJ, OBJ_create, ERR_R_MALLOC_FAILURE);
644     goto err;
645   }
646
647   len = a2d_ASN1_OBJECT(buf, len, oid, -1);
648   if (len == 0) {
649     goto err;
650   }
651
652   op = (ASN1_OBJECT *)ASN1_OBJECT_create(obj_next_nid(), buf, len, short_name,
653                                          long_name);
654   if (op == NULL) {
655     goto err;
656   }
657
658   if (obj_add_object(op)) {
659     ret = op->nid;
660   }
661   op = NULL;
662
663 err:
664   if (op != NULL) {
665     ASN1_OBJECT_free(op);
666   }
667   if (buf != NULL) {
668     OPENSSL_free(buf);
669   }
670
671   return ret;
672 }