v3_lib.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /* v3_lib.c */
  2. /*
  3. * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
  4. * 1999.
  5. */
  6. /* ====================================================================
  7. * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in
  18. * the documentation and/or other materials provided with the
  19. * distribution.
  20. *
  21. * 3. All advertising materials mentioning features or use of this
  22. * software must display the following acknowledgment:
  23. * "This product includes software developed by the OpenSSL Project
  24. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  25. *
  26. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  27. * endorse or promote products derived from this software without
  28. * prior written permission. For written permission, please contact
  29. * licensing@OpenSSL.org.
  30. *
  31. * 5. Products derived from this software may not be called "OpenSSL"
  32. * nor may "OpenSSL" appear in their names without prior written
  33. * permission of the OpenSSL Project.
  34. *
  35. * 6. Redistributions of any form whatsoever must retain the following
  36. * acknowledgment:
  37. * "This product includes software developed by the OpenSSL Project
  38. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  41. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  43. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  44. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  45. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  46. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  47. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  49. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  50. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  51. * OF THE POSSIBILITY OF SUCH DAMAGE.
  52. * ====================================================================
  53. *
  54. * This product includes cryptographic software written by Eric Young
  55. * (eay@cryptsoft.com). This product includes software written by Tim
  56. * Hudson (tjh@cryptsoft.com).
  57. *
  58. */
  59. /* X509 v3 extension utilities */
  60. #include <stdio.h>
  61. #include "cryptlib.h"
  62. #include <openssl/conf.h>
  63. #include <openssl/x509v3.h>
  64. #include "ext_dat.h"
  65. static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL;
  66. static int ext_cmp(const X509V3_EXT_METHOD *const *a,
  67. const X509V3_EXT_METHOD *const *b);
  68. static void ext_list_free(X509V3_EXT_METHOD *ext);
  69. int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
  70. {
  71. if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp))) {
  72. X509V3err(X509V3_F_X509V3_EXT_ADD, ERR_R_MALLOC_FAILURE);
  73. return 0;
  74. }
  75. if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
  76. X509V3err(X509V3_F_X509V3_EXT_ADD, ERR_R_MALLOC_FAILURE);
  77. return 0;
  78. }
  79. return 1;
  80. }
  81. static int ext_cmp(const X509V3_EXT_METHOD *const *a,
  82. const X509V3_EXT_METHOD *const *b)
  83. {
  84. return ((*a)->ext_nid - (*b)->ext_nid);
  85. }
  86. DECLARE_OBJ_BSEARCH_CMP_FN(const X509V3_EXT_METHOD *,
  87. const X509V3_EXT_METHOD *, ext);
  88. IMPLEMENT_OBJ_BSEARCH_CMP_FN(const X509V3_EXT_METHOD *,
  89. const X509V3_EXT_METHOD *, ext);
  90. const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
  91. {
  92. X509V3_EXT_METHOD tmp;
  93. const X509V3_EXT_METHOD *t = &tmp, *const *ret;
  94. int idx;
  95. if (nid < 0)
  96. return NULL;
  97. tmp.ext_nid = nid;
  98. ret = OBJ_bsearch_ext(&t, standard_exts, STANDARD_EXTENSION_COUNT);
  99. if (ret)
  100. return *ret;
  101. if (!ext_list)
  102. return NULL;
  103. idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
  104. if (idx == -1)
  105. return NULL;
  106. return sk_X509V3_EXT_METHOD_value(ext_list, idx);
  107. }
  108. const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
  109. {
  110. int nid;
  111. if ((nid = OBJ_obj2nid(ext->object)) == NID_undef)
  112. return NULL;
  113. return X509V3_EXT_get_nid(nid);
  114. }
  115. int X509V3_EXT_free(int nid, void *ext_data)
  116. {
  117. const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid);
  118. if (ext_method == NULL) {
  119. X509V3err(X509V3_F_X509V3_EXT_FREE,
  120. X509V3_R_CANNOT_FIND_FREE_FUNCTION);
  121. return 0;
  122. }
  123. if (ext_method->it != NULL)
  124. ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
  125. else if (ext_method->ext_free != NULL)
  126. ext_method->ext_free(ext_data);
  127. else {
  128. X509V3err(X509V3_F_X509V3_EXT_FREE,
  129. X509V3_R_CANNOT_FIND_FREE_FUNCTION);
  130. return 0;
  131. }
  132. return 1;
  133. }
  134. int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
  135. {
  136. for (; extlist->ext_nid != -1; extlist++)
  137. if (!X509V3_EXT_add(extlist))
  138. return 0;
  139. return 1;
  140. }
  141. int X509V3_EXT_add_alias(int nid_to, int nid_from)
  142. {
  143. const X509V3_EXT_METHOD *ext;
  144. X509V3_EXT_METHOD *tmpext;
  145. if (!(ext = X509V3_EXT_get_nid(nid_from))) {
  146. X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,
  147. X509V3_R_EXTENSION_NOT_FOUND);
  148. return 0;
  149. }
  150. if (!
  151. (tmpext =
  152. (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
  153. X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS, ERR_R_MALLOC_FAILURE);
  154. return 0;
  155. }
  156. *tmpext = *ext;
  157. tmpext->ext_nid = nid_to;
  158. tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
  159. return X509V3_EXT_add(tmpext);
  160. }
  161. void X509V3_EXT_cleanup(void)
  162. {
  163. sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
  164. ext_list = NULL;
  165. }
  166. static void ext_list_free(X509V3_EXT_METHOD *ext)
  167. {
  168. if (ext->ext_flags & X509V3_EXT_DYNAMIC)
  169. OPENSSL_free(ext);
  170. }
  171. /*
  172. * Legacy function: we don't need to add standard extensions any more because
  173. * they are now kept in ext_dat.h.
  174. */
  175. int X509V3_add_standard_extensions(void)
  176. {
  177. return 1;
  178. }
  179. /* Return an extension internal structure */
  180. void *X509V3_EXT_d2i(X509_EXTENSION *ext)
  181. {
  182. const X509V3_EXT_METHOD *method;
  183. const unsigned char *p;
  184. if (!(method = X509V3_EXT_get(ext)))
  185. return NULL;
  186. p = ext->value->data;
  187. if (method->it)
  188. return ASN1_item_d2i(NULL, &p, ext->value->length,
  189. ASN1_ITEM_ptr(method->it));
  190. return method->d2i(NULL, &p, ext->value->length);
  191. }
  192. /*-
  193. * Get critical flag and decoded version of extension from a NID.
  194. * The "idx" variable returns the last found extension and can
  195. * be used to retrieve multiple extensions of the same NID.
  196. * However multiple extensions with the same NID is usually
  197. * due to a badly encoded certificate so if idx is NULL we
  198. * choke if multiple extensions exist.
  199. * The "crit" variable is set to the critical value.
  200. * The return value is the decoded extension or NULL on
  201. * error. The actual error can have several different causes,
  202. * the value of *crit reflects the cause:
  203. * >= 0, extension found but not decoded (reflects critical value).
  204. * -1 extension not found.
  205. * -2 extension occurs more than once.
  206. */
  207. void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
  208. int *idx)
  209. {
  210. int lastpos, i;
  211. X509_EXTENSION *ex, *found_ex = NULL;
  212. if (!x) {
  213. if (idx)
  214. *idx = -1;
  215. if (crit)
  216. *crit = -1;
  217. return NULL;
  218. }
  219. if (idx)
  220. lastpos = *idx + 1;
  221. else
  222. lastpos = 0;
  223. if (lastpos < 0)
  224. lastpos = 0;
  225. for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
  226. ex = sk_X509_EXTENSION_value(x, i);
  227. if (OBJ_obj2nid(ex->object) == nid) {
  228. if (idx) {
  229. *idx = i;
  230. found_ex = ex;
  231. break;
  232. } else if (found_ex) {
  233. /* Found more than one */
  234. if (crit)
  235. *crit = -2;
  236. return NULL;
  237. }
  238. found_ex = ex;
  239. }
  240. }
  241. if (found_ex) {
  242. /* Found it */
  243. if (crit)
  244. *crit = X509_EXTENSION_get_critical(found_ex);
  245. return X509V3_EXT_d2i(found_ex);
  246. }
  247. /* Extension not found */
  248. if (idx)
  249. *idx = -1;
  250. if (crit)
  251. *crit = -1;
  252. return NULL;
  253. }
  254. /*
  255. * This function is a general extension append, replace and delete utility.
  256. * The precise operation is governed by the 'flags' value. The 'crit' and
  257. * 'value' arguments (if relevant) are the extensions internal structure.
  258. */
  259. int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
  260. int crit, unsigned long flags)
  261. {
  262. int extidx = -1;
  263. int errcode;
  264. X509_EXTENSION *ext, *extmp;
  265. unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
  266. /*
  267. * If appending we don't care if it exists, otherwise look for existing
  268. * extension.
  269. */
  270. if (ext_op != X509V3_ADD_APPEND)
  271. extidx = X509v3_get_ext_by_NID(*x, nid, -1);
  272. /* See if extension exists */
  273. if (extidx >= 0) {
  274. /* If keep existing, nothing to do */
  275. if (ext_op == X509V3_ADD_KEEP_EXISTING)
  276. return 1;
  277. /* If default then its an error */
  278. if (ext_op == X509V3_ADD_DEFAULT) {
  279. errcode = X509V3_R_EXTENSION_EXISTS;
  280. goto err;
  281. }
  282. /* If delete, just delete it */
  283. if (ext_op == X509V3_ADD_DELETE) {
  284. if (!sk_X509_EXTENSION_delete(*x, extidx))
  285. return -1;
  286. return 1;
  287. }
  288. } else {
  289. /*
  290. * If replace existing or delete, error since extension must exist
  291. */
  292. if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
  293. (ext_op == X509V3_ADD_DELETE)) {
  294. errcode = X509V3_R_EXTENSION_NOT_FOUND;
  295. goto err;
  296. }
  297. }
  298. /*
  299. * If we get this far then we have to create an extension: could have
  300. * some flags for alternative encoding schemes...
  301. */
  302. ext = X509V3_EXT_i2d(nid, crit, value);
  303. if (!ext) {
  304. X509V3err(X509V3_F_X509V3_ADD1_I2D,
  305. X509V3_R_ERROR_CREATING_EXTENSION);
  306. return 0;
  307. }
  308. /* If extension exists replace it.. */
  309. if (extidx >= 0) {
  310. extmp = sk_X509_EXTENSION_value(*x, extidx);
  311. X509_EXTENSION_free(extmp);
  312. if (!sk_X509_EXTENSION_set(*x, extidx, ext))
  313. return -1;
  314. return 1;
  315. }
  316. if (!*x && !(*x = sk_X509_EXTENSION_new_null()))
  317. return -1;
  318. if (!sk_X509_EXTENSION_push(*x, ext))
  319. return -1;
  320. return 1;
  321. err:
  322. if (!(flags & X509V3_ADD_SILENT))
  323. X509V3err(X509V3_F_X509V3_ADD1_I2D, errcode);
  324. return 0;
  325. }
  326. IMPLEMENT_STACK_OF(X509V3_EXT_METHOD)