1 // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <openssl/obj.h>
16 
17 #include <inttypes.h>
18 #include <limits.h>
19 #include <string.h>
20 
21 #include <openssl/asn1.h>
22 #include <openssl/bytestring.h>
23 #include <openssl/err.h>
24 #include <openssl/mem.h>
25 
26 #include "../asn1/internal.h"
27 #include "../internal.h"
28 #include "../lhash/internal.h"
29 
30 // obj_data.h must be included after the definition of |ASN1_OBJECT|.
31 #include "obj_dat.h"
32 
33 
34 DEFINE_LHASH_OF(ASN1_OBJECT)
35 
36 static CRYPTO_MUTEX global_added_lock = CRYPTO_MUTEX_INIT;
37 // These globals are protected by |global_added_lock|.
38 static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
39 static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL;
40 static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL;
41 static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
42 
43 static CRYPTO_MUTEX global_next_nid_lock = CRYPTO_MUTEX_INIT;
44 static unsigned global_next_nid = NUM_NID;
45 
obj_next_nid(void)46 static int obj_next_nid(void) {
47   CRYPTO_MUTEX_lock_write(&global_next_nid_lock);
48   int ret = global_next_nid++;
49   CRYPTO_MUTEX_unlock_write(&global_next_nid_lock);
50   return ret;
51 }
52 
OBJ_dup(const ASN1_OBJECT * o)53 ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
54   ASN1_OBJECT *r;
55   unsigned char *data = NULL;
56   char *sn = NULL, *ln = NULL;
57 
58   if (o == NULL) {
59     return NULL;
60   }
61 
62   if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
63     // TODO(fork): this is a little dangerous.
64     return (ASN1_OBJECT *)o;
65   }
66 
67   r = ASN1_OBJECT_new();
68   if (r == NULL) {
69     OPENSSL_PUT_ERROR(OBJ, ERR_R_ASN1_LIB);
70     return NULL;
71   }
72   r->ln = r->sn = NULL;
73 
74   // once data is attached to an object, it remains const
75   r->data = reinterpret_cast<uint8_t *>(OPENSSL_memdup(o->data, o->length));
76   if (o->length != 0 && r->data == NULL) {
77     goto err;
78   }
79 
80   r->length = o->length;
81   r->nid = o->nid;
82 
83   if (o->ln != NULL) {
84     ln = OPENSSL_strdup(o->ln);
85     if (ln == NULL) {
86       goto err;
87     }
88   }
89 
90   if (o->sn != NULL) {
91     sn = OPENSSL_strdup(o->sn);
92     if (sn == NULL) {
93       goto err;
94     }
95   }
96 
97   r->sn = sn;
98   r->ln = ln;
99 
100   r->flags =
101       o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
102                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
103   return r;
104 
105 err:
106   OPENSSL_free(ln);
107   OPENSSL_free(sn);
108   OPENSSL_free(data);
109   OPENSSL_free(r);
110   return NULL;
111 }
112 
OBJ_cmp(const ASN1_OBJECT * a,const ASN1_OBJECT * b)113 int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
114   if (a->length < b->length) {
115     return -1;
116   } else if (a->length > b->length) {
117     return 1;
118   }
119   return OPENSSL_memcmp(a->data, b->data, a->length);
120 }
121 
OBJ_get0_data(const ASN1_OBJECT * obj)122 const uint8_t *OBJ_get0_data(const ASN1_OBJECT *obj) {
123   if (obj == NULL) {
124     return NULL;
125   }
126 
127   return obj->data;
128 }
129 
OBJ_length(const ASN1_OBJECT * obj)130 size_t OBJ_length(const ASN1_OBJECT *obj) {
131   if (obj == NULL || obj->length < 0) {
132     return 0;
133   }
134 
135   return (size_t)obj->length;
136 }
137 
get_builtin_object(int nid)138 static const ASN1_OBJECT *get_builtin_object(int nid) {
139   // |NID_undef| is stored separately, so all the indices are off by one. The
140   // caller of this function must have a valid built-in, non-undef NID.
141   BSSL_CHECK(nid > 0 && nid < NUM_NID);
142   return &kObjects[nid - 1];
143 }
144 
145 // obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is
146 // an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
147 // unsigned int in the array.
obj_cmp(const void * key,const void * element)148 static int obj_cmp(const void *key, const void *element) {
149   uint16_t nid = *((const uint16_t *)element);
150   return OBJ_cmp(reinterpret_cast<const ASN1_OBJECT *>(key),
151                  get_builtin_object(nid));
152 }
153 
OBJ_obj2nid(const ASN1_OBJECT * obj)154 int OBJ_obj2nid(const ASN1_OBJECT *obj) {
155   if (obj == NULL) {
156     return NID_undef;
157   }
158 
159   if (obj->nid != 0) {
160     return obj->nid;
161   }
162 
163   CRYPTO_MUTEX_lock_read(&global_added_lock);
164   if (global_added_by_data != NULL) {
165     ASN1_OBJECT *match;
166 
167     match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
168     if (match != NULL) {
169       CRYPTO_MUTEX_unlock_read(&global_added_lock);
170       return match->nid;
171     }
172   }
173   CRYPTO_MUTEX_unlock_read(&global_added_lock);
174 
175   const uint16_t *nid_ptr = reinterpret_cast<const uint16_t *>(
176       bsearch(obj, kNIDsInOIDOrder, OPENSSL_ARRAY_SIZE(kNIDsInOIDOrder),
177               sizeof(kNIDsInOIDOrder[0]), obj_cmp));
178   if (nid_ptr == NULL) {
179     return NID_undef;
180   }
181 
182   return get_builtin_object(*nid_ptr)->nid;
183 }
184 
OBJ_cbs2nid(const CBS * cbs)185 int OBJ_cbs2nid(const CBS *cbs) {
186   if (CBS_len(cbs) > INT_MAX) {
187     return NID_undef;
188   }
189 
190   ASN1_OBJECT obj;
191   OPENSSL_memset(&obj, 0, sizeof(obj));
192   obj.data = CBS_data(cbs);
193   obj.length = (int)CBS_len(cbs);
194 
195   return OBJ_obj2nid(&obj);
196 }
197 
198 // short_name_cmp is called to search the kNIDsInShortNameOrder array. The
199 // |key| argument is name that we're looking for and |element| is a pointer to
200 // an unsigned int in the array.
short_name_cmp(const void * key,const void * element)201 static int short_name_cmp(const void *key, const void *element) {
202   const char *name = (const char *)key;
203   uint16_t nid = *((const uint16_t *)element);
204 
205   return strcmp(name, get_builtin_object(nid)->sn);
206 }
207 
OBJ_sn2nid(const char * short_name)208 int OBJ_sn2nid(const char *short_name) {
209   CRYPTO_MUTEX_lock_read(&global_added_lock);
210   if (global_added_by_short_name != NULL) {
211     ASN1_OBJECT *match, templ;
212 
213     templ.sn = short_name;
214     match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &templ);
215     if (match != NULL) {
216       CRYPTO_MUTEX_unlock_read(&global_added_lock);
217       return match->nid;
218     }
219   }
220   CRYPTO_MUTEX_unlock_read(&global_added_lock);
221 
222   const uint16_t *nid_ptr = reinterpret_cast<const uint16_t *>(
223       bsearch(short_name, kNIDsInShortNameOrder,
224               OPENSSL_ARRAY_SIZE(kNIDsInShortNameOrder),
225               sizeof(kNIDsInShortNameOrder[0]), short_name_cmp));
226   if (nid_ptr == NULL) {
227     return NID_undef;
228   }
229 
230   return get_builtin_object(*nid_ptr)->nid;
231 }
232 
233 // long_name_cmp is called to search the kNIDsInLongNameOrder array. The
234 // |key| argument is name that we're looking for and |element| is a pointer to
235 // an unsigned int in the array.
long_name_cmp(const void * key,const void * element)236 static int long_name_cmp(const void *key, const void *element) {
237   const char *name = (const char *)key;
238   uint16_t nid = *((const uint16_t *)element);
239 
240   return strcmp(name, get_builtin_object(nid)->ln);
241 }
242 
OBJ_ln2nid(const char * long_name)243 int OBJ_ln2nid(const char *long_name) {
244   CRYPTO_MUTEX_lock_read(&global_added_lock);
245   if (global_added_by_long_name != NULL) {
246     ASN1_OBJECT *match, templ;
247 
248     templ.ln = long_name;
249     match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &templ);
250     if (match != NULL) {
251       CRYPTO_MUTEX_unlock_read(&global_added_lock);
252       return match->nid;
253     }
254   }
255   CRYPTO_MUTEX_unlock_read(&global_added_lock);
256 
257   const uint16_t *nid_ptr = reinterpret_cast<const uint16_t *>(bsearch(
258       long_name, kNIDsInLongNameOrder, OPENSSL_ARRAY_SIZE(kNIDsInLongNameOrder),
259       sizeof(kNIDsInLongNameOrder[0]), long_name_cmp));
260   if (nid_ptr == NULL) {
261     return NID_undef;
262   }
263 
264   return get_builtin_object(*nid_ptr)->nid;
265 }
266 
OBJ_txt2nid(const char * s)267 int OBJ_txt2nid(const char *s) {
268   ASN1_OBJECT *obj;
269   int nid;
270 
271   obj = OBJ_txt2obj(s, 0 /* search names */);
272   nid = OBJ_obj2nid(obj);
273   ASN1_OBJECT_free(obj);
274   return nid;
275 }
276 
OBJ_nid2cbb(CBB * out,int nid)277 OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) {
278   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
279   return obj != NULL &&
280          CBB_add_asn1_element(out, CBS_ASN1_OBJECT, obj->data, obj->length);
281 }
282 
OBJ_get_undef(void)283 const ASN1_OBJECT *OBJ_get_undef(void) {
284   static const ASN1_OBJECT kUndef = {
285       /*sn=*/SN_undef,
286       /*ln=*/LN_undef,
287       /*nid=*/NID_undef,
288       /*length=*/0,
289       /*data=*/NULL,
290       /*flags=*/0,
291   };
292   return &kUndef;
293 }
294 
OBJ_nid2obj(int nid)295 ASN1_OBJECT *OBJ_nid2obj(int nid) {
296   if (nid == NID_undef) {
297     return (ASN1_OBJECT *)OBJ_get_undef();
298   }
299 
300   if (nid > 0 && nid < NUM_NID) {
301     const ASN1_OBJECT *obj = get_builtin_object(nid);
302     if (nid != NID_undef && obj->nid == NID_undef) {
303       goto err;
304     }
305     return (ASN1_OBJECT *)obj;
306   }
307 
308   CRYPTO_MUTEX_lock_read(&global_added_lock);
309   if (global_added_by_nid != NULL) {
310     ASN1_OBJECT *match, templ;
311 
312     templ.nid = nid;
313     match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &templ);
314     if (match != NULL) {
315       CRYPTO_MUTEX_unlock_read(&global_added_lock);
316       return match;
317     }
318   }
319   CRYPTO_MUTEX_unlock_read(&global_added_lock);
320 
321 err:
322   OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID);
323   return NULL;
324 }
325 
OBJ_nid2sn(int nid)326 const char *OBJ_nid2sn(int nid) {
327   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
328   if (obj == NULL) {
329     return NULL;
330   }
331 
332   return obj->sn;
333 }
334 
OBJ_nid2ln(int nid)335 const char *OBJ_nid2ln(int nid) {
336   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
337   if (obj == NULL) {
338     return NULL;
339   }
340 
341   return obj->ln;
342 }
343 
create_object_with_text_oid(int (* get_nid)(void),const char * oid,const char * short_name,const char * long_name)344 static ASN1_OBJECT *create_object_with_text_oid(int (*get_nid)(void),
345                                                 const char *oid,
346                                                 const char *short_name,
347                                                 const char *long_name) {
348   uint8_t *buf;
349   size_t len;
350   CBB cbb;
351   if (!CBB_init(&cbb, 32) ||
352       !CBB_add_asn1_oid_from_text(&cbb, oid, strlen(oid)) ||
353       !CBB_finish(&cbb, &buf, &len)) {
354     OPENSSL_PUT_ERROR(OBJ, OBJ_R_INVALID_OID_STRING);
355     CBB_cleanup(&cbb);
356     return NULL;
357   }
358 
359   ASN1_OBJECT *ret = ASN1_OBJECT_create(get_nid ? get_nid() : NID_undef, buf,
360                                         len, short_name, long_name);
361   OPENSSL_free(buf);
362   return ret;
363 }
364 
OBJ_txt2obj(const char * s,int dont_search_names)365 ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) {
366   if (!dont_search_names) {
367     int nid = OBJ_sn2nid(s);
368     if (nid == NID_undef) {
369       nid = OBJ_ln2nid(s);
370     }
371 
372     if (nid != NID_undef) {
373       return OBJ_nid2obj(nid);
374     }
375   }
376 
377   return create_object_with_text_oid(NULL, s, NULL, NULL);
378 }
379 
strlcpy_int(char * dst,const char * src,int dst_size)380 static int strlcpy_int(char *dst, const char *src, int dst_size) {
381   size_t ret = OPENSSL_strlcpy(dst, src, dst_size < 0 ? 0 : (size_t)dst_size);
382   if (ret > INT_MAX) {
383     OPENSSL_PUT_ERROR(OBJ, ERR_R_OVERFLOW);
384     return -1;
385   }
386   return (int)ret;
387 }
388 
OBJ_obj2txt(char * out,int out_len,const ASN1_OBJECT * obj,int always_return_oid)389 int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj,
390                 int always_return_oid) {
391   // Python depends on the empty OID successfully encoding as the empty
392   // string.
393   if (obj == NULL || obj->length == 0) {
394     return strlcpy_int(out, "", out_len);
395   }
396 
397   if (!always_return_oid) {
398     int nid = OBJ_obj2nid(obj);
399     if (nid != NID_undef) {
400       const char *name = OBJ_nid2ln(nid);
401       if (name == NULL) {
402         name = OBJ_nid2sn(nid);
403       }
404       if (name != NULL) {
405         return strlcpy_int(out, name, out_len);
406       }
407     }
408   }
409 
410   CBS cbs;
411   CBS_init(&cbs, obj->data, obj->length);
412   char *txt = CBS_asn1_oid_to_text(&cbs);
413   if (txt == NULL) {
414     if (out_len > 0) {
415       out[0] = '\0';
416     }
417     return -1;
418   }
419 
420   int ret = strlcpy_int(out, txt, out_len);
421   OPENSSL_free(txt);
422   return ret;
423 }
424 
hash_nid(const ASN1_OBJECT * obj)425 static uint32_t hash_nid(const ASN1_OBJECT *obj) { return obj->nid; }
426 
cmp_nid(const ASN1_OBJECT * a,const ASN1_OBJECT * b)427 static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
428   return a->nid - b->nid;
429 }
430 
hash_data(const ASN1_OBJECT * obj)431 static uint32_t hash_data(const ASN1_OBJECT *obj) {
432   return OPENSSL_hash32(obj->data, obj->length);
433 }
434 
hash_short_name(const ASN1_OBJECT * obj)435 static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
436   return OPENSSL_strhash(obj->sn);
437 }
438 
cmp_short_name(const ASN1_OBJECT * a,const ASN1_OBJECT * b)439 static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
440   return strcmp(a->sn, b->sn);
441 }
442 
hash_long_name(const ASN1_OBJECT * obj)443 static uint32_t hash_long_name(const ASN1_OBJECT *obj) {
444   return OPENSSL_strhash(obj->ln);
445 }
446 
cmp_long_name(const ASN1_OBJECT * a,const ASN1_OBJECT * b)447 static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
448   return strcmp(a->ln, b->ln);
449 }
450 
451 // obj_add_object inserts |obj| into the various global hashes for run-time
452 // added objects. It returns one on success or zero otherwise.
obj_add_object(ASN1_OBJECT * obj)453 static int obj_add_object(ASN1_OBJECT *obj) {
454   obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
455                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
456 
457   CRYPTO_MUTEX_lock_write(&global_added_lock);
458   if (global_added_by_nid == NULL) {
459     global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
460   }
461   if (global_added_by_data == NULL) {
462     global_added_by_data = lh_ASN1_OBJECT_new(hash_data, OBJ_cmp);
463   }
464   if (global_added_by_short_name == NULL) {
465     global_added_by_short_name =
466         lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name);
467   }
468   if (global_added_by_long_name == NULL) {
469     global_added_by_long_name =
470         lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name);
471   }
472 
473   int ok = 0;
474   if (global_added_by_nid == NULL ||         //
475       global_added_by_data == NULL ||        //
476       global_added_by_short_name == NULL ||  //
477       global_added_by_long_name == NULL) {
478     goto err;
479   }
480 
481   // We don't pay attention to |old_object| (which contains any previous object
482   // that was evicted from the hashes) because we don't have a reference count
483   // on ASN1_OBJECT values. Also, we should never have duplicates nids and so
484   // should always have objects in |global_added_by_nid|.
485   ASN1_OBJECT *old_object;
486   ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj);
487   if (obj->length != 0 && obj->data != NULL) {
488     ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj);
489   }
490   if (obj->sn != NULL) {
491     ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj);
492   }
493   if (obj->ln != NULL) {
494     ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
495   }
496 
497 err:
498   CRYPTO_MUTEX_unlock_write(&global_added_lock);
499   return ok;
500 }
501 
OBJ_create(const char * oid,const char * short_name,const char * long_name)502 int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
503   ASN1_OBJECT *op =
504       create_object_with_text_oid(obj_next_nid, oid, short_name, long_name);
505   if (op == NULL || !obj_add_object(op)) {
506     return NID_undef;
507   }
508   return op->nid;
509 }
510 
OBJ_cleanup(void)511 void OBJ_cleanup(void) {}
512