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