25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

665 lines
17 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 <limits.h>
  58. #include <string.h>
  59. #include <openssl/asn1.h>
  60. #include <openssl/buf.h>
  61. #include <openssl/bytestring.h>
  62. #include <openssl/err.h>
  63. #include <openssl/lhash.h>
  64. #include <openssl/mem.h>
  65. #include <openssl/thread.h>
  66. #include "obj_dat.h"
  67. #include "../internal.h"
  68. static struct CRYPTO_STATIC_MUTEX global_added_lock = CRYPTO_STATIC_MUTEX_INIT;
  69. /* These globals are protected by |global_added_lock|. */
  70. static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
  71. static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL;
  72. static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL;
  73. static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
  74. static struct CRYPTO_STATIC_MUTEX global_next_nid_lock =
  75. CRYPTO_STATIC_MUTEX_INIT;
  76. static unsigned global_next_nid = NUM_NID;
  77. static int obj_next_nid(void) {
  78. int ret;
  79. CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock);
  80. ret = global_next_nid++;
  81. CRYPTO_STATIC_MUTEX_unlock(&global_next_nid_lock);
  82. return ret;
  83. }
  84. ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
  85. ASN1_OBJECT *r;
  86. unsigned char *data = NULL;
  87. char *sn = NULL, *ln = NULL;
  88. if (o == NULL) {
  89. return NULL;
  90. }
  91. if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
  92. /* TODO(fork): this is a little dangerous. */
  93. return (ASN1_OBJECT *)o;
  94. }
  95. r = ASN1_OBJECT_new();
  96. if (r == NULL) {
  97. OPENSSL_PUT_ERROR(OBJ, ERR_R_ASN1_LIB);
  98. return NULL;
  99. }
  100. r->ln = r->sn = NULL;
  101. data = OPENSSL_malloc(o->length);
  102. if (data == NULL) {
  103. goto err;
  104. }
  105. if (o->data != NULL) {
  106. memcpy(data, o->data, o->length);
  107. }
  108. /* once data is attached to an object, it remains const */
  109. r->data = data;
  110. r->length = o->length;
  111. r->nid = o->nid;
  112. if (o->ln != NULL) {
  113. ln = OPENSSL_strdup(o->ln);
  114. if (ln == NULL) {
  115. goto err;
  116. }
  117. }
  118. if (o->sn != NULL) {
  119. sn = OPENSSL_strdup(o->sn);
  120. if (sn == NULL) {
  121. goto err;
  122. }
  123. }
  124. r->sn = sn;
  125. r->ln = ln;
  126. r->flags =
  127. o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
  128. ASN1_OBJECT_FLAG_DYNAMIC_DATA);
  129. return r;
  130. err:
  131. OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE);
  132. OPENSSL_free(ln);
  133. OPENSSL_free(sn);
  134. OPENSSL_free(data);
  135. OPENSSL_free(r);
  136. return NULL;
  137. }
  138. int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  139. int ret;
  140. ret = a->length - b->length;
  141. if (ret) {
  142. return ret;
  143. }
  144. return memcmp(a->data, b->data, a->length);
  145. }
  146. /* obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is
  147. * an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
  148. * unsigned int in the array. */
  149. static int obj_cmp(const void *key, const void *element) {
  150. unsigned nid = *((const unsigned*) element);
  151. const ASN1_OBJECT *a = key;
  152. const ASN1_OBJECT *b = &kObjects[nid];
  153. if (a->length < b->length) {
  154. return -1;
  155. } else if (a->length > b->length) {
  156. return 1;
  157. }
  158. return memcmp(a->data, b->data, a->length);
  159. }
  160. int OBJ_obj2nid(const ASN1_OBJECT *obj) {
  161. const unsigned int *nid_ptr;
  162. if (obj == NULL) {
  163. return NID_undef;
  164. }
  165. if (obj->nid != 0) {
  166. return obj->nid;
  167. }
  168. CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
  169. if (global_added_by_data != NULL) {
  170. ASN1_OBJECT *match;
  171. match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
  172. if (match != NULL) {
  173. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  174. return match->nid;
  175. }
  176. }
  177. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  178. nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp);
  179. if (nid_ptr == NULL) {
  180. return NID_undef;
  181. }
  182. return kObjects[*nid_ptr].nid;
  183. }
  184. int OBJ_cbs2nid(const CBS *cbs) {
  185. ASN1_OBJECT obj;
  186. memset(&obj, 0, sizeof(obj));
  187. obj.data = CBS_data(cbs);
  188. obj.length = CBS_len(cbs);
  189. return OBJ_obj2nid(&obj);
  190. }
  191. /* short_name_cmp is called to search the kNIDsInShortNameOrder array. The
  192. * |key| argument is name that we're looking for and |element| is a pointer to
  193. * an unsigned int in the array. */
  194. static int short_name_cmp(const void *key, const void *element) {
  195. const char *name = (const char *) key;
  196. unsigned nid = *((unsigned*) element);
  197. return strcmp(name, kObjects[nid].sn);
  198. }
  199. int OBJ_sn2nid(const char *short_name) {
  200. const unsigned int *nid_ptr;
  201. CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
  202. if (global_added_by_short_name != NULL) {
  203. ASN1_OBJECT *match, template;
  204. template.sn = short_name;
  205. match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
  206. if (match != NULL) {
  207. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  208. return match->nid;
  209. }
  210. }
  211. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  212. nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp);
  213. if (nid_ptr == NULL) {
  214. return NID_undef;
  215. }
  216. return kObjects[*nid_ptr].nid;
  217. }
  218. /* long_name_cmp is called to search the kNIDsInLongNameOrder array. The
  219. * |key| argument is name that we're looking for and |element| is a pointer to
  220. * an unsigned int in the array. */
  221. static int long_name_cmp(const void *key, const void *element) {
  222. const char *name = (const char *) key;
  223. unsigned nid = *((unsigned*) element);
  224. return strcmp(name, kObjects[nid].ln);
  225. }
  226. int OBJ_ln2nid(const char *long_name) {
  227. const unsigned int *nid_ptr;
  228. CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
  229. if (global_added_by_long_name != NULL) {
  230. ASN1_OBJECT *match, template;
  231. template.ln = long_name;
  232. match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
  233. if (match != NULL) {
  234. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  235. return match->nid;
  236. }
  237. }
  238. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  239. nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp);
  240. if (nid_ptr == NULL) {
  241. return NID_undef;
  242. }
  243. return kObjects[*nid_ptr].nid;
  244. }
  245. int OBJ_txt2nid(const char *s) {
  246. ASN1_OBJECT *obj;
  247. int nid;
  248. obj = OBJ_txt2obj(s, 0 /* search names */);
  249. nid = OBJ_obj2nid(obj);
  250. ASN1_OBJECT_free(obj);
  251. return nid;
  252. }
  253. OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) {
  254. const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
  255. CBB oid;
  256. if (obj == NULL ||
  257. !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) ||
  258. !CBB_add_bytes(&oid, obj->data, obj->length) ||
  259. !CBB_flush(out)) {
  260. return 0;
  261. }
  262. return 1;
  263. }
  264. const ASN1_OBJECT *OBJ_nid2obj(int nid) {
  265. if (nid >= 0 && nid < NUM_NID) {
  266. if (nid != NID_undef && kObjects[nid].nid == NID_undef) {
  267. goto err;
  268. }
  269. return &kObjects[nid];
  270. }
  271. CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
  272. if (global_added_by_nid != NULL) {
  273. ASN1_OBJECT *match, template;
  274. template.nid = nid;
  275. match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
  276. if (match != NULL) {
  277. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  278. return match;
  279. }
  280. }
  281. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  282. err:
  283. OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID);
  284. return NULL;
  285. }
  286. const char *OBJ_nid2sn(int nid) {
  287. const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
  288. if (obj == NULL) {
  289. return NULL;
  290. }
  291. return obj->sn;
  292. }
  293. const char *OBJ_nid2ln(int nid) {
  294. const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
  295. if (obj == NULL) {
  296. return NULL;
  297. }
  298. return obj->ln;
  299. }
  300. ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) {
  301. int nid = NID_undef;
  302. ASN1_OBJECT *op = NULL;
  303. unsigned char *buf;
  304. unsigned char *p;
  305. const unsigned char *bufp;
  306. int contents_len, total_len;
  307. if (!dont_search_names) {
  308. nid = OBJ_sn2nid(s);
  309. if (nid == NID_undef) {
  310. nid = OBJ_ln2nid(s);
  311. }
  312. if (nid != NID_undef) {
  313. return (ASN1_OBJECT*) OBJ_nid2obj(nid);
  314. }
  315. }
  316. /* Work out size of content octets */
  317. contents_len = a2d_ASN1_OBJECT(NULL, 0, s, -1);
  318. if (contents_len <= 0) {
  319. return NULL;
  320. }
  321. /* Work out total size */
  322. total_len = ASN1_object_size(0, contents_len, V_ASN1_OBJECT);
  323. buf = OPENSSL_malloc(total_len);
  324. if (buf == NULL) {
  325. OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE);
  326. return NULL;
  327. }
  328. p = buf;
  329. /* Write out tag+length */
  330. ASN1_put_object(&p, 0, contents_len, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
  331. /* Write out contents */
  332. a2d_ASN1_OBJECT(p, contents_len, s, -1);
  333. bufp = buf;
  334. op = d2i_ASN1_OBJECT(NULL, &bufp, total_len);
  335. OPENSSL_free(buf);
  336. return op;
  337. }
  338. int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, int dont_return_name) {
  339. int i, n = 0, len, nid, first, use_bn;
  340. BIGNUM *bl;
  341. unsigned long l;
  342. const unsigned char *p;
  343. char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
  344. if (out && out_len > 0) {
  345. out[0] = 0;
  346. }
  347. if (obj == NULL || obj->data == NULL) {
  348. return 0;
  349. }
  350. if (!dont_return_name && (nid = OBJ_obj2nid(obj)) != NID_undef) {
  351. const char *s;
  352. s = OBJ_nid2ln(nid);
  353. if (s == NULL) {
  354. s = OBJ_nid2sn(nid);
  355. }
  356. if (s) {
  357. if (out) {
  358. BUF_strlcpy(out, s, out_len);
  359. }
  360. return strlen(s);
  361. }
  362. }
  363. len = obj->length;
  364. p = obj->data;
  365. first = 1;
  366. bl = NULL;
  367. while (len > 0) {
  368. l = 0;
  369. use_bn = 0;
  370. for (;;) {
  371. unsigned char c = *p++;
  372. len--;
  373. if (len == 0 && (c & 0x80)) {
  374. goto err;
  375. }
  376. if (use_bn) {
  377. if (!BN_add_word(bl, c & 0x7f)) {
  378. goto err;
  379. }
  380. } else {
  381. l |= c & 0x7f;
  382. }
  383. if (!(c & 0x80)) {
  384. break;
  385. }
  386. if (!use_bn && (l > (ULONG_MAX >> 7L))) {
  387. if (!bl && !(bl = BN_new())) {
  388. goto err;
  389. }
  390. if (!BN_set_word(bl, l)) {
  391. goto err;
  392. }
  393. use_bn = 1;
  394. }
  395. if (use_bn) {
  396. if (!BN_lshift(bl, bl, 7)) {
  397. goto err;
  398. }
  399. } else {
  400. l <<= 7L;
  401. }
  402. }
  403. if (first) {
  404. first = 0;
  405. if (l >= 80) {
  406. i = 2;
  407. if (use_bn) {
  408. if (!BN_sub_word(bl, 80)) {
  409. goto err;
  410. }
  411. } else {
  412. l -= 80;
  413. }
  414. } else {
  415. i = (int)(l / 40);
  416. l -= (long)(i * 40);
  417. }
  418. if (out && out_len > 1) {
  419. *out++ = i + '0';
  420. *out = '0';
  421. out_len--;
  422. }
  423. n++;
  424. }
  425. if (use_bn) {
  426. char *bndec;
  427. bndec = BN_bn2dec(bl);
  428. if (!bndec) {
  429. goto err;
  430. }
  431. i = strlen(bndec);
  432. if (out) {
  433. if (out_len > 1) {
  434. *out++ = '.';
  435. *out = 0;
  436. out_len--;
  437. }
  438. BUF_strlcpy(out, bndec, out_len);
  439. if (i > out_len) {
  440. out += out_len;
  441. out_len = 0;
  442. } else {
  443. out += i;
  444. out_len -= i;
  445. }
  446. }
  447. n++;
  448. n += i;
  449. OPENSSL_free(bndec);
  450. } else {
  451. BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l);
  452. i = strlen(tbuf);
  453. if (out && out_len > 0) {
  454. BUF_strlcpy(out, tbuf, out_len);
  455. if (i > out_len) {
  456. out += out_len;
  457. out_len = 0;
  458. } else {
  459. out += i;
  460. out_len -= i;
  461. }
  462. }
  463. n += i;
  464. }
  465. }
  466. BN_free(bl);
  467. return n;
  468. err:
  469. BN_free(bl);
  470. return -1;
  471. }
  472. static uint32_t hash_nid(const ASN1_OBJECT *obj) {
  473. return obj->nid;
  474. }
  475. static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  476. return a->nid - b->nid;
  477. }
  478. static uint32_t hash_data(const ASN1_OBJECT *obj) {
  479. return OPENSSL_hash32(obj->data, obj->length);
  480. }
  481. static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  482. int i = a->length - b->length;
  483. if (i) {
  484. return i;
  485. }
  486. return memcmp(a->data, b->data, a->length);
  487. }
  488. static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
  489. return lh_strhash(obj->sn);
  490. }
  491. static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  492. return strcmp(a->sn, b->sn);
  493. }
  494. static uint32_t hash_long_name(const ASN1_OBJECT *obj) {
  495. return lh_strhash(obj->ln);
  496. }
  497. static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
  498. return strcmp(a->ln, b->ln);
  499. }
  500. /* obj_add_object inserts |obj| into the various global hashes for run-time
  501. * added objects. It returns one on success or zero otherwise. */
  502. static int obj_add_object(ASN1_OBJECT *obj) {
  503. int ok;
  504. ASN1_OBJECT *old_object;
  505. obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
  506. ASN1_OBJECT_FLAG_DYNAMIC_DATA);
  507. CRYPTO_STATIC_MUTEX_lock_write(&global_added_lock);
  508. if (global_added_by_nid == NULL) {
  509. global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
  510. global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data);
  511. global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name);
  512. global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name);
  513. }
  514. /* We don't pay attention to |old_object| (which contains any previous object
  515. * that was evicted from the hashes) because we don't have a reference count
  516. * on ASN1_OBJECT values. Also, we should never have duplicates nids and so
  517. * should always have objects in |global_added_by_nid|. */
  518. ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj);
  519. if (obj->length != 0 && obj->data != NULL) {
  520. ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj);
  521. }
  522. if (obj->sn != NULL) {
  523. ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj);
  524. }
  525. if (obj->ln != NULL) {
  526. ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
  527. }
  528. CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
  529. return ok;
  530. }
  531. int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
  532. int ret = NID_undef;
  533. ASN1_OBJECT *op = NULL;
  534. unsigned char *buf = NULL;
  535. int len;
  536. len = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
  537. if (len <= 0) {
  538. goto err;
  539. }
  540. buf = OPENSSL_malloc(len);
  541. if (buf == NULL) {
  542. OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE);
  543. goto err;
  544. }
  545. len = a2d_ASN1_OBJECT(buf, len, oid, -1);
  546. if (len == 0) {
  547. goto err;
  548. }
  549. op = (ASN1_OBJECT *)ASN1_OBJECT_create(obj_next_nid(), buf, len, short_name,
  550. long_name);
  551. if (op == NULL) {
  552. goto err;
  553. }
  554. if (obj_add_object(op)) {
  555. ret = op->nid;
  556. }
  557. op = NULL;
  558. err:
  559. ASN1_OBJECT_free(op);
  560. OPENSSL_free(buf);
  561. return ret;
  562. }