Skip to content

Commit e66cbf1

Browse files
committed
fixup! crypto: add signDigest/verifyDigest and Ed25519ctx support
1 parent 92b9654 commit e66cbf1

1 file changed

Lines changed: 143 additions & 178 deletions

File tree

src/crypto/crypto_sig.cc

Lines changed: 143 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,7 @@ bool SignTraits::DeriveBits(Environment* env,
704704
bool has_context = (params.flags & SignConfiguration::kHasContextString &&
705705
params.context_string.size() > 0);
706706
bool is_prehashed = params.flags & SignConfiguration::kHasPrehashed;
707+
bool is_sign = params.mode == SignConfiguration::Mode::Sign;
707708

708709
if (has_context && !is_prehashed && !SupportsContextString(key)) {
709710
if (can_throw) crypto::CheckThrow(env, SignBase::Error::ContextUnsupported);
@@ -713,30 +714,7 @@ bool SignTraits::DeriveBits(Environment* env,
713714
// Prehashed signing: the caller already hashed the data and is providing
714715
// the digest directly. Use the low-level EVP_PKEY_sign/EVP_PKEY_verify path.
715716
if (is_prehashed) {
716-
bool is_eddsa = key.id() == EVP_PKEY_ED25519 || key.id() == EVP_PKEY_ED448;
717-
#if OPENSSL_WITH_PQC
718-
bool is_mldsa = key.id() == EVP_PKEY_ML_DSA_44 ||
719-
key.id() == EVP_PKEY_ML_DSA_65 ||
720-
key.id() == EVP_PKEY_ML_DSA_87;
721-
#else
722-
bool is_mldsa = false;
723-
#endif
724-
725-
// One-shot-only algorithms that don't have prehash variants
726-
// (SLH-DSA) are not supported.
727-
if (key.isOneShotVariant() && !is_eddsa && !is_mldsa) {
728-
if (can_throw)
729-
crypto::CheckThrow(env, SignBase::Error::PrehashUnsupported);
730-
return false;
731-
}
732-
733-
// For ML-DSA, context must already be part of the externally computed
734-
// mu value. Passing a context string separately is not supported.
735-
if (has_context && is_mldsa) {
736-
if (can_throw)
737-
crypto::CheckThrow(env, SignBase::Error::ContextUnsupported);
738-
return false;
739-
}
717+
const int key_type = key.id();
740718

741719
EVPKeyCtxPointer pkctx = key.newCtx();
742720
if (!pkctx) [[unlikely]] {
@@ -746,101 +724,105 @@ bool SignTraits::DeriveBits(Environment* env,
746724

747725
int init_ret;
748726

749-
if (is_eddsa) {
727+
switch (key_type) {
728+
case EVP_PKEY_ED25519:
729+
case EVP_PKEY_ED448: {
750730
#ifdef OSSL_SIGNATURE_PARAM_INSTANCE
751-
// For Ed25519ph/Ed448ph, use EVP_PKEY_sign_init_ex with INSTANCE param.
752-
const char* instance_name =
753-
key.id() == EVP_PKEY_ED25519 ? "Ed25519ph" : "Ed448ph";
754-
755-
// Build OSSL_PARAM array with instance and optional context string.
756-
std::vector<OSSL_PARAM> ossl_params;
757-
ossl_params.push_back(OSSL_PARAM_construct_utf8_string(
758-
OSSL_SIGNATURE_PARAM_INSTANCE, const_cast<char*>(instance_name), 0));
759-
760-
if (has_context) {
761-
ossl_params.push_back(OSSL_PARAM_construct_octet_string(
762-
OSSL_SIGNATURE_PARAM_CONTEXT_STRING,
763-
const_cast<unsigned char*>(
764-
params.context_string.data<unsigned char>()),
765-
params.context_string.size()));
766-
}
767-
ossl_params.push_back(OSSL_PARAM_END);
768-
769-
switch (params.mode) {
770-
case SignConfiguration::Mode::Sign:
771-
init_ret = pkctx.initForSignEx(ossl_params.data());
772-
break;
773-
case SignConfiguration::Mode::Verify:
774-
init_ret = pkctx.initForVerifyEx(ossl_params.data());
775-
break;
776-
}
731+
const char* instance_name =
732+
key_type == EVP_PKEY_ED25519 ? "Ed25519ph" : "Ed448ph";
733+
734+
std::vector<OSSL_PARAM> ossl_params;
735+
ossl_params.push_back(
736+
OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE,
737+
const_cast<char*>(instance_name),
738+
0));
739+
740+
if (has_context) {
741+
ossl_params.push_back(OSSL_PARAM_construct_octet_string(
742+
OSSL_SIGNATURE_PARAM_CONTEXT_STRING,
743+
const_cast<unsigned char*>(
744+
params.context_string.data<unsigned char>()),
745+
params.context_string.size()));
746+
}
747+
ossl_params.push_back(OSSL_PARAM_END);
748+
749+
init_ret = is_sign ? pkctx.initForSignEx(ossl_params.data())
750+
: pkctx.initForVerifyEx(ossl_params.data());
751+
break;
777752
#else
778-
if (can_throw)
779-
crypto::CheckThrow(env, SignBase::Error::PrehashUnsupported);
780-
return false;
753+
if (can_throw)
754+
crypto::CheckThrow(env, SignBase::Error::PrehashUnsupported);
755+
return false;
781756
#endif // OSSL_SIGNATURE_PARAM_INSTANCE
782-
} else if (is_mldsa) {
783-
#ifdef OSSL_SIGNATURE_PARAM_MU
784-
// For ML-DSA, use EVP_PKEY_sign_message_init with mu param.
785-
// The caller provides the 64-byte mu value directly.
786-
// Context string is not passed here — it's already incorporated
787-
// into mu by the caller.
788-
int mu_flag = 1;
789-
std::vector<OSSL_PARAM> ossl_params;
790-
ossl_params.push_back(
791-
OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MU, &mu_flag));
792-
ossl_params.push_back(OSSL_PARAM_END);
793-
794-
switch (params.mode) {
795-
case SignConfiguration::Mode::Sign:
796-
init_ret = pkctx.initForSignMessage(ossl_params.data());
797-
break;
798-
case SignConfiguration::Mode::Verify:
799-
init_ret = pkctx.initForVerifyMessage(ossl_params.data());
800-
break;
801-
}
802-
#else
803-
if (can_throw)
804-
crypto::CheckThrow(env, SignBase::Error::PrehashUnsupported);
805-
return false;
806-
#endif // OSSL_SIGNATURE_PARAM_MU
807-
} else {
808-
// RSA, ECDSA, DSA: use standard EVP_PKEY_sign_init path.
809-
switch (params.mode) {
810-
case SignConfiguration::Mode::Sign:
811-
init_ret = pkctx.initForSign();
812-
break;
813-
case SignConfiguration::Mode::Verify:
814-
init_ret = pkctx.initForVerify();
815-
break;
816757
}
817758

818-
if (init_ret <= 0) [[unlikely]] {
819-
if (can_throw) crypto::CheckThrow(env, SignBase::Error::Init);
759+
#if OPENSSL_WITH_PQC
760+
case EVP_PKEY_ML_DSA_44:
761+
case EVP_PKEY_ML_DSA_65:
762+
case EVP_PKEY_ML_DSA_87: {
763+
// Context must already be part of the externally computed mu value.
764+
if (has_context) {
765+
if (can_throw)
766+
crypto::CheckThrow(env, SignBase::Error::ContextUnsupported);
767+
return false;
768+
}
769+
770+
#ifdef OSSL_SIGNATURE_PARAM_MU
771+
int mu_flag = 1;
772+
std::vector<OSSL_PARAM> ossl_params;
773+
ossl_params.push_back(
774+
OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MU, &mu_flag));
775+
ossl_params.push_back(OSSL_PARAM_END);
776+
777+
init_ret = is_sign ? pkctx.initForSignMessage(ossl_params.data())
778+
: pkctx.initForVerifyMessage(ossl_params.data());
779+
break;
780+
#else
781+
if (can_throw)
782+
crypto::CheckThrow(env, SignBase::Error::PrehashUnsupported);
820783
return false;
784+
#endif // OSSL_SIGNATURE_PARAM_MU
821785
}
786+
#endif // OPENSSL_WITH_PQC
822787

823-
int padding = params.flags & SignConfiguration::kHasPadding
824-
? params.padding
825-
: key.getDefaultSignPadding();
788+
default:
789+
if (key.isOneShotVariant()) {
790+
if (can_throw)
791+
crypto::CheckThrow(env, SignBase::Error::PrehashUnsupported);
792+
return false;
793+
}
826794

827-
std::optional<int> salt_length =
828-
params.flags & SignConfiguration::kHasSaltLength
829-
? std::optional<int>(params.salt_length)
830-
: std::nullopt;
795+
init_ret = is_sign ? pkctx.initForSign() : pkctx.initForVerify();
831796

832-
if (!ApplyRSAOptions(key, pkctx.get(), padding, salt_length)) {
833-
if (can_throw) crypto::CheckThrow(env, SignBase::Error::PrivateKey);
834-
return false;
835-
}
797+
if (init_ret <= 0) [[unlikely]] {
798+
if (can_throw) crypto::CheckThrow(env, SignBase::Error::Init);
799+
return false;
800+
}
836801

837-
if (!pkctx.setSignatureMd(params.digest)) {
838-
if (can_throw) crypto::CheckThrow(env, SignBase::Error::Init);
839-
return false;
840-
}
802+
{
803+
int padding = params.flags & SignConfiguration::kHasPadding
804+
? params.padding
805+
: key.getDefaultSignPadding();
806+
807+
std::optional<int> salt_length =
808+
params.flags & SignConfiguration::kHasSaltLength
809+
? std::optional<int>(params.salt_length)
810+
: std::nullopt;
811+
812+
if (!ApplyRSAOptions(key, pkctx.get(), padding, salt_length)) {
813+
if (can_throw) crypto::CheckThrow(env, SignBase::Error::PrivateKey);
814+
return false;
815+
}
816+
817+
if (!pkctx.setSignatureMd(params.digest)) {
818+
if (can_throw) crypto::CheckThrow(env, SignBase::Error::Init);
819+
return false;
820+
}
821+
}
822+
break;
841823
}
842824

843-
if (is_eddsa && init_ret <= 0) [[unlikely]] {
825+
if (init_ret <= 0) [[unlikely]] {
844826
if (can_throw) crypto::CheckThrow(env, SignBase::Error::Init);
845827
return false;
846828
}
@@ -850,36 +832,31 @@ bool SignTraits::DeriveBits(Environment* env,
850832
.len = params.data.size(),
851833
};
852834

853-
switch (params.mode) {
854-
case SignConfiguration::Mode::Sign: {
855-
auto sig = pkctx.sign(data_buf);
856-
if (!sig) [[unlikely]] {
857-
if (can_throw) crypto::CheckThrow(env, SignBase::Error::PrivateKey);
858-
return false;
859-
}
860-
DCHECK(!sig.isSecure());
861-
auto bs = ByteSource::Allocated(sig.release());
835+
if (is_sign) {
836+
auto sig = pkctx.sign(data_buf);
837+
if (!sig) [[unlikely]] {
838+
if (can_throw) crypto::CheckThrow(env, SignBase::Error::PrivateKey);
839+
return false;
840+
}
841+
DCHECK(!sig.isSecure());
842+
auto bs = ByteSource::Allocated(sig.release());
862843

863-
if (UseP1363Encoding(key, params.dsa_encoding)) {
864-
*out = ConvertSignatureToP1363(env, key, std::move(bs));
865-
} else {
866-
*out = std::move(bs);
867-
}
868-
break;
844+
if (UseP1363Encoding(key, params.dsa_encoding)) {
845+
*out = ConvertSignatureToP1363(env, key, std::move(bs));
846+
} else {
847+
*out = std::move(bs);
869848
}
870-
case SignConfiguration::Mode::Verify: {
871-
ncrypto::Buffer<const unsigned char> sig_buf{
872-
.data = params.signature.data<unsigned char>(),
873-
.len = params.signature.size(),
874-
};
875-
auto buf = DataPointer::Alloc(1);
876-
static_cast<char*>(buf.get())[0] = 0;
877-
if (pkctx.verify(sig_buf, data_buf)) {
878-
static_cast<char*>(buf.get())[0] = 1;
879-
}
880-
*out = ByteSource::Allocated(buf.release());
881-
break;
849+
} else {
850+
ncrypto::Buffer<const unsigned char> sig_buf{
851+
.data = params.signature.data<unsigned char>(),
852+
.len = params.signature.size(),
853+
};
854+
auto buf = DataPointer::Alloc(1);
855+
static_cast<char*>(buf.get())[0] = 0;
856+
if (pkctx.verify(sig_buf, data_buf)) {
857+
static_cast<char*>(buf.get())[0] = 1;
882858
}
859+
*out = ByteSource::Allocated(buf.release());
883860
}
884861

885862
return true;
@@ -897,21 +874,13 @@ bool SignTraits::DeriveBits(Environment* env,
897874
.len = params.context_string.size(),
898875
};
899876

900-
switch (params.mode) {
901-
case SignConfiguration::Mode::Sign:
902-
return context.signInitWithContext(key, params.digest, context_buf);
903-
case SignConfiguration::Mode::Verify:
904-
return context.verifyInitWithContext(key, params.digest, context_buf);
905-
}
906-
} else {
907-
switch (params.mode) {
908-
case SignConfiguration::Mode::Sign:
909-
return context.signInit(key, params.digest);
910-
case SignConfiguration::Mode::Verify:
911-
return context.verifyInit(key, params.digest);
912-
}
877+
return is_sign
878+
? context.signInitWithContext(key, params.digest, context_buf)
879+
: context.verifyInitWithContext(
880+
key, params.digest, context_buf);
913881
}
914-
UNREACHABLE();
882+
return is_sign ? context.signInit(key, params.digest)
883+
: context.verifyInit(key, params.digest);
915884
})();
916885

917886
if (!ctx.has_value()) [[unlikely]] {
@@ -933,41 +902,37 @@ bool SignTraits::DeriveBits(Environment* env,
933902
return false;
934903
}
935904

936-
switch (params.mode) {
937-
case SignConfiguration::Mode::Sign: {
938-
if (key.isOneShotVariant()) {
939-
auto data = context.signOneShot(params.data);
940-
if (!data) [[unlikely]] {
941-
if (can_throw) crypto::CheckThrow(env, SignBase::Error::PrivateKey);
942-
return false;
943-
}
944-
DCHECK(!data.isSecure());
945-
*out = ByteSource::Allocated(data.release());
946-
} else {
947-
auto data = context.sign(params.data);
948-
if (!data) [[unlikely]] {
949-
if (can_throw) crypto::CheckThrow(env, SignBase::Error::PrivateKey);
950-
return false;
951-
}
952-
DCHECK(!data.isSecure());
953-
auto bs = ByteSource::Allocated(data.release());
905+
if (is_sign) {
906+
if (key.isOneShotVariant()) {
907+
auto data = context.signOneShot(params.data);
908+
if (!data) [[unlikely]] {
909+
if (can_throw) crypto::CheckThrow(env, SignBase::Error::PrivateKey);
910+
return false;
911+
}
912+
DCHECK(!data.isSecure());
913+
*out = ByteSource::Allocated(data.release());
914+
} else {
915+
auto data = context.sign(params.data);
916+
if (!data) [[unlikely]] {
917+
if (can_throw) crypto::CheckThrow(env, SignBase::Error::PrivateKey);
918+
return false;
919+
}
920+
DCHECK(!data.isSecure());
921+
auto bs = ByteSource::Allocated(data.release());
954922

955-
if (UseP1363Encoding(key, params.dsa_encoding)) {
956-
*out = ConvertSignatureToP1363(env, key, std::move(bs));
957-
} else {
958-
*out = std::move(bs);
959-
}
923+
if (UseP1363Encoding(key, params.dsa_encoding)) {
924+
*out = ConvertSignatureToP1363(env, key, std::move(bs));
925+
} else {
926+
*out = std::move(bs);
960927
}
961-
break;
962928
}
963-
case SignConfiguration::Mode::Verify: {
964-
auto buf = DataPointer::Alloc(1);
965-
static_cast<char*>(buf.get())[0] = 0;
966-
if (context.verify(params.data, params.signature)) {
967-
static_cast<char*>(buf.get())[0] = 1;
968-
}
969-
*out = ByteSource::Allocated(buf.release());
929+
} else {
930+
auto buf = DataPointer::Alloc(1);
931+
static_cast<char*>(buf.get())[0] = 0;
932+
if (context.verify(params.data, params.signature)) {
933+
static_cast<char*>(buf.get())[0] = 1;
970934
}
935+
*out = ByteSource::Allocated(buf.release());
971936
}
972937

973938
return true;

0 commit comments

Comments
 (0)