/* Set KDF parameters based on KDF NID */ static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid) { int kdf_nid, kdfmd_nid, cofactor; const EVP_MD *kdf_md; if (eckdf_nid == NID_undef) return 0; /* Lookup KDF type, cofactor mode and digest */ if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid)) return 0; if (kdf_nid == NID_dh_std_kdf) cofactor = 0; else if (kdf_nid == NID_dh_cofactor_kdf) cofactor = 1; else return 0; if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0) return 0; if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_62) <= 0) return 0; kdf_md = EVP_get_digestbynid(kdfmd_nid); if (!kdf_md) return 0; if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) return 0; return 1; }
static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (strcmp(type, "ec_paramgen_curve") == 0) { int nid; nid = EC_curve_nist2nid(value); if (nid == NID_undef) nid = OBJ_sn2nid(value); if (nid == NID_undef) nid = OBJ_ln2nid(value); if (nid == NID_undef) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); return 0; } return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); #ifndef OPENSSL_NO_SM2 } else if (!strcmp(type, "ec_scheme")) { int scheme; if (!strcmp(value, "secg")) scheme = NID_secg_scheme; else if (!strcmp(value, "sm2")) scheme = NID_sm_scheme; else return -2; return EVP_PKEY_CTX_set_ec_scheme(ctx, scheme); } else if (!strcmp(type, "signer_id")) { return EVP_PKEY_CTX_set_signer_id(ctx, value); } else if (!strcmp(type, "ec_encrypt_param")) { int encrypt_param; if (!(encrypt_param = OBJ_txt2nid(value))) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_EC_ENCRYPT_PARAM); return 0; } return EVP_PKEY_CTX_set_ec_encrypt_param(ctx, encrypt_param); #endif } else if (strcmp(type, "ec_param_enc") == 0) { int param_enc; if (strcmp(value, "explicit") == 0) param_enc = 0; else if (strcmp(value, "named_curve") == 0) param_enc = OPENSSL_EC_NAMED_CURVE; else return -2; return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); } else if (strcmp(type, "ecdh_kdf_md") == 0) { const EVP_MD *md; if ((md = EVP_get_digestbyname(value)) == NULL) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md); } else if (strcmp(type, "ecdh_cofactor_mode") == 0) { int co_mode; co_mode = atoi(value); return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode); } return -2; }
static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (strcmp(type, "ec_paramgen_curve") == 0) { int nid; nid = EC_curve_nist2nid(value); if (nid == NID_undef) nid = OBJ_sn2nid(value); if (nid == NID_undef) nid = OBJ_ln2nid(value); if (nid == NID_undef) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); return 0; } return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); } else if (strcmp(type, "ec_param_enc") == 0) { int param_enc; if (strcmp(value, "explicit") == 0) param_enc = 0; else if (strcmp(value, "named_curve") == 0) param_enc = OPENSSL_EC_NAMED_CURVE; else return -2; return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); } else if (strcmp(type, "ecdh_kdf_md") == 0) { const EVP_MD *md; md = EVP_get_digestbyname(value); if (md == NULL) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md); } else if (strcmp(type, "ecdh_cofactor_mode") == 0) { uint8_t error; int co_mode; co_mode = safe_atoi(value, INT_MIN, INT_MAX, &error); if (error) return 0; /* TODO(KC): Is this the correct error to return here? */ return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode); } return -2; }
static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (!strcmp(type, "ec_paramgen_curve")) { int nid; nid = EC_curve_nist2nid(value); if (nid == NID_undef) nid = OBJ_sn2nid(value); if (nid == NID_undef) nid = OBJ_ln2nid(value); if (nid == NID_undef) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); return 0; } return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); } else if (!strcmp(type, "ec_param_enc")) { int param_enc; if (!strcmp(value, "explicit")) param_enc = 0; else if (!strcmp(value, "named_curve")) param_enc = OPENSSL_EC_NAMED_CURVE; else return -2; return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); } else if (!strcmp(type, "ecdh_kdf_md")) { const EVP_MD *md; if (!(md = EVP_get_digestbyname(value))) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md); } else if (!strcmp(type, "ecdh_cofactor_mode")) { int co_mode; co_mode = atoi(value); return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode); } return -2; }
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; EVP_CIPHER_CTX *ctx; int keylen; X509_ALGOR *talg, *wrap_alg = NULL; ASN1_OBJECT *aoid; ASN1_BIT_STRING *pubkey; ASN1_STRING *wrap_str; ASN1_OCTET_STRING *ukm; unsigned char *penc = NULL; int penclen; int rv = 0; int ecdh_nid, kdf_type, kdf_nid, wrap_nid; const EVP_MD *kdf_md; pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!pctx) return 0; /* Get ephemeral key */ pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, NULL, NULL, NULL)) goto err; X509_ALGOR_get0(&aoid, NULL, NULL, talg); /* Is everything uninitialised? */ if (aoid == OBJ_nid2obj(NID_undef)) { EC_KEY *eckey = pkey->pkey.ec; /* Set the key */ unsigned char *p; penclen = i2o_ECPublicKey(eckey, NULL); if (penclen <= 0) goto err; penc = OPENSSL_malloc(penclen); if (!penc) goto err; p = penc; penclen = i2o_ECPublicKey(eckey, &p); if (penclen <= 0) goto err; ASN1_STRING_set0(pubkey, penc, penclen); pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), V_ASN1_UNDEF, NULL); } /* See if custom paraneters set */ kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx); if (kdf_type <= 0) goto err; if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md)) goto err; ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx); if (ecdh_nid < 0) goto err; else if (ecdh_nid == 0) ecdh_nid = NID_dh_std_kdf; else if (ecdh_nid == 1) ecdh_nid = NID_dh_cofactor_kdf; if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { kdf_type = EVP_PKEY_ECDH_KDF_X9_62; if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) goto err; } else /* Uknown KDF */ goto err; if (kdf_md == NULL) { /* Fixme later for better MD */ kdf_md = EVP_sha1(); if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) goto err; } if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) goto err; /* Lookup NID for KDF+cofactor+digest */ if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid)) goto err; /* Get wrap NID */ ctx = CMS_RecipientInfo_kari_get0_ctx(ri); wrap_nid = EVP_CIPHER_CTX_type(ctx); keylen = EVP_CIPHER_CTX_key_length(ctx); /* Package wrap algorithm in an AlgorithmIdentifier */ wrap_alg = X509_ALGOR_new(); if (!wrap_alg) goto err; wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); wrap_alg->parameter = ASN1_TYPE_new(); if (!wrap_alg->parameter) goto err; if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) goto err; if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { ASN1_TYPE_free(wrap_alg->parameter); wrap_alg->parameter = NULL; } if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) goto err; penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen); if (!penclen) goto err; if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0) goto err; penc = NULL; /* * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter * of another AlgorithmIdentifier. */ penclen = i2d_X509_ALGOR(wrap_alg, &penc); if (!penc || !penclen) goto err; wrap_str = ASN1_STRING_new(); if (!wrap_str) goto err; ASN1_STRING_set0(wrap_str, penc, penclen); penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str); rv = 1; err: OPENSSL_free(penc); X509_ALGOR_free(wrap_alg); return rv; }
static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (!strcmp(type, "ec_paramgen_curve")) { int nid; nid = EC_curve_nist2nid(value); if (nid == NID_undef) nid = OBJ_sn2nid(value); if (nid == NID_undef) nid = OBJ_ln2nid(value); if (nid == NID_undef) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); return 0; } printf("curve = %s\n", value); return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); } else if (!strcmp(type, "ec_param_enc")) { int param_enc; if (!strcmp(value, "explicit")) param_enc = 0; else if (!strcmp(value, "named_curve")) param_enc = OPENSSL_EC_NAMED_CURVE; else return -2; return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); #ifndef OPENSSL_NO_GMSSL } else if (!strcmp(type, "ec_sign_algor")) { int sign_type; if (!strcmp(value, "ecdsa")) sign_type = NID_secg_scheme; else if (!strcmp(value, "sm2")) sign_type = NID_sm_scheme; else return -2; return EVP_PKEY_CTX_set_ec_sign_type(ctx, sign_type); } else if (!strcmp(type, "ec_encrypt_algor")) { int enc_type; if (!strcmp(value, "ecies")) enc_type = NID_secg_scheme; else if (!strcmp(value, "sm2")) enc_type = NID_sm_scheme; else return -2; return EVP_PKEY_CTX_set_ec_enc_type(ctx, enc_type); } else if (!strcmp(type, "ec_derive_algor")) { int dh_type; if (!strcmp(value, "ecdh")) dh_type = NID_secg_scheme; else if (!strcmp(value, "sm2")) dh_type = NID_sm_scheme; else return -2; return EVP_PKEY_CTX_set_ec_dh_type(ctx, dh_type); #endif } else if (!strcmp(type, "ecdh_kdf_md")) { const EVP_MD *md; if (!(md = EVP_get_digestbyname(value))) { ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md); } else if (!strcmp(type, "ecdh_cofactor_mode")) { int co_mode; co_mode = atoi(value); return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode); } return -2; }