v3_lib.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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. X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
  87. {
  88. X509V3_EXT_METHOD tmp, *t = &tmp, **ret;
  89. int idx;
  90. if (nid < 0)
  91. return NULL;
  92. tmp.ext_nid = nid;
  93. ret = (X509V3_EXT_METHOD **)OBJ_bsearch((char *)&t,
  94. (char *)standard_exts,
  95. STANDARD_EXTENSION_COUNT,
  96. sizeof(X509V3_EXT_METHOD *),
  97. (int (*)
  98. (const void *,
  99. const void *))ext_cmp);
  100. if (ret)
  101. return *ret;
  102. if (!ext_list)
  103. return NULL;
  104. idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp);
  105. if (idx == -1)
  106. return NULL;
  107. return sk_X509V3_EXT_METHOD_value(ext_list, idx);
  108. }
  109. X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
  110. {
  111. int nid;
  112. if ((nid = OBJ_obj2nid(ext->object)) == NID_undef)
  113. return NULL;
  114. return X509V3_EXT_get_nid(nid);
  115. }
  116. int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
  117. {
  118. for (; extlist->ext_nid != -1; extlist++)
  119. if (!X509V3_EXT_add(extlist))
  120. return 0;
  121. return 1;
  122. }
  123. int X509V3_EXT_add_alias(int nid_to, int nid_from)
  124. {
  125. X509V3_EXT_METHOD *ext, *tmpext;
  126. if (!(ext = X509V3_EXT_get_nid(nid_from))) {
  127. X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS,
  128. X509V3_R_EXTENSION_NOT_FOUND);
  129. return 0;
  130. }
  131. if (!
  132. (tmpext =
  133. (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
  134. X509V3err(X509V3_F_X509V3_EXT_ADD_ALIAS, ERR_R_MALLOC_FAILURE);
  135. return 0;
  136. }
  137. *tmpext = *ext;
  138. tmpext->ext_nid = nid_to;
  139. tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
  140. return X509V3_EXT_add(tmpext);
  141. }
  142. void X509V3_EXT_cleanup(void)
  143. {
  144. sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
  145. ext_list = NULL;
  146. }
  147. static void ext_list_free(X509V3_EXT_METHOD *ext)
  148. {
  149. if (ext->ext_flags & X509V3_EXT_DYNAMIC)
  150. OPENSSL_free(ext);
  151. }
  152. /*
  153. * Legacy function: we don't need to add standard extensions any more because
  154. * they are now kept in ext_dat.h.
  155. */
  156. int X509V3_add_standard_extensions(void)
  157. {
  158. return 1;
  159. }
  160. /* Return an extension internal structure */
  161. void *X509V3_EXT_d2i(X509_EXTENSION *ext)
  162. {
  163. X509V3_EXT_METHOD *method;
  164. const unsigned char *p;
  165. if (!(method = X509V3_EXT_get(ext)))
  166. return NULL;
  167. p = ext->value->data;
  168. if (method->it)
  169. return ASN1_item_d2i(NULL, &p, ext->value->length,
  170. ASN1_ITEM_ptr(method->it));
  171. return method->d2i(NULL, &p, ext->value->length);
  172. }
  173. /*-
  174. * Get critical flag and decoded version of extension from a NID.
  175. * The "idx" variable returns the last found extension and can
  176. * be used to retrieve multiple extensions of the same NID.
  177. * However multiple extensions with the same NID is usually
  178. * due to a badly encoded certificate so if idx is NULL we
  179. * choke if multiple extensions exist.
  180. * The "crit" variable is set to the critical value.
  181. * The return value is the decoded extension or NULL on
  182. * error. The actual error can have several different causes,
  183. * the value of *crit reflects the cause:
  184. * >= 0, extension found but not decoded (reflects critical value).
  185. * -1 extension not found.
  186. * -2 extension occurs more than once.
  187. */
  188. void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
  189. int *idx)
  190. {
  191. int lastpos, i;
  192. X509_EXTENSION *ex, *found_ex = NULL;
  193. if (!x) {
  194. if (idx)
  195. *idx = -1;
  196. if (crit)
  197. *crit = -1;
  198. return NULL;
  199. }
  200. if (idx)
  201. lastpos = *idx + 1;
  202. else
  203. lastpos = 0;
  204. if (lastpos < 0)
  205. lastpos = 0;
  206. for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
  207. ex = sk_X509_EXTENSION_value(x, i);
  208. if (OBJ_obj2nid(ex->object) == nid) {
  209. if (idx) {
  210. *idx = i;
  211. found_ex = ex;
  212. break;
  213. } else if (found_ex) {
  214. /* Found more than one */
  215. if (crit)
  216. *crit = -2;
  217. return NULL;
  218. }
  219. found_ex = ex;
  220. }
  221. }
  222. if (found_ex) {
  223. /* Found it */
  224. if (crit)
  225. *crit = X509_EXTENSION_get_critical(found_ex);
  226. return X509V3_EXT_d2i(found_ex);
  227. }
  228. /* Extension not found */
  229. if (idx)
  230. *idx = -1;
  231. if (crit)
  232. *crit = -1;
  233. return NULL;
  234. }
  235. /*
  236. * This function is a general extension append, replace and delete utility.
  237. * The precise operation is governed by the 'flags' value. The 'crit' and
  238. * 'value' arguments (if relevant) are the extensions internal structure.
  239. */
  240. int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
  241. int crit, unsigned long flags)
  242. {
  243. int extidx = -1;
  244. int errcode;
  245. X509_EXTENSION *ext, *extmp;
  246. unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
  247. /*
  248. * If appending we don't care if it exists, otherwise look for existing
  249. * extension.
  250. */
  251. if (ext_op != X509V3_ADD_APPEND)
  252. extidx = X509v3_get_ext_by_NID(*x, nid, -1);
  253. /* See if extension exists */
  254. if (extidx >= 0) {
  255. /* If keep existing, nothing to do */
  256. if (ext_op == X509V3_ADD_KEEP_EXISTING)
  257. return 1;
  258. /* If default then its an error */
  259. if (ext_op == X509V3_ADD_DEFAULT) {
  260. errcode = X509V3_R_EXTENSION_EXISTS;
  261. goto err;
  262. }
  263. /* If delete, just delete it */
  264. if (ext_op == X509V3_ADD_DELETE) {
  265. if (!sk_X509_EXTENSION_delete(*x, extidx))
  266. return -1;
  267. return 1;
  268. }
  269. } else {
  270. /*
  271. * If replace existing or delete, error since extension must exist
  272. */
  273. if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
  274. (ext_op == X509V3_ADD_DELETE)) {
  275. errcode = X509V3_R_EXTENSION_NOT_FOUND;
  276. goto err;
  277. }
  278. }
  279. /*
  280. * If we get this far then we have to create an extension: could have
  281. * some flags for alternative encoding schemes...
  282. */
  283. ext = X509V3_EXT_i2d(nid, crit, value);
  284. if (!ext) {
  285. X509V3err(X509V3_F_X509V3_ADD1_I2D,
  286. X509V3_R_ERROR_CREATING_EXTENSION);
  287. return 0;
  288. }
  289. /* If extension exists replace it.. */
  290. if (extidx >= 0) {
  291. extmp = sk_X509_EXTENSION_value(*x, extidx);
  292. X509_EXTENSION_free(extmp);
  293. if (!sk_X509_EXTENSION_set(*x, extidx, ext))
  294. return -1;
  295. return 1;
  296. }
  297. if (!*x && !(*x = sk_X509_EXTENSION_new_null()))
  298. return -1;
  299. if (!sk_X509_EXTENSION_push(*x, ext))
  300. return -1;
  301. return 1;
  302. err:
  303. if (!(flags & X509V3_ADD_SILENT))
  304. X509V3err(X509V3_F_X509V3_ADD1_I2D, errcode);
  305. return 0;
  306. }
  307. IMPLEMENT_STACK_OF(X509V3_EXT_METHOD)