core_namemap.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /*
  2. * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "internal/namemap.h"
  10. #include "internal/tsan_assist.h"
  11. #include "internal/hashtable.h"
  12. #include "internal/sizes.h"
  13. #include "crypto/context.h"
  14. #define NAMEMAP_HT_BUCKETS 512
  15. HT_START_KEY_DEFN(namenum_key)
  16. HT_DEF_KEY_FIELD_CHAR_ARRAY(name, 64)
  17. HT_END_KEY_DEFN(NAMENUM_KEY)
  18. /*-
  19. * The namemap itself
  20. * ==================
  21. */
  22. typedef STACK_OF(OPENSSL_STRING) NAMES;
  23. DEFINE_STACK_OF(NAMES)
  24. struct ossl_namemap_st {
  25. /* Flags */
  26. unsigned int stored:1; /* If 1, it's stored in a library context */
  27. HT *namenum_ht; /* Name->number mapping */
  28. CRYPTO_RWLOCK *lock;
  29. STACK_OF(NAMES) *numnames;
  30. TSAN_QUALIFIER int max_number; /* Current max number */
  31. };
  32. static void name_string_free(char *name)
  33. {
  34. OPENSSL_free(name);
  35. }
  36. static void names_free(NAMES *n)
  37. {
  38. sk_OPENSSL_STRING_pop_free(n, name_string_free);
  39. }
  40. /* OSSL_LIB_CTX_METHOD functions for a namemap stored in a library context */
  41. void *ossl_stored_namemap_new(OSSL_LIB_CTX *libctx)
  42. {
  43. OSSL_NAMEMAP *namemap = ossl_namemap_new(libctx);
  44. if (namemap != NULL)
  45. namemap->stored = 1;
  46. return namemap;
  47. }
  48. void ossl_stored_namemap_free(void *vnamemap)
  49. {
  50. OSSL_NAMEMAP *namemap = vnamemap;
  51. if (namemap != NULL) {
  52. /* Pretend it isn't stored, or ossl_namemap_free() will do nothing */
  53. namemap->stored = 0;
  54. ossl_namemap_free(namemap);
  55. }
  56. }
  57. /*-
  58. * API functions
  59. * =============
  60. */
  61. int ossl_namemap_empty(OSSL_NAMEMAP *namemap)
  62. {
  63. #ifdef TSAN_REQUIRES_LOCKING
  64. /* No TSAN support */
  65. int rv;
  66. if (namemap == NULL)
  67. return 1;
  68. if (!CRYPTO_THREAD_read_lock(namemap->lock))
  69. return -1;
  70. rv = namemap->max_number == 0;
  71. CRYPTO_THREAD_unlock(namemap->lock);
  72. return rv;
  73. #else
  74. /* Have TSAN support */
  75. return namemap == NULL || tsan_load(&namemap->max_number) == 0;
  76. #endif
  77. }
  78. /*
  79. * Call the callback for all names in the namemap with the given number.
  80. * A return value 1 means that the callback was called for all names. A
  81. * return value of 0 means that the callback was not called for any names.
  82. */
  83. int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
  84. void (*fn)(const char *name, void *data),
  85. void *data)
  86. {
  87. int i;
  88. NAMES *names;
  89. if (namemap == NULL || number <= 0)
  90. return 0;
  91. /*
  92. * We duplicate the NAMES stack under a read lock. Subsequently we call
  93. * the user function, so that we're not holding the read lock when in user
  94. * code. This could lead to deadlocks.
  95. */
  96. if (!CRYPTO_THREAD_read_lock(namemap->lock))
  97. return 0;
  98. names = sk_NAMES_value(namemap->numnames, number - 1);
  99. if (names != NULL)
  100. names = sk_OPENSSL_STRING_dup(names);
  101. CRYPTO_THREAD_unlock(namemap->lock);
  102. if (names == NULL)
  103. return 0;
  104. for (i = 0; i < sk_OPENSSL_STRING_num(names); i++)
  105. fn(sk_OPENSSL_STRING_value(names, i), data);
  106. sk_OPENSSL_STRING_free(names);
  107. return i > 0;
  108. }
  109. int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
  110. {
  111. int number = 0;
  112. HT_VALUE *val;
  113. NAMENUM_KEY key;
  114. #ifndef FIPS_MODULE
  115. if (namemap == NULL)
  116. namemap = ossl_namemap_stored(NULL);
  117. #endif
  118. if (namemap == NULL)
  119. return 0;
  120. HT_INIT_KEY(&key);
  121. HT_SET_KEY_STRING_CASE(&key, name, name);
  122. val = ossl_ht_get(namemap->namenum_ht, TO_HT_KEY(&key));
  123. if (val != NULL)
  124. /* We store a (small) int directly instead of a pointer to it. */
  125. number = (int)(intptr_t)val->value;
  126. return number;
  127. }
  128. int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
  129. const char *name, size_t name_len)
  130. {
  131. int number = 0;
  132. HT_VALUE *val;
  133. NAMENUM_KEY key;
  134. #ifndef FIPS_MODULE
  135. if (namemap == NULL)
  136. namemap = ossl_namemap_stored(NULL);
  137. #endif
  138. if (namemap == NULL)
  139. return 0;
  140. HT_INIT_KEY(&key);
  141. HT_SET_KEY_STRING_CASE_N(&key, name, name, name_len);
  142. val = ossl_ht_get(namemap->namenum_ht, TO_HT_KEY(&key));
  143. if (val != NULL)
  144. /* We store a (small) int directly instead of a pointer to it. */
  145. number = (int)(intptr_t)val->value;
  146. return number;
  147. }
  148. const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number,
  149. size_t idx)
  150. {
  151. NAMES *names;
  152. const char *ret = NULL;
  153. if (namemap == NULL || number <= 0)
  154. return NULL;
  155. if (!CRYPTO_THREAD_read_lock(namemap->lock))
  156. return NULL;
  157. names = sk_NAMES_value(namemap->numnames, number - 1);
  158. if (names != NULL)
  159. ret = sk_OPENSSL_STRING_value(names, idx);
  160. CRYPTO_THREAD_unlock(namemap->lock);
  161. return ret;
  162. }
  163. /* This function is not thread safe, the namemap must be locked */
  164. static int numname_insert(OSSL_NAMEMAP *namemap, int number,
  165. const char *name)
  166. {
  167. NAMES *names;
  168. char *tmpname;
  169. if (number > 0) {
  170. names = sk_NAMES_value(namemap->numnames, number - 1);
  171. if (!ossl_assert(names != NULL)) {
  172. /* cannot happen */
  173. return 0;
  174. }
  175. } else {
  176. /* a completely new entry */
  177. names = sk_OPENSSL_STRING_new_null();
  178. if (names == NULL)
  179. return 0;
  180. }
  181. if ((tmpname = OPENSSL_strdup(name)) == NULL)
  182. goto err;
  183. if (!sk_OPENSSL_STRING_push(names, tmpname))
  184. goto err;
  185. tmpname = NULL;
  186. if (number <= 0) {
  187. if (!sk_NAMES_push(namemap->numnames, names))
  188. goto err;
  189. number = sk_NAMES_num(namemap->numnames);
  190. }
  191. return number;
  192. err:
  193. if (number <= 0)
  194. sk_OPENSSL_STRING_pop_free(names, name_string_free);
  195. OPENSSL_free(tmpname);
  196. return 0;
  197. }
  198. /* This function is not thread safe, the namemap must be locked */
  199. static int namemap_add_name(OSSL_NAMEMAP *namemap, int number,
  200. const char *name)
  201. {
  202. int ret;
  203. HT_VALUE val = { 0 };
  204. NAMENUM_KEY key;
  205. /* If it already exists, we don't add it */
  206. if ((ret = ossl_namemap_name2num(namemap, name)) != 0)
  207. return ret;
  208. if ((number = numname_insert(namemap, number, name)) == 0)
  209. return 0;
  210. /* Using tsan_store alone here is safe since we're under lock */
  211. tsan_store(&namemap->max_number, number);
  212. HT_INIT_KEY(&key);
  213. HT_SET_KEY_STRING_CASE(&key, name, name);
  214. val.value = (void *)(intptr_t)number;
  215. ret = ossl_ht_insert(namemap->namenum_ht, TO_HT_KEY(&key), &val, NULL);
  216. if (!ossl_assert(ret != 0)) /* cannot happen as we are under write lock */
  217. return 0;
  218. if (ret < 1) {
  219. /* unable to insert due to too many collisions */
  220. ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_NAMES);
  221. return 0;
  222. }
  223. return number;
  224. }
  225. int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number,
  226. const char *name)
  227. {
  228. int tmp_number;
  229. #ifndef FIPS_MODULE
  230. if (namemap == NULL)
  231. namemap = ossl_namemap_stored(NULL);
  232. #endif
  233. if (name == NULL || *name == 0 || namemap == NULL)
  234. return 0;
  235. if (!CRYPTO_THREAD_write_lock(namemap->lock))
  236. return 0;
  237. tmp_number = namemap_add_name(namemap, number, name);
  238. CRYPTO_THREAD_unlock(namemap->lock);
  239. return tmp_number;
  240. }
  241. int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
  242. const char *names, const char separator)
  243. {
  244. char *tmp, *p, *q, *endp;
  245. /* Check that we have a namemap */
  246. if (!ossl_assert(namemap != NULL)) {
  247. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  248. return 0;
  249. }
  250. if ((tmp = OPENSSL_strdup(names)) == NULL)
  251. return 0;
  252. if (!CRYPTO_THREAD_write_lock(namemap->lock)) {
  253. OPENSSL_free(tmp);
  254. return 0;
  255. }
  256. /*
  257. * Check that no name is an empty string, and that all names have at
  258. * most one numeric identity together.
  259. */
  260. for (p = tmp; *p != '\0'; p = q) {
  261. int this_number;
  262. size_t l;
  263. if ((q = strchr(p, separator)) == NULL) {
  264. l = strlen(p); /* offset to \0 */
  265. q = p + l;
  266. } else {
  267. l = q - p; /* offset to the next separator */
  268. *q++ = '\0';
  269. }
  270. if (*p == '\0') {
  271. ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME);
  272. number = 0;
  273. goto end;
  274. }
  275. this_number = ossl_namemap_name2num(namemap, p);
  276. if (number == 0) {
  277. number = this_number;
  278. } else if (this_number != 0 && this_number != number) {
  279. ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES,
  280. "\"%s\" has an existing different identity %d (from \"%s\")",
  281. p, this_number, names);
  282. number = 0;
  283. goto end;
  284. }
  285. }
  286. endp = p;
  287. /* Now that we have checked, register all names */
  288. for (p = tmp; p < endp; p = q) {
  289. int this_number;
  290. q = p + strlen(p) + 1;
  291. this_number = namemap_add_name(namemap, number, p);
  292. if (number == 0) {
  293. number = this_number;
  294. } else if (this_number != number) {
  295. ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
  296. "Got number %d when expecting %d",
  297. this_number, number);
  298. number = 0;
  299. goto end;
  300. }
  301. }
  302. end:
  303. CRYPTO_THREAD_unlock(namemap->lock);
  304. OPENSSL_free(tmp);
  305. return number;
  306. }
  307. /*-
  308. * Pre-population
  309. * ==============
  310. */
  311. #ifndef FIPS_MODULE
  312. #include <openssl/evp.h>
  313. /* Creates an initial namemap with names found in the legacy method db */
  314. static void get_legacy_evp_names(int base_nid, int nid, const char *pem_name,
  315. void *arg)
  316. {
  317. int num = 0;
  318. ASN1_OBJECT *obj;
  319. if (base_nid != NID_undef) {
  320. num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(base_nid));
  321. num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(base_nid));
  322. }
  323. if (nid != NID_undef) {
  324. num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(nid));
  325. num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(nid));
  326. if ((obj = OBJ_nid2obj(nid)) != NULL) {
  327. char txtoid[OSSL_MAX_NAME_SIZE];
  328. if (OBJ_obj2txt(txtoid, sizeof(txtoid), obj, 1) > 0)
  329. num = ossl_namemap_add_name(arg, num, txtoid);
  330. }
  331. }
  332. if (pem_name != NULL)
  333. num = ossl_namemap_add_name(arg, num, pem_name);
  334. }
  335. static void get_legacy_cipher_names(const OBJ_NAME *on, void *arg)
  336. {
  337. const EVP_CIPHER *cipher = (void *)OBJ_NAME_get(on->name, on->type);
  338. if (cipher != NULL)
  339. get_legacy_evp_names(NID_undef, EVP_CIPHER_get_type(cipher), NULL, arg);
  340. }
  341. static void get_legacy_md_names(const OBJ_NAME *on, void *arg)
  342. {
  343. const EVP_MD *md = (void *)OBJ_NAME_get(on->name, on->type);
  344. if (md != NULL)
  345. get_legacy_evp_names(0, EVP_MD_get_type(md), NULL, arg);
  346. }
  347. static void get_legacy_pkey_meth_names(const EVP_PKEY_ASN1_METHOD *ameth,
  348. void *arg)
  349. {
  350. int nid = 0, base_nid = 0, flags = 0;
  351. const char *pem_name = NULL;
  352. EVP_PKEY_asn1_get0_info(&nid, &base_nid, &flags, NULL, &pem_name, ameth);
  353. if (nid != NID_undef) {
  354. if ((flags & ASN1_PKEY_ALIAS) == 0) {
  355. switch (nid) {
  356. case EVP_PKEY_DHX:
  357. /* We know that the name "DHX" is used too */
  358. get_legacy_evp_names(0, nid, "DHX", arg);
  359. /* FALLTHRU */
  360. default:
  361. get_legacy_evp_names(0, nid, pem_name, arg);
  362. }
  363. } else {
  364. /*
  365. * Treat aliases carefully, some of them are undesirable, or
  366. * should not be treated as such for providers.
  367. */
  368. switch (nid) {
  369. case EVP_PKEY_SM2:
  370. /*
  371. * SM2 is a separate keytype with providers, not an alias for
  372. * EC.
  373. */
  374. get_legacy_evp_names(0, nid, pem_name, arg);
  375. break;
  376. default:
  377. /* Use the short name of the base nid as the common reference */
  378. get_legacy_evp_names(base_nid, nid, pem_name, arg);
  379. }
  380. }
  381. }
  382. }
  383. #endif
  384. /*-
  385. * Constructors / destructors
  386. * ==========================
  387. */
  388. OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx)
  389. {
  390. #ifndef FIPS_MODULE
  391. int nms;
  392. #endif
  393. OSSL_NAMEMAP *namemap =
  394. ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX);
  395. if (namemap == NULL)
  396. return NULL;
  397. #ifndef FIPS_MODULE
  398. nms = ossl_namemap_empty(namemap);
  399. if (nms < 0) {
  400. /*
  401. * Could not get lock to make the count, so maybe internal objects
  402. * weren't added. This seems safest.
  403. */
  404. return NULL;
  405. }
  406. if (nms == 1) {
  407. int i, end;
  408. /* Before pilfering, we make sure the legacy database is populated */
  409. OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
  410. | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
  411. OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH,
  412. get_legacy_cipher_names, namemap);
  413. OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH,
  414. get_legacy_md_names, namemap);
  415. /* We also pilfer data from the legacy EVP_PKEY_ASN1_METHODs */
  416. for (i = 0, end = EVP_PKEY_asn1_get_count(); i < end; i++)
  417. get_legacy_pkey_meth_names(EVP_PKEY_asn1_get0(i), namemap);
  418. }
  419. #endif
  420. return namemap;
  421. }
  422. OSSL_NAMEMAP *ossl_namemap_new(OSSL_LIB_CTX *libctx)
  423. {
  424. OSSL_NAMEMAP *namemap;
  425. HT_CONFIG htconf = { NULL, NULL, NULL, NAMEMAP_HT_BUCKETS, 1, 1 };
  426. htconf.ctx = libctx;
  427. if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) == NULL)
  428. goto err;
  429. if ((namemap->lock = CRYPTO_THREAD_lock_new()) == NULL)
  430. goto err;
  431. if ((namemap->namenum_ht = ossl_ht_new(&htconf)) == NULL)
  432. goto err;
  433. if ((namemap->numnames = sk_NAMES_new_null()) == NULL)
  434. goto err;
  435. return namemap;
  436. err:
  437. ossl_namemap_free(namemap);
  438. return NULL;
  439. }
  440. void ossl_namemap_free(OSSL_NAMEMAP *namemap)
  441. {
  442. if (namemap == NULL || namemap->stored)
  443. return;
  444. sk_NAMES_pop_free(namemap->numnames, names_free);
  445. ossl_ht_free(namemap->namenum_ht);
  446. CRYPTO_THREAD_lock_free(namemap->lock);
  447. OPENSSL_free(namemap);
  448. }