hpke_util.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /*
  2. * Copyright 2022 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 <string.h>
  10. #include <openssl/core_names.h>
  11. #include <openssl/kdf.h>
  12. #include <openssl/params.h>
  13. #include <openssl/err.h>
  14. #include <openssl/proverr.h>
  15. #include <openssl/hpke.h>
  16. #include <openssl/sha.h>
  17. #include <openssl/rand.h>
  18. #include "crypto/ecx.h"
  19. #include "internal/hpke_util.h"
  20. #include "internal/packet.h"
  21. #include "internal/nelem.h"
  22. /*
  23. * Delimiter used in OSSL_HPKE_str2suite
  24. */
  25. #define OSSL_HPKE_STR_DELIMCHAR ','
  26. /*
  27. * table with identifier and synonym strings
  28. * right now, there are 4 synonyms for each - a name, a hex string
  29. * a hex string with a leading zero and a decimal string - more
  30. * could be added but that seems like enough
  31. */
  32. typedef struct {
  33. uint16_t id;
  34. char *synonyms[4];
  35. } synonymttab_t;
  36. /* max length of string we'll try map to a suite */
  37. #define OSSL_HPKE_MAX_SUITESTR 38
  38. /* Define HPKE labels from RFC9180 in hex for EBCDIC compatibility */
  39. /* ASCII: "HPKE-v1", in hex for EBCDIC compatibility */
  40. static const char LABEL_HPKEV1[] = "\x48\x50\x4B\x45\x2D\x76\x31";
  41. /*
  42. * Note that if additions are made to the set of IANA codepoints
  43. * and the tables below, corresponding additions should also be
  44. * made to the synonymtab tables a little further down so that
  45. * OSSL_HPKE_str2suite() continues to function correctly.
  46. *
  47. * The canonical place to check for IANA registered codepoints
  48. * is: https://www.iana.org/assignments/hpke/hpke.xhtml
  49. */
  50. /*
  51. * @brief table of KEMs
  52. * See RFC9180 Section 7.1 "Table 2 KEM IDs"
  53. */
  54. static const OSSL_HPKE_KEM_INFO hpke_kem_tab[] = {
  55. #ifndef OPENSSL_NO_EC
  56. { OSSL_HPKE_KEM_ID_P256, "EC", OSSL_HPKE_KEMSTR_P256,
  57. LN_sha256, SHA256_DIGEST_LENGTH, 65, 65, 32, 0xFF },
  58. { OSSL_HPKE_KEM_ID_P384, "EC", OSSL_HPKE_KEMSTR_P384,
  59. LN_sha384, SHA384_DIGEST_LENGTH, 97, 97, 48, 0xFF },
  60. { OSSL_HPKE_KEM_ID_P521, "EC", OSSL_HPKE_KEMSTR_P521,
  61. LN_sha512, SHA512_DIGEST_LENGTH, 133, 133, 66, 0x01 },
  62. { OSSL_HPKE_KEM_ID_X25519, OSSL_HPKE_KEMSTR_X25519, NULL,
  63. LN_sha256, SHA256_DIGEST_LENGTH,
  64. X25519_KEYLEN, X25519_KEYLEN, X25519_KEYLEN, 0x00 },
  65. { OSSL_HPKE_KEM_ID_X448, OSSL_HPKE_KEMSTR_X448, NULL,
  66. LN_sha512, SHA512_DIGEST_LENGTH,
  67. X448_KEYLEN, X448_KEYLEN, X448_KEYLEN, 0x00 }
  68. #else
  69. { OSSL_HPKE_KEM_ID_RESERVED, NULL, NULL, NULL, 0, 0, 0, 0, 0x00 }
  70. #endif
  71. };
  72. /*
  73. * @brief table of AEADs
  74. * See RFC9180 Section 7.2 "Table 3 KDF IDs"
  75. */
  76. static const OSSL_HPKE_AEAD_INFO hpke_aead_tab[] = {
  77. { OSSL_HPKE_AEAD_ID_AES_GCM_128, LN_aes_128_gcm, 16, 16,
  78. OSSL_HPKE_MAX_NONCELEN },
  79. { OSSL_HPKE_AEAD_ID_AES_GCM_256, LN_aes_256_gcm, 16, 32,
  80. OSSL_HPKE_MAX_NONCELEN },
  81. #ifndef OPENSSL_NO_CHACHA20
  82. # ifndef OPENSSL_NO_POLY1305
  83. { OSSL_HPKE_AEAD_ID_CHACHA_POLY1305, LN_chacha20_poly1305, 16, 32,
  84. OSSL_HPKE_MAX_NONCELEN },
  85. # endif
  86. { OSSL_HPKE_AEAD_ID_EXPORTONLY, NULL, 0, 0, 0 }
  87. #endif
  88. };
  89. /*
  90. * @brief table of KDFs
  91. * See RFC9180 Section 7.3 "Table 5 AEAD IDs"
  92. */
  93. static const OSSL_HPKE_KDF_INFO hpke_kdf_tab[] = {
  94. { OSSL_HPKE_KDF_ID_HKDF_SHA256, LN_sha256, SHA256_DIGEST_LENGTH },
  95. { OSSL_HPKE_KDF_ID_HKDF_SHA384, LN_sha384, SHA384_DIGEST_LENGTH },
  96. { OSSL_HPKE_KDF_ID_HKDF_SHA512, LN_sha512, SHA512_DIGEST_LENGTH }
  97. };
  98. /**
  99. * Synonym tables for KEMs, KDFs and AEADs: idea is to allow
  100. * mapping strings to suites with a little flexibility in terms
  101. * of allowing a name or a couple of forms of number (for
  102. * the IANA codepoint). If new IANA codepoints are allocated
  103. * then these tables should be updated at the same time as the
  104. * others above.
  105. *
  106. * The function to use these is ossl_hpke_str2suite() further down
  107. * this file and shouln't need modification so long as the table
  108. * sizes (i.e. allow exactly 4 synonyms) don't change.
  109. */
  110. static const synonymttab_t kemstrtab[] = {
  111. {OSSL_HPKE_KEM_ID_P256,
  112. {OSSL_HPKE_KEMSTR_P256, "0x10", "0x10", "16" }},
  113. {OSSL_HPKE_KEM_ID_P384,
  114. {OSSL_HPKE_KEMSTR_P384, "0x11", "0x11", "17" }},
  115. {OSSL_HPKE_KEM_ID_P521,
  116. {OSSL_HPKE_KEMSTR_P521, "0x12", "0x12", "18" }},
  117. {OSSL_HPKE_KEM_ID_X25519,
  118. {OSSL_HPKE_KEMSTR_X25519, "0x20", "0x20", "32" }},
  119. {OSSL_HPKE_KEM_ID_X448,
  120. {OSSL_HPKE_KEMSTR_X448, "0x21", "0x21", "33" }}
  121. };
  122. static const synonymttab_t kdfstrtab[] = {
  123. {OSSL_HPKE_KDF_ID_HKDF_SHA256,
  124. {OSSL_HPKE_KDFSTR_256, "0x1", "0x01", "1"}},
  125. {OSSL_HPKE_KDF_ID_HKDF_SHA384,
  126. {OSSL_HPKE_KDFSTR_384, "0x2", "0x02", "2"}},
  127. {OSSL_HPKE_KDF_ID_HKDF_SHA512,
  128. {OSSL_HPKE_KDFSTR_512, "0x3", "0x03", "3"}}
  129. };
  130. static const synonymttab_t aeadstrtab[] = {
  131. {OSSL_HPKE_AEAD_ID_AES_GCM_128,
  132. {OSSL_HPKE_AEADSTR_AES128GCM, "0x1", "0x01", "1"}},
  133. {OSSL_HPKE_AEAD_ID_AES_GCM_256,
  134. {OSSL_HPKE_AEADSTR_AES256GCM, "0x2", "0x02", "2"}},
  135. {OSSL_HPKE_AEAD_ID_CHACHA_POLY1305,
  136. {OSSL_HPKE_AEADSTR_CP, "0x3", "0x03", "3"}},
  137. {OSSL_HPKE_AEAD_ID_EXPORTONLY,
  138. {OSSL_HPKE_AEADSTR_EXP, "ff", "0xff", "255"}}
  139. };
  140. /* Return an object containing KEM constants associated with a EC curve name */
  141. const OSSL_HPKE_KEM_INFO *ossl_HPKE_KEM_INFO_find_curve(const char *curve)
  142. {
  143. int i, sz = OSSL_NELEM(hpke_kem_tab);
  144. for (i = 0; i < sz; ++i) {
  145. const char *group = hpke_kem_tab[i].groupname;
  146. if (group == NULL)
  147. group = hpke_kem_tab[i].keytype;
  148. if (OPENSSL_strcasecmp(curve, group) == 0)
  149. return &hpke_kem_tab[i];
  150. }
  151. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
  152. return NULL;
  153. }
  154. const OSSL_HPKE_KEM_INFO *ossl_HPKE_KEM_INFO_find_id(uint16_t kemid)
  155. {
  156. int i, sz = OSSL_NELEM(hpke_kem_tab);
  157. /*
  158. * this check can happen if we're in a no-ec build and there are no
  159. * KEMS available
  160. */
  161. if (kemid == OSSL_HPKE_KEM_ID_RESERVED) {
  162. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
  163. return NULL;
  164. }
  165. for (i = 0; i != sz; ++i) {
  166. if (hpke_kem_tab[i].kem_id == kemid)
  167. return &hpke_kem_tab[i];
  168. }
  169. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
  170. return NULL;
  171. }
  172. const OSSL_HPKE_KEM_INFO *ossl_HPKE_KEM_INFO_find_random(OSSL_LIB_CTX *ctx)
  173. {
  174. unsigned char rval = 0;
  175. int sz = OSSL_NELEM(hpke_kem_tab);
  176. if (RAND_bytes_ex(ctx, &rval, sizeof(rval), 0) <= 0)
  177. return NULL;
  178. return &hpke_kem_tab[rval % sz];
  179. }
  180. const OSSL_HPKE_KDF_INFO *ossl_HPKE_KDF_INFO_find_id(uint16_t kdfid)
  181. {
  182. int i, sz = OSSL_NELEM(hpke_kdf_tab);
  183. for (i = 0; i != sz; ++i) {
  184. if (hpke_kdf_tab[i].kdf_id == kdfid)
  185. return &hpke_kdf_tab[i];
  186. }
  187. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KDF);
  188. return NULL;
  189. }
  190. const OSSL_HPKE_KDF_INFO *ossl_HPKE_KDF_INFO_find_random(OSSL_LIB_CTX *ctx)
  191. {
  192. unsigned char rval = 0;
  193. int sz = OSSL_NELEM(hpke_kdf_tab);
  194. if (RAND_bytes_ex(ctx, &rval, sizeof(rval), 0) <= 0)
  195. return NULL;
  196. return &hpke_kdf_tab[rval % sz];
  197. }
  198. const OSSL_HPKE_AEAD_INFO *ossl_HPKE_AEAD_INFO_find_id(uint16_t aeadid)
  199. {
  200. int i, sz = OSSL_NELEM(hpke_aead_tab);
  201. for (i = 0; i != sz; ++i) {
  202. if (hpke_aead_tab[i].aead_id == aeadid)
  203. return &hpke_aead_tab[i];
  204. }
  205. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AEAD);
  206. return NULL;
  207. }
  208. const OSSL_HPKE_AEAD_INFO *ossl_HPKE_AEAD_INFO_find_random(OSSL_LIB_CTX *ctx)
  209. {
  210. unsigned char rval = 0;
  211. /* the minus 1 below is so we don't pick the EXPORTONLY codepoint */
  212. int sz = OSSL_NELEM(hpke_aead_tab) - 1;
  213. if (RAND_bytes_ex(ctx, &rval, sizeof(rval), 0) <= 0)
  214. return NULL;
  215. return &hpke_aead_tab[rval % sz];
  216. }
  217. static int kdf_derive(EVP_KDF_CTX *kctx,
  218. unsigned char *out, size_t outlen, int mode,
  219. const unsigned char *salt, size_t saltlen,
  220. const unsigned char *ikm, size_t ikmlen,
  221. const unsigned char *info, size_t infolen)
  222. {
  223. int ret;
  224. OSSL_PARAM params[5], *p = params;
  225. *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
  226. if (salt != NULL)
  227. *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
  228. (char *)salt, saltlen);
  229. if (ikm != NULL)
  230. *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
  231. (char *)ikm, ikmlen);
  232. if (info != NULL)
  233. *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
  234. (char *)info, infolen);
  235. *p = OSSL_PARAM_construct_end();
  236. ret = EVP_KDF_derive(kctx, out, outlen, params) > 0;
  237. if (!ret)
  238. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
  239. return ret;
  240. }
  241. int ossl_hpke_kdf_extract(EVP_KDF_CTX *kctx,
  242. unsigned char *prk, size_t prklen,
  243. const unsigned char *salt, size_t saltlen,
  244. const unsigned char *ikm, size_t ikmlen)
  245. {
  246. return kdf_derive(kctx, prk, prklen, EVP_KDF_HKDF_MODE_EXTRACT_ONLY,
  247. salt, saltlen, ikm, ikmlen, NULL, 0);
  248. }
  249. /* Common code to perform a HKDF expand */
  250. int ossl_hpke_kdf_expand(EVP_KDF_CTX *kctx,
  251. unsigned char *okm, size_t okmlen,
  252. const unsigned char *prk, size_t prklen,
  253. const unsigned char *info, size_t infolen)
  254. {
  255. return kdf_derive(kctx, okm, okmlen, EVP_KDF_HKDF_MODE_EXPAND_ONLY,
  256. NULL, 0, prk, prklen, info, infolen);
  257. }
  258. /*
  259. * See RFC 9180 Section 4 LabelExtract()
  260. */
  261. int ossl_hpke_labeled_extract(EVP_KDF_CTX *kctx,
  262. unsigned char *prk, size_t prklen,
  263. const unsigned char *salt, size_t saltlen,
  264. const char *protocol_label,
  265. const unsigned char *suiteid, size_t suiteidlen,
  266. const char *label,
  267. const unsigned char *ikm, size_t ikmlen)
  268. {
  269. int ret = 0;
  270. size_t label_hpkev1len = 0;
  271. size_t protocol_labellen = 0;
  272. size_t labellen = 0;
  273. size_t labeled_ikmlen = 0;
  274. unsigned char *labeled_ikm = NULL;
  275. WPACKET pkt;
  276. label_hpkev1len = strlen(LABEL_HPKEV1);
  277. protocol_labellen = strlen(protocol_label);
  278. labellen = strlen(label);
  279. labeled_ikmlen = label_hpkev1len + protocol_labellen
  280. + suiteidlen + labellen + ikmlen;
  281. labeled_ikm = OPENSSL_malloc(labeled_ikmlen);
  282. if (labeled_ikm == NULL)
  283. return 0;
  284. /* labeled_ikm = concat("HPKE-v1", suiteid, label, ikm) */
  285. if (!WPACKET_init_static_len(&pkt, labeled_ikm, labeled_ikmlen, 0)
  286. || !WPACKET_memcpy(&pkt, LABEL_HPKEV1, label_hpkev1len)
  287. || !WPACKET_memcpy(&pkt, protocol_label, protocol_labellen)
  288. || !WPACKET_memcpy(&pkt, suiteid, suiteidlen)
  289. || !WPACKET_memcpy(&pkt, label, labellen)
  290. || !WPACKET_memcpy(&pkt, ikm, ikmlen)
  291. || !WPACKET_get_total_written(&pkt, &labeled_ikmlen)
  292. || !WPACKET_finish(&pkt)) {
  293. ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
  294. goto end;
  295. }
  296. ret = ossl_hpke_kdf_extract(kctx, prk, prklen, salt, saltlen,
  297. labeled_ikm, labeled_ikmlen);
  298. end:
  299. WPACKET_cleanup(&pkt);
  300. OPENSSL_cleanse(labeled_ikm, labeled_ikmlen);
  301. OPENSSL_free(labeled_ikm);
  302. return ret;
  303. }
  304. /*
  305. * See RFC 9180 Section 4 LabelExpand()
  306. */
  307. int ossl_hpke_labeled_expand(EVP_KDF_CTX *kctx,
  308. unsigned char *okm, size_t okmlen,
  309. const unsigned char *prk, size_t prklen,
  310. const char *protocol_label,
  311. const unsigned char *suiteid, size_t suiteidlen,
  312. const char *label,
  313. const unsigned char *info, size_t infolen)
  314. {
  315. int ret = 0;
  316. size_t label_hpkev1len = 0;
  317. size_t protocol_labellen = 0;
  318. size_t labellen = 0;
  319. size_t labeled_infolen = 0;
  320. unsigned char *labeled_info = NULL;
  321. WPACKET pkt;
  322. label_hpkev1len = strlen(LABEL_HPKEV1);
  323. protocol_labellen = strlen(protocol_label);
  324. labellen = strlen(label);
  325. labeled_infolen = 2 + okmlen + prklen + label_hpkev1len
  326. + protocol_labellen + suiteidlen + labellen + infolen;
  327. labeled_info = OPENSSL_malloc(labeled_infolen);
  328. if (labeled_info == NULL)
  329. return 0;
  330. /* labeled_info = concat(okmlen, "HPKE-v1", suiteid, label, info) */
  331. if (!WPACKET_init_static_len(&pkt, labeled_info, labeled_infolen, 0)
  332. || !WPACKET_put_bytes_u16(&pkt, okmlen)
  333. || !WPACKET_memcpy(&pkt, LABEL_HPKEV1, label_hpkev1len)
  334. || !WPACKET_memcpy(&pkt, protocol_label, protocol_labellen)
  335. || !WPACKET_memcpy(&pkt, suiteid, suiteidlen)
  336. || !WPACKET_memcpy(&pkt, label, labellen)
  337. || !WPACKET_memcpy(&pkt, info, infolen)
  338. || !WPACKET_get_total_written(&pkt, &labeled_infolen)
  339. || !WPACKET_finish(&pkt)) {
  340. ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
  341. goto end;
  342. }
  343. ret = ossl_hpke_kdf_expand(kctx, okm, okmlen,
  344. prk, prklen, labeled_info, labeled_infolen);
  345. end:
  346. WPACKET_cleanup(&pkt);
  347. OPENSSL_free(labeled_info);
  348. return ret;
  349. }
  350. /* Common code to create a HKDF ctx */
  351. EVP_KDF_CTX *ossl_kdf_ctx_create(const char *kdfname, const char *mdname,
  352. OSSL_LIB_CTX *libctx, const char *propq)
  353. {
  354. EVP_KDF *kdf;
  355. EVP_KDF_CTX *kctx = NULL;
  356. kdf = EVP_KDF_fetch(libctx, kdfname, propq);
  357. kctx = EVP_KDF_CTX_new(kdf);
  358. EVP_KDF_free(kdf);
  359. if (kctx != NULL && mdname != NULL) {
  360. OSSL_PARAM params[3], *p = params;
  361. if (mdname != NULL)
  362. *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
  363. (char *)mdname, 0);
  364. if (propq != NULL)
  365. *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_PROPERTIES,
  366. (char *)propq, 0);
  367. *p = OSSL_PARAM_construct_end();
  368. if (EVP_KDF_CTX_set_params(kctx, params) <= 0) {
  369. EVP_KDF_CTX_free(kctx);
  370. return NULL;
  371. }
  372. }
  373. return kctx;
  374. }
  375. /*
  376. * @brief look for a label into the synonym tables, and return its id
  377. * @param st is the string value
  378. * @param synp is the synonyms labels array
  379. * @param arrsize is the previous array size
  380. * @return 0 when not found, else the matching item id.
  381. */
  382. static uint16_t synonyms_name2id(const char *st, const synonymttab_t *synp,
  383. size_t arrsize)
  384. {
  385. size_t i, j;
  386. for (i = 0; i < arrsize; ++i) {
  387. for (j = 0; j < OSSL_NELEM(synp[i].synonyms); ++j) {
  388. if (OPENSSL_strcasecmp(st, synp[i].synonyms[j]) == 0)
  389. return synp[i].id;
  390. }
  391. }
  392. return 0;
  393. }
  394. /*
  395. * @brief map a string to a HPKE suite based on synonym tables
  396. * @param str is the string value
  397. * @param suite is the resulting suite
  398. * @return 1 for success, otherwise failure
  399. */
  400. int ossl_hpke_str2suite(const char *suitestr, OSSL_HPKE_SUITE *suite)
  401. {
  402. uint16_t kem = 0, kdf = 0, aead = 0;
  403. char *st = NULL, *instrcp = NULL;
  404. size_t inplen;
  405. int labels = 0, result = 0;
  406. int delim_count = 0;
  407. if (suitestr == NULL || suitestr[0] == 0x00 || suite == NULL) {
  408. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
  409. return 0;
  410. }
  411. inplen = OPENSSL_strnlen(suitestr, OSSL_HPKE_MAX_SUITESTR);
  412. if (inplen >= OSSL_HPKE_MAX_SUITESTR) {
  413. ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT);
  414. return 0;
  415. }
  416. /*
  417. * we don't want a delimiter at the end of the string;
  418. * strtok_r/s() doesn't care about that, so we should
  419. */
  420. if (suitestr[inplen - 1] == OSSL_HPKE_STR_DELIMCHAR)
  421. return 0;
  422. /* We want exactly two delimiters in the input string */
  423. for (st = (char *)suitestr; *st != '\0'; st++) {
  424. if (*st == OSSL_HPKE_STR_DELIMCHAR)
  425. delim_count++;
  426. }
  427. if (delim_count != 2)
  428. return 0;
  429. /* Duplicate `suitestr` to allow its parsing */
  430. instrcp = OPENSSL_memdup(suitestr, inplen + 1);
  431. if (instrcp == NULL)
  432. goto fail;
  433. /* See if it contains a mix of our strings and numbers */
  434. st = instrcp;
  435. while (st != NULL && labels < 3) {
  436. char *cp = strchr(st, OSSL_HPKE_STR_DELIMCHAR);
  437. /* add a NUL like strtok would if we're not at the end */
  438. if (cp != NULL)
  439. *cp = '\0';
  440. /* check if string is known or number and if so handle appropriately */
  441. if (labels == 0
  442. && (kem = synonyms_name2id(st, kemstrtab,
  443. OSSL_NELEM(kemstrtab))) == 0)
  444. goto fail;
  445. else if (labels == 1
  446. && (kdf = synonyms_name2id(st, kdfstrtab,
  447. OSSL_NELEM(kdfstrtab))) == 0)
  448. goto fail;
  449. else if (labels == 2
  450. && (aead = synonyms_name2id(st, aeadstrtab,
  451. OSSL_NELEM(aeadstrtab))) == 0)
  452. goto fail;
  453. if (cp == NULL)
  454. st = NULL;
  455. else
  456. st = cp + 1;
  457. ++labels;
  458. }
  459. if (st != NULL || labels != 3)
  460. goto fail;
  461. suite->kem_id = kem;
  462. suite->kdf_id = kdf;
  463. suite->aead_id = aead;
  464. result = 1;
  465. fail:
  466. OPENSSL_free(instrcp);
  467. return result;
  468. }