v3_lib.c 10 KB

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