You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

555 lines
16 KiB

  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. #include <openssl/obj.h>
  57. #include <inttypes.h>
  58. #include <limits.h>
  59. #include <string.h>
  60. #include <openssl/asn1.h>
  61. #include <openssl/buf.h>
  62. #include <openssl/bytestring.h>
  63. #include <openssl/err.h>
  64. #include <openssl/lhash.h>
  65. #include <openssl/mem.h>
  66. #include <openssl/thread.h>
  67. #include "obj_dat.h"
  68. #include "../internal.h"
  69. DEFINE_LHASH_OF(ASN1_OBJECT)
  70. static struct CRYPTO_STATIC_MUTEX global_added_lock = CRYPTO_STATIC_MUTEX_INIT;
  71. // These globals are protected by |global_added_lock|.
  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. static struct CRYPTO_STATIC_MUTEX global_next_nid_lock =
  77. CRYPTO_STATIC_MUTEX_INIT;
  78. static unsigned global_next_nid = NUM_NID;
  79. static int obj_next_nid(void) {
  80. int ret;
  81. CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock);
  82. ret = global_next_nid++;
  83. CRYPTO_STATIC_MUTEX_unlock_write(&global_next_nid_lock);
  84. return ret;
  85. }
  86. ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
  87. ASN1_OBJECT *r;
  88. unsigned char *data = NULL;
  89. char *sn = NULL, *ln = NULL;
  90. if (o == NULL) {
  91. return NULL;
  92. }
  93. if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
  94. // TODO(fork): this is a little dangerous.
  95. return (ASN1_OBJECT *)o;
  96. }
  97. r = ASN1_OBJECT_new();
  98. if (r == NULL) {
  99. OPENSSL_PUT_ERROR(OBJ, ERR_R_ASN1_LIB);
  100. return NULL;
  101. }
  102. r->ln = r->sn = NULL;
  103. data = OPENSSL_malloc(o->length);
  104. if (data == NULL) {
  105. goto err;
  106. }
  107. if (o->data != NULL) {
  108. OPENSSL_memcpy(data, o->data, o->length);
  109. }
  110. // once data is attached to an object, it remains const
  111. r->data = data;
  112. r->length = o->length;
  113. r->nid = o->nid;
  114. if (o->ln != NULL) {
  115. ln = OPENSSL_strdup(o->ln);
  116. if (ln == NULL) {
  117. goto err;
  118. }
  119. }
  120. if (o->sn != NULL) {
  121. sn = OPENSSL_strdup(o->sn);
  122. if (sn == NULL) {
  123. goto err;
  124. }
  125. }
  126. r->sn = sn;
  127. r->ln = ln;
  128. r->flags =
  129. o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
  130. ASN1_OBJECT_FLAG_DYNAMIC_DATA);
  131. return r;
  132. err:
  133. OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE);
  134. OPENSSL_free(ln);
  135. OPENSSL_free(sn);
  136. OPENSSL_free(data);
  137. OPENSSL_free(r);
  138. return NULL;
  139. }
  140. int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  141. int ret;
  142. ret = a->length - b->length;
  143. if (ret) {
  144. return ret;
  145. }
  146. return OPENSSL_memcmp(a->data, b->data, a->length);
  147. }
  148. const uint8_t *OBJ_get0_data(const ASN1_OBJECT *obj) {
  149. if (obj == NULL) {
  150. return NULL;
  151. }
  152. return obj->data;
  153. }
  154. size_t OBJ_length(const ASN1_OBJECT *obj) {
  155. if (obj == NULL || obj->length < 0) {
  156. return 0;
  157. }
  158. return (size_t)obj->length;
  159. }
  160. // obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is
  161. // an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
  162. // unsigned int in the array.
  163. static int obj_cmp(const void *key, const void *element) {
  164. unsigned nid = *((const unsigned*) element);
  165. const ASN1_OBJECT *a = key;
  166. const ASN1_OBJECT *b = &kObjects[nid];
  167. if (a->length < b->length) {
  168. return -1;
  169. } else if (a->length > b->length) {
  170. return 1;
  171. }
  172. return OPENSSL_memcmp(a->data, b->data, a->length);
  173. }
  174. int OBJ_obj2nid(const ASN1_OBJECT *obj) {
  175. const unsigned int *nid_ptr;
  176. if (obj == NULL) {
  177. return NID_undef;
  178. }
  179. if (obj->nid != 0) {
  180. return obj->nid;
  181. }
  182. CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
  183. if (global_added_by_data != NULL) {
  184. ASN1_OBJECT *match;
  185. match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
  186. if (match != NULL) {
  187. CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
  188. return match->nid;
  189. }
  190. }
  191. CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
  192. nid_ptr = bsearch(obj, kNIDsInOIDOrder, OPENSSL_ARRAY_SIZE(kNIDsInOIDOrder),
  193. sizeof(kNIDsInOIDOrder[0]), obj_cmp);
  194. if (nid_ptr == NULL) {
  195. return NID_undef;
  196. }
  197. return kObjects[*nid_ptr].nid;
  198. }
  199. int OBJ_cbs2nid(const CBS *cbs) {
  200. if (CBS_len(cbs) > INT_MAX) {
  201. return NID_undef;
  202. }
  203. ASN1_OBJECT obj;
  204. OPENSSL_memset(&obj, 0, sizeof(obj));
  205. obj.data = CBS_data(cbs);
  206. obj.length = (int)CBS_len(cbs);
  207. return OBJ_obj2nid(&obj);
  208. }
  209. // short_name_cmp is called to search the kNIDsInShortNameOrder array. The
  210. // |key| argument is name that we're looking for and |element| is a pointer to
  211. // an unsigned int in the array.
  212. static int short_name_cmp(const void *key, const void *element) {
  213. const char *name = (const char *) key;
  214. unsigned nid = *((unsigned*) element);
  215. return strcmp(name, kObjects[nid].sn);
  216. }
  217. int OBJ_sn2nid(const char *short_name) {
  218. const unsigned int *nid_ptr;
  219. CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
  220. if (global_added_by_short_name != NULL) {
  221. ASN1_OBJECT *match, template;
  222. template.sn = short_name;
  223. match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
  224. if (match != NULL) {
  225. CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
  226. return match->nid;
  227. }
  228. }
  229. CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
  230. nid_ptr = bsearch(short_name, kNIDsInShortNameOrder,
  231. OPENSSL_ARRAY_SIZE(kNIDsInShortNameOrder),
  232. sizeof(kNIDsInShortNameOrder[0]), short_name_cmp);
  233. if (nid_ptr == NULL) {
  234. return NID_undef;
  235. }
  236. return kObjects[*nid_ptr].nid;
  237. }
  238. // long_name_cmp is called to search the kNIDsInLongNameOrder array. The
  239. // |key| argument is name that we're looking for and |element| is a pointer to
  240. // an unsigned int in the array.
  241. static int long_name_cmp(const void *key, const void *element) {
  242. const char *name = (const char *) key;
  243. unsigned nid = *((unsigned*) element);
  244. return strcmp(name, kObjects[nid].ln);
  245. }
  246. int OBJ_ln2nid(const char *long_name) {
  247. const unsigned int *nid_ptr;
  248. CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
  249. if (global_added_by_long_name != NULL) {
  250. ASN1_OBJECT *match, template;
  251. template.ln = long_name;
  252. match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
  253. if (match != NULL) {
  254. CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
  255. return match->nid;
  256. }
  257. }
  258. CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
  259. nid_ptr = bsearch(long_name, kNIDsInLongNameOrder,
  260. OPENSSL_ARRAY_SIZE(kNIDsInLongNameOrder),
  261. sizeof(kNIDsInLongNameOrder[0]), long_name_cmp);
  262. if (nid_ptr == NULL) {
  263. return NID_undef;
  264. }
  265. return kObjects[*nid_ptr].nid;
  266. }
  267. int OBJ_txt2nid(const char *s) {
  268. ASN1_OBJECT *obj;
  269. int nid;
  270. obj = OBJ_txt2obj(s, 0 /* search names */);
  271. nid = OBJ_obj2nid(obj);
  272. ASN1_OBJECT_free(obj);
  273. return nid;
  274. }
  275. OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) {
  276. const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
  277. CBB oid;
  278. if (obj == NULL ||
  279. !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) ||
  280. !CBB_add_bytes(&oid, obj->data, obj->length) ||
  281. !CBB_flush(out)) {
  282. return 0;
  283. }
  284. return 1;
  285. }
  286. const ASN1_OBJECT *OBJ_nid2obj(int nid) {
  287. if (nid >= 0 && nid < NUM_NID) {
  288. if (nid != NID_undef && kObjects[nid].nid == NID_undef) {
  289. goto err;
  290. }
  291. return &kObjects[nid];
  292. }
  293. CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
  294. if (global_added_by_nid != NULL) {
  295. ASN1_OBJECT *match, template;
  296. template.nid = nid;
  297. match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
  298. if (match != NULL) {
  299. CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
  300. return match;
  301. }
  302. }
  303. CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
  304. err:
  305. OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID);
  306. return NULL;
  307. }
  308. const char *OBJ_nid2sn(int nid) {
  309. const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
  310. if (obj == NULL) {
  311. return NULL;
  312. }
  313. return obj->sn;
  314. }
  315. const char *OBJ_nid2ln(int nid) {
  316. const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
  317. if (obj == NULL) {
  318. return NULL;
  319. }
  320. return obj->ln;
  321. }
  322. static ASN1_OBJECT *create_object_with_text_oid(int (*get_nid)(void),
  323. const char *oid,
  324. const char *short_name,
  325. const char *long_name) {
  326. uint8_t *buf;
  327. size_t len;
  328. CBB cbb;
  329. if (!CBB_init(&cbb, 32) ||
  330. !CBB_add_asn1_oid_from_text(&cbb, oid, strlen(oid)) ||
  331. !CBB_finish(&cbb, &buf, &len)) {
  332. OPENSSL_PUT_ERROR(OBJ, OBJ_R_INVALID_OID_STRING);
  333. CBB_cleanup(&cbb);
  334. return NULL;
  335. }
  336. ASN1_OBJECT *ret = ASN1_OBJECT_create(get_nid ? get_nid() : NID_undef, buf,
  337. len, short_name, long_name);
  338. OPENSSL_free(buf);
  339. return ret;
  340. }
  341. ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) {
  342. if (!dont_search_names) {
  343. int nid = OBJ_sn2nid(s);
  344. if (nid == NID_undef) {
  345. nid = OBJ_ln2nid(s);
  346. }
  347. if (nid != NID_undef) {
  348. return (ASN1_OBJECT*) OBJ_nid2obj(nid);
  349. }
  350. }
  351. return create_object_with_text_oid(NULL, s, NULL, NULL);
  352. }
  353. static int strlcpy_int(char *dst, const char *src, int dst_size) {
  354. size_t ret = BUF_strlcpy(dst, src, dst_size < 0 ? 0 : (size_t)dst_size);
  355. if (ret > INT_MAX) {
  356. OPENSSL_PUT_ERROR(OBJ, ERR_R_OVERFLOW);
  357. return -1;
  358. }
  359. return (int)ret;
  360. }
  361. int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj,
  362. int always_return_oid) {
  363. // Python depends on the empty OID successfully encoding as the empty
  364. // string.
  365. if (obj == NULL || obj->length == 0) {
  366. return strlcpy_int(out, "", out_len);
  367. }
  368. if (!always_return_oid) {
  369. int nid = OBJ_obj2nid(obj);
  370. if (nid != NID_undef) {
  371. const char *name = OBJ_nid2ln(nid);
  372. if (name == NULL) {
  373. name = OBJ_nid2sn(nid);
  374. }
  375. if (name != NULL) {
  376. return strlcpy_int(out, name, out_len);
  377. }
  378. }
  379. }
  380. CBS cbs;
  381. CBS_init(&cbs, obj->data, obj->length);
  382. char *txt = CBS_asn1_oid_to_text(&cbs);
  383. if (txt == NULL) {
  384. if (out_len > 0) {
  385. out[0] = '\0';
  386. }
  387. return -1;
  388. }
  389. int ret = strlcpy_int(out, txt, out_len);
  390. OPENSSL_free(txt);
  391. return ret;
  392. }
  393. static uint32_t hash_nid(const ASN1_OBJECT *obj) {
  394. return obj->nid;
  395. }
  396. static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  397. return a->nid - b->nid;
  398. }
  399. static uint32_t hash_data(const ASN1_OBJECT *obj) {
  400. return OPENSSL_hash32(obj->data, obj->length);
  401. }
  402. static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  403. int i = a->length - b->length;
  404. if (i) {
  405. return i;
  406. }
  407. return OPENSSL_memcmp(a->data, b->data, a->length);
  408. }
  409. static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
  410. return lh_strhash(obj->sn);
  411. }
  412. static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  413. return strcmp(a->sn, b->sn);
  414. }
  415. static uint32_t hash_long_name(const ASN1_OBJECT *obj) {
  416. return lh_strhash(obj->ln);
  417. }
  418. static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  419. return strcmp(a->ln, b->ln);
  420. }
  421. // obj_add_object inserts |obj| into the various global hashes for run-time
  422. // added objects. It returns one on success or zero otherwise.
  423. static int obj_add_object(ASN1_OBJECT *obj) {
  424. int ok;
  425. ASN1_OBJECT *old_object;
  426. obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
  427. ASN1_OBJECT_FLAG_DYNAMIC_DATA);
  428. CRYPTO_STATIC_MUTEX_lock_write(&global_added_lock);
  429. if (global_added_by_nid == NULL) {
  430. global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
  431. global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data);
  432. global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name);
  433. global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name);
  434. }
  435. // We don't pay attention to |old_object| (which contains any previous object
  436. // that was evicted from the hashes) because we don't have a reference count
  437. // on ASN1_OBJECT values. Also, we should never have duplicates nids and so
  438. // should always have objects in |global_added_by_nid|.
  439. ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj);
  440. if (obj->length != 0 && obj->data != NULL) {
  441. ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj);
  442. }
  443. if (obj->sn != NULL) {
  444. ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj);
  445. }
  446. if (obj->ln != NULL) {
  447. ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
  448. }
  449. CRYPTO_STATIC_MUTEX_unlock_write(&global_added_lock);
  450. return ok;
  451. }
  452. int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
  453. ASN1_OBJECT *op =
  454. create_object_with_text_oid(obj_next_nid, oid, short_name, long_name);
  455. if (op == NULL ||
  456. !obj_add_object(op)) {
  457. return NID_undef;
  458. }
  459. return op->nid;
  460. }
  461. void OBJ_cleanup(void) {}