int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); /* Decode PSS parameters */ int ret = 0; X509_ALGOR *maskHash; RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); goto err; } const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm); if (mgf1md == NULL || md == NULL) { goto err; } int saltlen = 20; if (pss->saltLength != NULL) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* Could perform more salt length sanity checks but the main * RSA routines will trap other invalid values anyway. */ if (saltlen < 0) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); goto err; } } /* low-level routines support only trailer field 0xbc (value 1) * and PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); goto err; } EVP_PKEY_CTX *pctx; if (!EVP_DigestVerifyInit(ctx, &pctx, md, NULL, pkey) || !EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) || !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, saltlen) || !EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md)) { goto err; } ret = 1; err: RSA_PSS_PARAMS_free(pss); X509_ALGOR_free(maskHash); return ret; }
static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { int rv = -1; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); return -1; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg); if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS); goto err; } /* We have all parameters now set up context */ if (pkey) { if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) goto err; } else { const EVP_MD *checkmd; if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0) goto err; if (EVP_MD_type(md) != EVP_MD_type(checkmd)) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH); goto err; } } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; /* Carry on */ rv = 1; err: RSA_PSS_PARAMS_free(pss); return rv; }
static int test_EVP_DigestSignAlgorithm(void) { int ret = 0; EVP_PKEY *pkey = NULL; EVP_MD_CTX md_ctx; EVP_PKEY_CTX *pkey_ctx; EVP_MD_CTX_init(&md_ctx); pkey = load_example_rsa_key(); if (pkey == NULL) { goto out; } /* Test a simple AlgorithmIdentifier. */ if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) || !test_algorithm_roundtrip(&md_ctx, pkey)) { fprintf(stderr, "RSA with SHA-256 failed\n"); goto out; } EVP_MD_CTX_cleanup(&md_ctx); EVP_MD_CTX_init(&md_ctx); /* Test RSA-PSS with custom parameters. */ if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) || !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) || !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) || !test_algorithm_roundtrip(&md_ctx, pkey)) { fprintf(stderr, "RSA-PSS failed\n"); goto out; } ret = 1; out: if (!ret) { BIO_print_errors_fp(stderr); } EVP_MD_CTX_cleanup(&md_ctx); if (pkey) { EVP_PKEY_free(pkey); } return ret; }
static int rsa_cms_decrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pkctx; X509_ALGOR *cmsalg; int nid; int rv = -1; unsigned char *label = NULL; int labellen = 0; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_OAEP_PARAMS *oaep; X509_ALGOR *maskHash; pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!pkctx) return 0; if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg)) return -1; nid = OBJ_obj2nid(cmsalg->algorithm); if (nid == NID_rsaEncryption) return 1; if (nid != NID_rsaesOaep) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE); return -1; } /* Decode OAEP parameters */ oaep = rsa_oaep_decode(cmsalg, &maskHash); if (oaep == NULL) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(oaep->maskGenFunc, maskHash); if (!mgf1md) goto err; md = rsa_algor_to_md(oaep->hashFunc); if (!md) goto err; if (oaep->pSourceFunc) { X509_ALGOR *plab = oaep->pSourceFunc; if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE); goto err; } if (plab->parameter->type != V_ASN1_OCTET_STRING) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_LABEL); goto err; } label = plab->parameter->value.octet_string->data; /* Stop label being freed when OAEP parameters are freed */ plab->parameter->value.octet_string->data = NULL; labellen = plab->parameter->value.octet_string->length; } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0) goto err; /* Carry on */ rv = 1; err: RSA_OAEP_PARAMS_free(oaep); X509_ALGOR_free(maskHash); return rv; }
static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { int rv = -1; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); return -1; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); if (!mgf1md) goto err; md = rsa_algor_to_md(pss->hashAlgorithm); if (!md) goto err; if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* * Could perform more salt length sanity checks but the main RSA * routines will trap other invalid values anyway. */ if (saltlen < 0) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_SALT_LENGTH); goto err; } } else saltlen = 20; /* * low-level routines support only trailer field 0xbc (value 1) and * PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_TRAILER); goto err; } /* We have all parameters now set up context */ if (pkey) { if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) goto err; } else { const EVP_MD *checkmd; if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0) goto err; if (EVP_MD_type(md) != EVP_MD_type(checkmd)) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH); goto err; } } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; /* Carry on */ rv = 1; err: RSA_PSS_PARAMS_free(pss); X509_ALGOR_free(maskHash); return rv; }
static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, X509_ALGOR *sigalg, ASN1_BIT_STRING *sig, EVP_PKEY *pkey) { int rv = -1; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; EVP_PKEY_CTX *pkctx; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); return -1; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_PSS_PARAMETERS); goto err; } /* Check mask and lookup mask hash algorithm */ if (pss->maskGenAlgorithm) { if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) != NID_mgf1) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_ALGORITHM); goto err; } if (!maskHash) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_PARAMETER); goto err; } mgf1md = EVP_get_digestbyobj(maskHash->algorithm); if (mgf1md == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_MASK_DIGEST); goto err; } } else mgf1md = EVP_sha1(); if (pss->hashAlgorithm) { md = EVP_get_digestbyobj(pss->hashAlgorithm->algorithm); if (md == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_PSS_DIGEST); goto err; } } else md = EVP_sha1(); if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* Could perform more salt length sanity checks but the main * RSA routines will trap other invalid values anyway. */ if (saltlen < 0) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_SALT_LENGTH); goto err; } } else saltlen = 20; /* low-level routines support only trailer field 0xbc (value 1) * and PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_TRAILER); goto err; } /* We have all parameters now set up context */ if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) goto err; if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; /* Carry on */ rv = 2; err: RSA_PSS_PARAMS_free(pss); if (maskHash) X509_ALGOR_free(maskHash); return rv; }
static bool alg_wrap_wrp(const jose_hook_alg_t *alg, jose_cfg_t *cfg, json_t *jwe, json_t *rcp, const json_t *jwk, json_t *cek) { openssl_auto(EVP_PKEY_CTX) *epc = NULL; openssl_auto(EVP_PKEY) *key = NULL; const EVP_MD *md = NULL; const RSA *rsa = NULL; uint8_t *pt = NULL; uint8_t *ct = NULL; bool ret = false; size_t ptl = 0; size_t ctl = 0; int tmp = 0; int pad = 0; if (!json_object_get(cek, "k") && !jose_jwk_gen(cfg, cek)) return false; switch (str2enum(alg->name, NAMES, NULL)) { case 0: pad = RSA_PKCS1_PADDING; tmp = 11; md = EVP_sha1(); break; case 1: pad = RSA_PKCS1_OAEP_PADDING; tmp = 41; md = EVP_sha1(); break; case 2: pad = RSA_PKCS1_OAEP_PADDING; tmp = 41; md = EVP_sha256(); break; default: return false; } key = jose_openssl_jwk_to_EVP_PKEY(cfg, jwk); if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_RSA) return false; ptl = jose_b64_dec(json_object_get(cek, "k"), NULL, 0); if (ptl == SIZE_MAX) return false; rsa = EVP_PKEY_get0_RSA(key); if (!rsa) return false; if ((int) ptl >= RSA_size(rsa) - tmp) return false; epc = EVP_PKEY_CTX_new(key, NULL); if (!epc) return false; if (EVP_PKEY_encrypt_init(epc) <= 0) return false; if (EVP_PKEY_CTX_set_rsa_padding(epc, pad) <= 0) return false; if (pad == RSA_PKCS1_OAEP_PADDING) { if (EVP_PKEY_CTX_set_rsa_oaep_md(epc, md) <= 0) return false; if (EVP_PKEY_CTX_set_rsa_mgf1_md(epc, md) <= 0) return false; } pt = malloc(ptl); if (!pt) return false; if (jose_b64_dec(json_object_get(cek, "k"), pt, ptl) != ptl) goto egress; if (EVP_PKEY_encrypt(epc, NULL, &ctl, pt, ptl) <= 0) goto egress; ct = malloc(ctl); if (!ct) goto egress; if (EVP_PKEY_encrypt(epc, ct, &ctl, pt, ptl) <= 0) goto egress; if (json_object_set_new(rcp, "encrypted_key", jose_b64_enc(ct, ctl)) < 0) goto egress; ret = add_entity(jwe, rcp, "recipients", "header", "encrypted_key", NULL); egress: if (pt) { OPENSSL_cleanse(pt, ptl); free(pt); } free(ct); return ret; }
static bool alg_wrap_unw(const jose_hook_alg_t *alg, jose_cfg_t *cfg, const json_t *jwe, const json_t *rcp, const json_t *jwk, json_t *cek) { openssl_auto(EVP_PKEY_CTX) *epc = NULL; openssl_auto(EVP_PKEY) *key = NULL; const uint8_t *tt = NULL; const EVP_MD *md = NULL; uint8_t *ct = NULL; uint8_t *pt = NULL; uint8_t *rt = NULL; bool ret = false; size_t ctl = 0; size_t ptl = 0; size_t rtl = 0; size_t ttl = 0; int pad = 0; switch (str2enum(alg->name, NAMES, NULL)) { case 0: pad = RSA_PKCS1_PADDING; md = EVP_sha1(); break; case 1: pad = RSA_PKCS1_OAEP_PADDING; md = EVP_sha1(); break; case 2: pad = RSA_PKCS1_OAEP_PADDING; md = EVP_sha256(); break; default: return false; } key = jose_openssl_jwk_to_EVP_PKEY(cfg, jwk); if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_RSA) goto egress; ctl = jose_b64_dec(json_object_get(rcp, "encrypted_key"), NULL, 0); if (ctl == SIZE_MAX) goto egress; ct = malloc(ctl); if (!ct) goto egress; if (jose_b64_dec(json_object_get(rcp, "encrypted_key"), ct, ctl) != ctl) goto egress; ptl = ctl; pt = malloc(ptl); if (!pt) goto egress; epc = EVP_PKEY_CTX_new(key, NULL); if (!epc) goto egress; if (EVP_PKEY_decrypt_init(epc) <= 0) goto egress; if (EVP_PKEY_CTX_set_rsa_padding(epc, pad) <= 0) goto egress; if (pad == RSA_PKCS1_OAEP_PADDING) { if (EVP_PKEY_CTX_set_rsa_oaep_md(epc, md) <= 0) return false; if (EVP_PKEY_CTX_set_rsa_mgf1_md(epc, md) <= 0) goto egress; } /* Handle MMA Attack as prescribed by RFC 3218, always generate a * random buffer of appropriate length so that the same operations * are performed whether decrypt succeeds or not, in an attempt to * foil timing attacks */ rtl = ptl; rt = malloc(rtl); if (!rt) goto egress; if (RAND_bytes(rt, rtl) <= 0) goto egress; ret |= EVP_PKEY_decrypt(epc, pt, &ptl, ct, ctl) > 0; ttl = ret ? ptl : rtl; tt = ret ? pt : rt; ret |= pad == RSA_PKCS1_PADDING; if (json_object_set_new(cek, "k", jose_b64_enc(tt, ttl)) < 0) ret = false; egress: if (pt) { OPENSSL_cleanse(pt, ptl); free(pt); } if (rt) { OPENSSL_cleanse(rt, rtl); free(rt); } free(ct); return ret; }
/* From PSS AlgorithmIdentifier set public key parameters. */ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { int ret = 0; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; EVP_PKEY_CTX *pkctx; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_UNSUPPORTED_SIGNATURE_TYPE); return 0; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_PSS_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); if (!mgf1md) { goto err; } md = rsa_algor_to_md(pss->hashAlgorithm); if (!md) { goto err; } saltlen = 20; if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* Could perform more salt length sanity checks but the main * RSA routines will trap other invalid values anyway. */ if (saltlen < 0) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_SALT_LENGTH); goto err; } } /* low-level routines support only trailer field 0xbc (value 1) * and PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_TRAILER); goto err; } if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) || !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) || !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) || !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) { goto err; } ret = 1; err: RSA_PSS_PARAMS_free(pss); if (maskHash) { X509_ALGOR_free(maskHash); } return ret; }
static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (!value) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING); return 0; } if (!strcmp(type, "rsa_padding_mode")) { int pm; if (!strcmp(value, "pkcs1")) pm = RSA_PKCS1_PADDING; else if (!strcmp(value, "sslv23")) pm = RSA_SSLV23_PADDING; else if (!strcmp(value, "none")) pm = RSA_NO_PADDING; else if (!strcmp(value, "oeap")) pm = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(value, "oaep")) pm = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(value, "x931")) pm = RSA_X931_PADDING; else if (!strcmp(value, "pss")) pm = RSA_PKCS1_PSS_PADDING; else { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE); return -2; } return EVP_PKEY_CTX_set_rsa_padding(ctx, pm); } if (!strcmp(type, "rsa_pss_saltlen")) { int saltlen; saltlen = atoi(value); return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen); } if (!strcmp(type, "rsa_keygen_bits")) { int nbits; nbits = atoi(value); return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits); } if (!strcmp(type, "rsa_keygen_pubexp")) { int ret; BIGNUM *pubexp = NULL; if (!BN_asc2bn(&pubexp, value)) return 0; ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp); if (ret <= 0) BN_free(pubexp); return ret; } if (!strcmp(type, "rsa_mgf1_md")) { const EVP_MD *md; if (!(md = EVP_get_digestbyname(value))) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md); } if (!strcmp(type, "rsa_oaep_md")) { const EVP_MD *md; if (!(md = EVP_get_digestbyname(value))) { RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md); } if (!strcmp(type, "rsa_oaep_label")) { unsigned char *lab; long lablen; int ret; lab = string_to_hex(value, &lablen); if (!lab) return 0; ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen); if (ret <= 0) OPENSSL_free(lab); return ret; } return -2; }