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