Align EVP_PKEY Ed25519 API with upstream.
Rather than adding a new mode to EVP_PKEY_CTX, upstream chose to tie single-shot signing to EVP_MD_CTX, adding functions which combine EVP_Digest*Update and EVP_Digest*Final. This adds a weird vestigial EVP_MD_CTX and makes the signing digest parameter non-uniform, slightly complicating things. But it means APIs like X509_sign_ctx can work without modification. Align with upstream's APIs. This required a bit of fiddling around evp_test.cc. For consistency and to avoid baking details of parameter input order, I made it eagerly read all inputs before calling SetupContext. Otherwise which attributes are present depend a lot on the shape of the API we use---notably the NO_DEFAULT_DIGEST tests for RSA switch to failing before consuming an input, which is odd. (This only matters because we have some tests which expect the operation to abort the operation early with parameter errors and match against Error. Those probably should not use FileTest to begin with, but I'll tease that apart a later time.) Upstream also named NID_Ed25519 as NID_ED25519, even though the algorithm is normally stylized as "Ed25519". Switch it to match. Change-Id: Id6c8f5715930038e754de50338924d044e908045 Reviewed-on: https://boringssl-review.googlesource.com/17044 Commit-Queue: Steven Valdez <svaldez@google.com> Reviewed-by: Steven Valdez <svaldez@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
parent
ff2394527f
commit
19670949ca
@ -61,14 +61,24 @@
|
||||
#include "../fipsmodule/digest/internal.h"
|
||||
|
||||
|
||||
enum evp_sign_verify_t {
|
||||
evp_sign,
|
||||
evp_verify,
|
||||
};
|
||||
|
||||
static const struct evp_md_pctx_ops md_pctx_ops = {
|
||||
EVP_PKEY_CTX_free,
|
||||
EVP_PKEY_CTX_dup,
|
||||
};
|
||||
|
||||
static int uses_prehash(EVP_MD_CTX *ctx, enum evp_sign_verify_t op) {
|
||||
return (op == evp_sign) ? (ctx->pctx->pmeth->sign != NULL)
|
||||
: (ctx->pctx->pmeth->verify != NULL);
|
||||
}
|
||||
|
||||
static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
|
||||
int is_verify) {
|
||||
enum evp_sign_verify_t op) {
|
||||
if (ctx->pctx == NULL) {
|
||||
ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
|
||||
}
|
||||
@ -77,12 +87,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
}
|
||||
ctx->pctx_ops = &md_pctx_ops;
|
||||
|
||||
if (type == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_verify) {
|
||||
if (op == evp_verify) {
|
||||
if (!EVP_PKEY_verify_init(ctx->pctx)) {
|
||||
return 0;
|
||||
}
|
||||
@ -91,38 +96,63 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) {
|
||||
|
||||
if (type != NULL &&
|
||||
!EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uses_prehash(ctx, op)) {
|
||||
if (type == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_DigestInit_ex(ctx, type, e)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pctx) {
|
||||
*pctx = ctx->pctx;
|
||||
}
|
||||
if (!EVP_DigestInit_ex(ctx, type, e)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type,
|
||||
ENGINE *e, EVP_PKEY *pkey) {
|
||||
return do_sigver_init(ctx, pctx, type, e, pkey, 0);
|
||||
return do_sigver_init(ctx, pctx, type, e, pkey, evp_sign);
|
||||
}
|
||||
|
||||
int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) {
|
||||
return do_sigver_init(ctx, pctx, type, e, pkey, 1);
|
||||
return do_sigver_init(ctx, pctx, type, e, pkey, evp_verify);
|
||||
}
|
||||
|
||||
int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
|
||||
if (!uses_prehash(ctx, evp_sign)) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EVP_DigestUpdate(ctx, data, len);
|
||||
}
|
||||
|
||||
int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
|
||||
if (!uses_prehash(ctx, evp_verify)) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EVP_DigestUpdate(ctx, data, len);
|
||||
}
|
||||
|
||||
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
|
||||
size_t *out_sig_len) {
|
||||
if (!uses_prehash(ctx, evp_sign)) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out_sig) {
|
||||
EVP_MD_CTX tmp_ctx;
|
||||
int ret;
|
||||
@ -144,6 +174,11 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
|
||||
|
||||
int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
|
||||
size_t sig_len) {
|
||||
if (!uses_prehash(ctx, evp_verify)) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_CTX tmp_ctx;
|
||||
int ret;
|
||||
uint8_t md[EVP_MAX_MD_SIZE];
|
||||
@ -157,3 +192,40 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len,
|
||||
const uint8_t *data, size_t data_len) {
|
||||
if (uses_prehash(ctx, evp_sign)) {
|
||||
/* If |out_sig| is NULL, the caller is only querying the maximum output
|
||||
* length. |data| should only be incorporated in the final call. */
|
||||
if (out_sig != NULL &&
|
||||
!EVP_DigestSignUpdate(ctx, data, data_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EVP_DigestSignFinal(ctx, out_sig, out_sig_len);
|
||||
}
|
||||
|
||||
if (ctx->pctx->pmeth->sign_message == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctx->pctx->pmeth->sign_message(ctx->pctx, out_sig, out_sig_len, data,
|
||||
data_len);
|
||||
}
|
||||
|
||||
int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
|
||||
const uint8_t *data, size_t len) {
|
||||
if (uses_prehash(ctx, evp_verify)) {
|
||||
return EVP_DigestVerifyUpdate(ctx, data, len) &&
|
||||
EVP_DigestVerifyFinal(ctx, sig, sig_len);
|
||||
}
|
||||
|
||||
if (ctx->pctx->pmeth->verify_message == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctx->pctx->pmeth->verify_message(ctx->pctx, sig, sig_len, data, len);
|
||||
}
|
||||
|
@ -236,50 +236,6 @@ int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *sig_len,
|
||||
return ctx->pmeth->sign(ctx, sig, sig_len, digest, digest_len);
|
||||
}
|
||||
|
||||
static const EVP_MD *get_signature_md(EVP_PKEY_CTX *ctx) {
|
||||
const EVP_MD *md;
|
||||
if (!EVP_PKEY_CTX_get_signature_md(ctx, &md)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (md == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
int EVP_PKEY_sign_message(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *sig_len,
|
||||
const uint8_t *data, size_t data_len) {
|
||||
if (ctx == NULL || ctx->pmeth == NULL ||
|
||||
(ctx->pmeth->sign == NULL && ctx->pmeth->sign_message == NULL)) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->operation != EVP_PKEY_OP_SIGN) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->pmeth->sign_message != NULL) {
|
||||
return ctx->pmeth->sign_message(ctx, sig, sig_len, data, data_len);
|
||||
}
|
||||
|
||||
/* Don't bother digesting if we are only sampling the length. */
|
||||
if (sig == NULL) {
|
||||
*sig_len = EVP_PKEY_size(EVP_PKEY_CTX_get0_pkey(ctx));
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t digest[EVP_MAX_MD_SIZE];
|
||||
unsigned digest_len;
|
||||
const EVP_MD *md = get_signature_md(ctx);
|
||||
return md != NULL &&
|
||||
EVP_Digest(data, data_len, digest, &digest_len, md, NULL) &&
|
||||
EVP_PKEY_sign(ctx, sig, sig_len, digest, digest_len);
|
||||
}
|
||||
|
||||
int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) {
|
||||
if (ctx == NULL || ctx->pmeth == NULL ||
|
||||
(ctx->pmeth->verify == NULL && ctx->pmeth->verify_message == NULL)) {
|
||||
@ -303,31 +259,6 @@ int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t sig_len,
|
||||
return ctx->pmeth->verify(ctx, sig, sig_len, digest, digest_len);
|
||||
}
|
||||
|
||||
int EVP_PKEY_verify_message(EVP_PKEY_CTX *ctx, const uint8_t *sig,
|
||||
size_t sig_len, const uint8_t *data,
|
||||
size_t data_len) {
|
||||
if (ctx == NULL || ctx->pmeth == NULL ||
|
||||
(ctx->pmeth->verify == NULL && ctx->pmeth->verify_message == NULL)) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return 0;
|
||||
}
|
||||
if (ctx->operation != EVP_PKEY_OP_VERIFY) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->pmeth->verify_message != NULL) {
|
||||
return ctx->pmeth->verify_message(ctx, sig, sig_len, data, data_len);
|
||||
}
|
||||
|
||||
uint8_t digest[EVP_MAX_MD_SIZE];
|
||||
unsigned digest_len;
|
||||
const EVP_MD *md = get_signature_md(ctx);
|
||||
return md != NULL &&
|
||||
EVP_Digest(data, data_len, digest, &digest_len, md, NULL) &&
|
||||
EVP_PKEY_verify(ctx, sig, sig_len, digest, digest_len);
|
||||
}
|
||||
|
||||
int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) {
|
||||
if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
|
||||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
|
@ -621,4 +621,20 @@ TEST(EVPExtraTest, Ed25519) {
|
||||
ASSERT_TRUE(pubkey2);
|
||||
EXPECT_FALSE(EVP_PKEY_cmp(pubkey.get(), pubkey2.get()));
|
||||
EXPECT_FALSE(EVP_PKEY_cmp(privkey.get(), pubkey2.get()));
|
||||
|
||||
// Ed25519 may not be used streaming.
|
||||
bssl::ScopedEVP_MD_CTX ctx;
|
||||
ASSERT_TRUE(
|
||||
EVP_DigestSignInit(ctx.get(), nullptr, nullptr, nullptr, privkey.get()));
|
||||
EXPECT_FALSE(EVP_DigestSignUpdate(ctx.get(), nullptr, 0));
|
||||
size_t len;
|
||||
EXPECT_FALSE(EVP_DigestSignFinal(ctx.get(), nullptr, &len));
|
||||
ERR_clear_error();
|
||||
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_DigestVerifyInit(ctx.get(), nullptr, nullptr, nullptr,
|
||||
privkey.get()));
|
||||
EXPECT_FALSE(EVP_DigestVerifyUpdate(ctx.get(), nullptr, 0));
|
||||
EXPECT_FALSE(EVP_DigestVerifyFinal(ctx.get(), nullptr, 0));
|
||||
ERR_clear_error();
|
||||
}
|
||||
|
@ -185,6 +185,30 @@ static bool ImportKey(FileTest *t, KeyMap *key_map,
|
||||
return true;
|
||||
}
|
||||
|
||||
// SetupContext configures |ctx| based on attributes in |t|, with the exception
|
||||
// of the signing digest which must be configured externally.
|
||||
static bool SetupContext(FileTest *t, EVP_PKEY_CTX *ctx) {
|
||||
if (t->HasAttribute("RSAPadding")) {
|
||||
int padding;
|
||||
if (!GetRSAPadding(t, &padding, t->GetAttributeOrDie("RSAPadding")) ||
|
||||
!EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (t->HasAttribute("PSSSaltLength") &&
|
||||
!EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
ctx, atoi(t->GetAttributeOrDie("PSSSaltLength").c_str()))) {
|
||||
return false;
|
||||
}
|
||||
if (t->HasAttribute("MGF1Digest")) {
|
||||
const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("MGF1Digest"));
|
||||
if (digest == nullptr || !EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, digest)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestEVP(FileTest *t, KeyMap *key_map) {
|
||||
if (t->GetType() == "PrivateKey") {
|
||||
return ImportKey(t, key_map, EVP_parse_private_key,
|
||||
@ -195,26 +219,26 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) {
|
||||
return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key);
|
||||
}
|
||||
|
||||
int (*key_op_init)(EVP_PKEY_CTX *ctx);
|
||||
int (*key_op_init)(EVP_PKEY_CTX *ctx) = nullptr;
|
||||
int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
|
||||
const uint8_t *in, size_t in_len) = nullptr;
|
||||
int (*verify_op)(EVP_PKEY_CTX * ctx, const uint8_t *sig, size_t sig_len,
|
||||
const uint8_t *in, size_t in_len) = nullptr;
|
||||
int (*md_op_init)(EVP_MD_CTX * ctx, EVP_PKEY_CTX * *pctx, const EVP_MD *type,
|
||||
ENGINE *e, EVP_PKEY *pkey) = nullptr;
|
||||
bool is_verify = false;
|
||||
if (t->GetType() == "Decrypt") {
|
||||
key_op_init = EVP_PKEY_decrypt_init;
|
||||
key_op = EVP_PKEY_decrypt;
|
||||
} else if (t->GetType() == "Sign") {
|
||||
key_op_init = EVP_PKEY_sign_init;
|
||||
key_op = EVP_PKEY_sign;
|
||||
} else if (t->GetType() == "SignMessage") {
|
||||
key_op_init = EVP_PKEY_sign_init;
|
||||
key_op = EVP_PKEY_sign_message;
|
||||
} else if (t->GetType() == "Verify") {
|
||||
key_op_init = EVP_PKEY_verify_init;
|
||||
verify_op = EVP_PKEY_verify;
|
||||
is_verify = true;
|
||||
} else if (t->GetType() == "SignMessage") {
|
||||
md_op_init = EVP_DigestSignInit;
|
||||
} else if (t->GetType() == "VerifyMessage") {
|
||||
key_op_init = EVP_PKEY_verify_init;
|
||||
verify_op = EVP_PKEY_verify_message;
|
||||
md_op_init = EVP_DigestVerifyInit;
|
||||
is_verify = true;
|
||||
} else {
|
||||
ADD_FAILURE() << "Unknown test " << t->GetType();
|
||||
return false;
|
||||
@ -228,67 +252,75 @@ static bool TestEVP(FileTest *t, KeyMap *key_map) {
|
||||
}
|
||||
EVP_PKEY *key = (*key_map)[key_name].get();
|
||||
|
||||
std::vector<uint8_t> input;
|
||||
if (!t->GetBytes(&input, "Input")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up the EVP_PKEY_CTX.
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
|
||||
if (!ctx || !key_op_init(ctx.get())) {
|
||||
return false;
|
||||
}
|
||||
const EVP_MD *digest = nullptr;
|
||||
if (t->HasAttribute("Digest")) {
|
||||
const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("Digest"));
|
||||
if (digest == nullptr ||
|
||||
!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (t->HasAttribute("RSAPadding")) {
|
||||
int padding;
|
||||
if (!GetRSAPadding(t, &padding, t->GetAttributeOrDie("RSAPadding")) ||
|
||||
!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), padding)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (t->HasAttribute("PSSSaltLength") &&
|
||||
!EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
ctx.get(), atoi(t->GetAttributeOrDie("PSSSaltLength").c_str()))) {
|
||||
return false;
|
||||
}
|
||||
if (t->HasAttribute("MGF1Digest")) {
|
||||
const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("MGF1Digest"));
|
||||
if (digest == nullptr ||
|
||||
!EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), digest)) {
|
||||
digest = GetDigest(t, t->GetAttributeOrDie("Digest"));
|
||||
if (digest == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (verify_op != nullptr) {
|
||||
std::vector<uint8_t> output;
|
||||
if (!t->GetBytes(&output, "Output") ||
|
||||
!verify_op(ctx.get(), output.data(), output.size(), input.data(),
|
||||
input.size())) {
|
||||
// For verify tests, the "output" is the signature. Read it now so that, for
|
||||
// tests which expect a failure in SetupContext, the attribute is still
|
||||
// consumed.
|
||||
std::vector<uint8_t> input, actual, output;
|
||||
if (!t->GetBytes(&input, "Input") ||
|
||||
(is_verify && !t->GetBytes(&output, "Output"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (md_op_init) {
|
||||
bssl::ScopedEVP_MD_CTX ctx;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
if (!md_op_init(ctx.get(), &pctx, digest, nullptr, key) ||
|
||||
!SetupContext(t, pctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_verify) {
|
||||
return !!EVP_DigestVerify(ctx.get(), output.data(), output.size(),
|
||||
input.data(), input.size());
|
||||
}
|
||||
|
||||
size_t len;
|
||||
if (!EVP_DigestSign(ctx.get(), nullptr, &len, input.data(), input.size())) {
|
||||
return false;
|
||||
}
|
||||
actual.resize(len);
|
||||
if (!EVP_DigestSign(ctx.get(), actual.data(), &len, input.data(),
|
||||
input.size()) ||
|
||||
!t->GetBytes(&output, "Output")) {
|
||||
return false;
|
||||
}
|
||||
actual.resize(len);
|
||||
EXPECT_EQ(Bytes(output), Bytes(actual));
|
||||
return true;
|
||||
}
|
||||
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
|
||||
if (!ctx ||
|
||||
!key_op_init(ctx.get()) ||
|
||||
(digest != nullptr &&
|
||||
!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) ||
|
||||
!SetupContext(t, ctx.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_verify) {
|
||||
return !!EVP_PKEY_verify(ctx.get(), output.data(), output.size(),
|
||||
input.data(), input.size());
|
||||
}
|
||||
|
||||
size_t len;
|
||||
std::vector<uint8_t> actual, output;
|
||||
if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) {
|
||||
return false;
|
||||
}
|
||||
actual.resize(len);
|
||||
if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) {
|
||||
if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size()) ||
|
||||
!t->GetBytes(&output, "Output")) {
|
||||
return false;
|
||||
}
|
||||
actual.resize(len);
|
||||
if (!t->GetBytes(&output, "Output")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EXPECT_EQ(Bytes(output), Bytes(actual));
|
||||
return true;
|
||||
}
|
||||
@ -301,8 +333,9 @@ TEST(EVPTest, TestVectors) {
|
||||
ASSERT_FALSE(result) << "Operation unexpectedly succeeded.";
|
||||
uint32_t err = ERR_peek_error();
|
||||
EXPECT_EQ(t->GetAttributeOrDie("Error"), ERR_reason_error_string(err));
|
||||
} else {
|
||||
ASSERT_TRUE(result) << "Operation unexpectedly failed.";
|
||||
} else if (!result) {
|
||||
ADD_FAILURE() << "Operation unexpectedly failed.";
|
||||
ERR_print_errors_fp(stdout);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -56,6 +56,7 @@
|
||||
|
||||
/* This file is generated by crypto/obj/objects.go. */
|
||||
|
||||
|
||||
#define NUM_NID 950
|
||||
|
||||
static const uint8_t kObjectData[] = {
|
||||
@ -1811,7 +1812,7 @@ static const uint8_t kObjectData[] = {
|
||||
0x2b, 0x81, 0x04, 0x01, 0x0e, 0x02,
|
||||
/* NID_dhSinglePass_cofactorDH_sha512kdf_scheme */
|
||||
0x2b, 0x81, 0x04, 0x01, 0x0e, 0x03,
|
||||
/* NID_Ed25519 */
|
||||
/* NID_ED25519 */
|
||||
0x2b, 0x65, 0x70,
|
||||
};
|
||||
|
||||
@ -3442,7 +3443,7 @@ static const ASN1_OBJECT kObjects[NUM_NID] = {
|
||||
{"dh-std-kdf", "dh-std-kdf", NID_dh_std_kdf, 0, NULL, 0},
|
||||
{"dh-cofactor-kdf", "dh-cofactor-kdf", NID_dh_cofactor_kdf, 0, NULL, 0},
|
||||
{"X25519", "X25519", NID_X25519, 0, NULL, 0},
|
||||
{"Ed25519", "Ed25519", NID_Ed25519, 3, &kObjectData[6175], 0},
|
||||
{"ED25519", "ED25519", NID_ED25519, 3, &kObjectData[6175], 0},
|
||||
};
|
||||
|
||||
static const unsigned kNIDsInShortNameOrder[] = {
|
||||
@ -3531,7 +3532,7 @@ static const unsigned kNIDsInShortNameOrder[] = {
|
||||
70 /* DSA-SHA1-old */,
|
||||
67 /* DSA-old */,
|
||||
297 /* DVCS */,
|
||||
949 /* Ed25519 */,
|
||||
949 /* ED25519 */,
|
||||
99 /* GN */,
|
||||
855 /* HMAC */,
|
||||
780 /* HMAC-MD5 */,
|
||||
@ -4404,7 +4405,7 @@ static const unsigned kNIDsInLongNameOrder[] = {
|
||||
382 /* Directory */,
|
||||
392 /* Domain */,
|
||||
132 /* E-mail Protection */,
|
||||
949 /* Ed25519 */,
|
||||
949 /* ED25519 */,
|
||||
389 /* Enterprises */,
|
||||
384 /* Experimental */,
|
||||
372 /* Extended OCSP Status */,
|
||||
@ -5332,27 +5333,39 @@ static const unsigned kNIDsInLongNameOrder[] = {
|
||||
};
|
||||
|
||||
static const unsigned kNIDsInOIDOrder[] = {
|
||||
434 /* 0.9 (OBJ_data) */, 182 /* 1.2 (OBJ_member_body) */,
|
||||
379 /* 1.3 (OBJ_org) */, 676 /* 1.3 (OBJ_identified_organization) */,
|
||||
11 /* 2.5 (OBJ_X500) */, 647 /* 2.23 (OBJ_international_organizations) */,
|
||||
380 /* 1.3.6 (OBJ_dod) */, 12 /* 2.5.4 (OBJ_X509) */,
|
||||
378 /* 2.5.8 (OBJ_X500algorithms) */, 81 /* 2.5.29 (OBJ_id_ce) */,
|
||||
512 /* 2.23.42 (OBJ_id_set) */, 678 /* 2.23.43 (OBJ_wap) */,
|
||||
435 /* 0.9.2342 (OBJ_pss) */, 183 /* 1.2.840 (OBJ_ISO_US) */,
|
||||
381 /* 1.3.6.1 (OBJ_iana) */, 949 /* 1.3.101.112 (OBJ_Ed25519) */,
|
||||
434 /* 0.9 (OBJ_data) */,
|
||||
182 /* 1.2 (OBJ_member_body) */,
|
||||
379 /* 1.3 (OBJ_org) */,
|
||||
676 /* 1.3 (OBJ_identified_organization) */,
|
||||
11 /* 2.5 (OBJ_X500) */,
|
||||
647 /* 2.23 (OBJ_international_organizations) */,
|
||||
380 /* 1.3.6 (OBJ_dod) */,
|
||||
12 /* 2.5.4 (OBJ_X509) */,
|
||||
378 /* 2.5.8 (OBJ_X500algorithms) */,
|
||||
81 /* 2.5.29 (OBJ_id_ce) */,
|
||||
512 /* 2.23.42 (OBJ_id_set) */,
|
||||
678 /* 2.23.43 (OBJ_wap) */,
|
||||
435 /* 0.9.2342 (OBJ_pss) */,
|
||||
183 /* 1.2.840 (OBJ_ISO_US) */,
|
||||
381 /* 1.3.6.1 (OBJ_iana) */,
|
||||
949 /* 1.3.101.112 (OBJ_ED25519) */,
|
||||
677 /* 1.3.132 (OBJ_certicom_arc) */,
|
||||
394 /* 2.5.1.5 (OBJ_selected_attribute_types) */,
|
||||
13 /* 2.5.4.3 (OBJ_commonName) */, 100 /* 2.5.4.4 (OBJ_surname) */,
|
||||
105 /* 2.5.4.5 (OBJ_serialNumber) */, 14 /* 2.5.4.6 (OBJ_countryName) */,
|
||||
13 /* 2.5.4.3 (OBJ_commonName) */,
|
||||
100 /* 2.5.4.4 (OBJ_surname) */,
|
||||
105 /* 2.5.4.5 (OBJ_serialNumber) */,
|
||||
14 /* 2.5.4.6 (OBJ_countryName) */,
|
||||
15 /* 2.5.4.7 (OBJ_localityName) */,
|
||||
16 /* 2.5.4.8 (OBJ_stateOrProvinceName) */,
|
||||
660 /* 2.5.4.9 (OBJ_streetAddress) */,
|
||||
17 /* 2.5.4.10 (OBJ_organizationName) */,
|
||||
18 /* 2.5.4.11 (OBJ_organizationalUnitName) */,
|
||||
106 /* 2.5.4.12 (OBJ_title) */, 107 /* 2.5.4.13 (OBJ_description) */,
|
||||
106 /* 2.5.4.12 (OBJ_title) */,
|
||||
107 /* 2.5.4.13 (OBJ_description) */,
|
||||
859 /* 2.5.4.14 (OBJ_searchGuide) */,
|
||||
860 /* 2.5.4.15 (OBJ_businessCategory) */,
|
||||
861 /* 2.5.4.16 (OBJ_postalAddress) */, 661 /* 2.5.4.17 (OBJ_postalCode) */,
|
||||
861 /* 2.5.4.16 (OBJ_postalAddress) */,
|
||||
661 /* 2.5.4.17 (OBJ_postalCode) */,
|
||||
862 /* 2.5.4.18 (OBJ_postOfficeBox) */,
|
||||
863 /* 2.5.4.19 (OBJ_physicalDeliveryOfficeName) */,
|
||||
864 /* 2.5.4.20 (OBJ_telephoneNumber) */,
|
||||
@ -5366,15 +5379,18 @@ static const unsigned kNIDsInOIDOrder[] = {
|
||||
872 /* 2.5.4.28 (OBJ_preferredDeliveryMethod) */,
|
||||
873 /* 2.5.4.29 (OBJ_presentationAddress) */,
|
||||
874 /* 2.5.4.30 (OBJ_supportedApplicationContext) */,
|
||||
875 /* 2.5.4.31 (OBJ_member) */, 876 /* 2.5.4.32 (OBJ_owner) */,
|
||||
877 /* 2.5.4.33 (OBJ_roleOccupant) */, 878 /* 2.5.4.34 (OBJ_seeAlso) */,
|
||||
875 /* 2.5.4.31 (OBJ_member) */,
|
||||
876 /* 2.5.4.32 (OBJ_owner) */,
|
||||
877 /* 2.5.4.33 (OBJ_roleOccupant) */,
|
||||
878 /* 2.5.4.34 (OBJ_seeAlso) */,
|
||||
879 /* 2.5.4.35 (OBJ_userPassword) */,
|
||||
880 /* 2.5.4.36 (OBJ_userCertificate) */,
|
||||
881 /* 2.5.4.37 (OBJ_cACertificate) */,
|
||||
882 /* 2.5.4.38 (OBJ_authorityRevocationList) */,
|
||||
883 /* 2.5.4.39 (OBJ_certificateRevocationList) */,
|
||||
884 /* 2.5.4.40 (OBJ_crossCertificatePair) */,
|
||||
173 /* 2.5.4.41 (OBJ_name) */, 99 /* 2.5.4.42 (OBJ_givenName) */,
|
||||
173 /* 2.5.4.41 (OBJ_name) */,
|
||||
99 /* 2.5.4.42 (OBJ_givenName) */,
|
||||
101 /* 2.5.4.43 (OBJ_initials) */,
|
||||
509 /* 2.5.4.44 (OBJ_generationQualifier) */,
|
||||
503 /* 2.5.4.45 (OBJ_x500UniqueIdentifier) */,
|
||||
@ -5386,7 +5402,8 @@ static const unsigned kNIDsInOIDOrder[] = {
|
||||
889 /* 2.5.4.51 (OBJ_houseIdentifier) */,
|
||||
890 /* 2.5.4.52 (OBJ_supportedAlgorithms) */,
|
||||
891 /* 2.5.4.53 (OBJ_deltaRevocationList) */,
|
||||
892 /* 2.5.4.54 (OBJ_dmdName) */, 510 /* 2.5.4.65 (OBJ_pseudonym) */,
|
||||
892 /* 2.5.4.54 (OBJ_dmdName) */,
|
||||
510 /* 2.5.4.65 (OBJ_pseudonym) */,
|
||||
400 /* 2.5.4.72 (OBJ_role) */,
|
||||
769 /* 2.5.29.9 (OBJ_subject_directory_attributes) */,
|
||||
82 /* 2.5.29.14 (OBJ_subject_key_identifier) */,
|
||||
@ -5395,7 +5412,8 @@ static const unsigned kNIDsInOIDOrder[] = {
|
||||
85 /* 2.5.29.17 (OBJ_subject_alt_name) */,
|
||||
86 /* 2.5.29.18 (OBJ_issuer_alt_name) */,
|
||||
87 /* 2.5.29.19 (OBJ_basic_constraints) */,
|
||||
88 /* 2.5.29.20 (OBJ_crl_number) */, 141 /* 2.5.29.21 (OBJ_crl_reason) */,
|
||||
88 /* 2.5.29.20 (OBJ_crl_number) */,
|
||||
141 /* 2.5.29.21 (OBJ_crl_reason) */,
|
||||
430 /* 2.5.29.23 (OBJ_hold_instruction_code) */,
|
||||
142 /* 2.5.29.24 (OBJ_invalidity_date) */,
|
||||
140 /* 2.5.29.27 (OBJ_delta_crl) */,
|
||||
@ -5411,16 +5429,26 @@ static const unsigned kNIDsInOIDOrder[] = {
|
||||
857 /* 2.5.29.46 (OBJ_freshest_crl) */,
|
||||
748 /* 2.5.29.54 (OBJ_inhibit_any_policy) */,
|
||||
402 /* 2.5.29.55 (OBJ_target_information) */,
|
||||
403 /* 2.5.29.56 (OBJ_no_rev_avail) */, 513 /* 2.23.42.0 (OBJ_set_ctype) */,
|
||||
514 /* 2.23.42.1 (OBJ_set_msgExt) */, 515 /* 2.23.42.3 (OBJ_set_attr) */,
|
||||
516 /* 2.23.42.5 (OBJ_set_policy) */, 517 /* 2.23.42.7 (OBJ_set_certExt) */,
|
||||
518 /* 2.23.42.8 (OBJ_set_brand) */, 679 /* 2.23.43.1 (OBJ_wap_wsg) */,
|
||||
382 /* 1.3.6.1.1 (OBJ_Directory) */, 383 /* 1.3.6.1.2 (OBJ_Management) */,
|
||||
384 /* 1.3.6.1.3 (OBJ_Experimental) */, 385 /* 1.3.6.1.4 (OBJ_Private) */,
|
||||
386 /* 1.3.6.1.5 (OBJ_Security) */, 387 /* 1.3.6.1.6 (OBJ_SNMPv2) */,
|
||||
388 /* 1.3.6.1.7 (OBJ_Mail) */, 376 /* 1.3.14.3.2 (OBJ_algorithm) */,
|
||||
395 /* 2.5.1.5.55 (OBJ_clearance) */, 19 /* 2.5.8.1.1 (OBJ_rsa) */,
|
||||
96 /* 2.5.8.3.100 (OBJ_mdc2WithRSA) */, 95 /* 2.5.8.3.101 (OBJ_mdc2) */,
|
||||
403 /* 2.5.29.56 (OBJ_no_rev_avail) */,
|
||||
513 /* 2.23.42.0 (OBJ_set_ctype) */,
|
||||
514 /* 2.23.42.1 (OBJ_set_msgExt) */,
|
||||
515 /* 2.23.42.3 (OBJ_set_attr) */,
|
||||
516 /* 2.23.42.5 (OBJ_set_policy) */,
|
||||
517 /* 2.23.42.7 (OBJ_set_certExt) */,
|
||||
518 /* 2.23.42.8 (OBJ_set_brand) */,
|
||||
679 /* 2.23.43.1 (OBJ_wap_wsg) */,
|
||||
382 /* 1.3.6.1.1 (OBJ_Directory) */,
|
||||
383 /* 1.3.6.1.2 (OBJ_Management) */,
|
||||
384 /* 1.3.6.1.3 (OBJ_Experimental) */,
|
||||
385 /* 1.3.6.1.4 (OBJ_Private) */,
|
||||
386 /* 1.3.6.1.5 (OBJ_Security) */,
|
||||
387 /* 1.3.6.1.6 (OBJ_SNMPv2) */,
|
||||
388 /* 1.3.6.1.7 (OBJ_Mail) */,
|
||||
376 /* 1.3.14.3.2 (OBJ_algorithm) */,
|
||||
395 /* 2.5.1.5.55 (OBJ_clearance) */,
|
||||
19 /* 2.5.8.1.1 (OBJ_rsa) */,
|
||||
96 /* 2.5.8.3.100 (OBJ_mdc2WithRSA) */,
|
||||
95 /* 2.5.8.3.101 (OBJ_mdc2) */,
|
||||
746 /* 2.5.29.32.0 (OBJ_any_policy) */,
|
||||
910 /* 2.5.29.37.0 (OBJ_anyExtendedKeyUsage) */,
|
||||
519 /* 2.23.42.0.0 (OBJ_setct_PANData) */,
|
||||
@ -5535,22 +5563,27 @@ static const unsigned kNIDsInOIDOrder[] = {
|
||||
638 /* 2.23.42.8.34 (OBJ_set_brand_AmericanExpress) */,
|
||||
639 /* 2.23.42.8.35 (OBJ_set_brand_JCB) */,
|
||||
805 /* 1.2.643.2.2 (OBJ_cryptopro) */,
|
||||
806 /* 1.2.643.2.9 (OBJ_cryptocom) */, 184 /* 1.2.840.10040 (OBJ_X9_57) */,
|
||||
806 /* 1.2.643.2.9 (OBJ_cryptocom) */,
|
||||
184 /* 1.2.840.10040 (OBJ_X9_57) */,
|
||||
405 /* 1.2.840.10045 (OBJ_ansi_X9_62) */,
|
||||
389 /* 1.3.6.1.4.1 (OBJ_Enterprises) */,
|
||||
504 /* 1.3.6.1.7.1 (OBJ_mime_mhs) */,
|
||||
104 /* 1.3.14.3.2.3 (OBJ_md5WithRSA) */,
|
||||
29 /* 1.3.14.3.2.6 (OBJ_des_ecb) */, 31 /* 1.3.14.3.2.7 (OBJ_des_cbc) */,
|
||||
29 /* 1.3.14.3.2.6 (OBJ_des_ecb) */,
|
||||
31 /* 1.3.14.3.2.7 (OBJ_des_cbc) */,
|
||||
45 /* 1.3.14.3.2.8 (OBJ_des_ofb64) */,
|
||||
30 /* 1.3.14.3.2.9 (OBJ_des_cfb64) */,
|
||||
377 /* 1.3.14.3.2.11 (OBJ_rsaSignature) */,
|
||||
67 /* 1.3.14.3.2.12 (OBJ_dsa_2) */, 66 /* 1.3.14.3.2.13 (OBJ_dsaWithSHA) */,
|
||||
67 /* 1.3.14.3.2.12 (OBJ_dsa_2) */,
|
||||
66 /* 1.3.14.3.2.13 (OBJ_dsaWithSHA) */,
|
||||
42 /* 1.3.14.3.2.15 (OBJ_shaWithRSAEncryption) */,
|
||||
32 /* 1.3.14.3.2.17 (OBJ_des_ede_ecb) */, 41 /* 1.3.14.3.2.18 (OBJ_sha) */,
|
||||
32 /* 1.3.14.3.2.17 (OBJ_des_ede_ecb) */,
|
||||
41 /* 1.3.14.3.2.18 (OBJ_sha) */,
|
||||
64 /* 1.3.14.3.2.26 (OBJ_sha1) */,
|
||||
70 /* 1.3.14.3.2.27 (OBJ_dsaWithSHA1_2) */,
|
||||
115 /* 1.3.14.3.2.29 (OBJ_sha1WithRSA) */,
|
||||
117 /* 1.3.36.3.2.1 (OBJ_ripemd160) */, 143 /* 1.3.101.1.4.1 (OBJ_sxnet) */,
|
||||
117 /* 1.3.36.3.2.1 (OBJ_ripemd160) */,
|
||||
143 /* 1.3.101.1.4.1 (OBJ_sxnet) */,
|
||||
721 /* 1.3.132.0.1 (OBJ_sect163k1) */,
|
||||
722 /* 1.3.132.0.2 (OBJ_sect163r1) */,
|
||||
728 /* 1.3.132.0.3 (OBJ_sect239k1) */,
|
||||
@ -5614,7 +5647,8 @@ static const unsigned kNIDsInOIDOrder[] = {
|
||||
816 /* 1.2.643.2.2.23 (OBJ_id_GostR3411_94_prf) */,
|
||||
817 /* 1.2.643.2.2.98 (OBJ_id_GostR3410_2001DH) */,
|
||||
818 /* 1.2.643.2.2.99 (OBJ_id_GostR3410_94DH) */,
|
||||
1 /* 1.2.840.113549 (OBJ_rsadsi) */, 185 /* 1.2.840.10040.4 (OBJ_X9cm) */,
|
||||
1 /* 1.2.840.113549 (OBJ_rsadsi) */,
|
||||
185 /* 1.2.840.10040.4 (OBJ_X9cm) */,
|
||||
127 /* 1.3.6.1.5.5.7 (OBJ_id_pkix) */,
|
||||
505 /* 1.3.6.1.7.1.1 (OBJ_mime_mhs_headings) */,
|
||||
506 /* 1.3.6.1.7.1.2 (OBJ_mime_mhs_bodies) */,
|
||||
|
@ -937,4 +937,4 @@ dhSinglePass_cofactorDH_sha512kdf_scheme 945
|
||||
dh_std_kdf 946
|
||||
dh_cofactor_kdf 947
|
||||
X25519 948
|
||||
Ed25519 949
|
||||
ED25519 949
|
||||
|
@ -88,7 +88,7 @@ static const nid_triple kTriples[] = {
|
||||
/* The following algorithms use more complex (or simpler) parameters. The
|
||||
* digest "undef" indicates the caller should handle this explicitly. */
|
||||
{NID_rsassaPss, NID_undef, NID_rsaEncryption},
|
||||
{NID_Ed25519, NID_undef, NID_Ed25519},
|
||||
{NID_ED25519, NID_undef, NID_ED25519},
|
||||
};
|
||||
|
||||
int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, int *out_pkey_nid) {
|
||||
|
@ -1335,4 +1335,4 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
|
||||
: X25519
|
||||
|
||||
# See draft-ietf-curdle-pkix-04.
|
||||
1 3 101 112 : Ed25519
|
||||
1 3 101 112 : ED25519
|
||||
|
@ -104,8 +104,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
|
||||
|| !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
|
||||
if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) {
|
||||
outl = 0;
|
||||
OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
|
@ -73,6 +73,7 @@
|
||||
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
|
||||
ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
|
||||
{
|
||||
EVP_MD_CTX ctx;
|
||||
uint8_t *buf_in = NULL;
|
||||
int ret = 0, inl = 0;
|
||||
|
||||
@ -86,9 +87,9 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (ctx == NULL ||
|
||||
!x509_digest_verify_init(ctx, a)) {
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
|
||||
if (!x509_digest_verify_init(&ctx, a, pkey)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -99,19 +100,19 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_verify_message(ctx, signature->data,
|
||||
(size_t)signature->length, buf_in, inl)) {
|
||||
if (!EVP_DigestVerify(&ctx, signature->data, (size_t)signature->length,
|
||||
buf_in, inl)) {
|
||||
OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
err:
|
||||
if (buf_in != NULL) {
|
||||
OPENSSL_cleanse(buf_in, (unsigned int)inl);
|
||||
OPENSSL_cleanse(buf_in, inl);
|
||||
OPENSSL_free(buf_in);
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
@ -66,9 +66,8 @@
|
||||
|
||||
|
||||
int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
|
||||
const EVP_MD *digest = EVP_MD_CTX_md(ctx);
|
||||
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
|
||||
if (digest == NULL || pkey == NULL) {
|
||||
if (pkey == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
|
||||
return 0;
|
||||
}
|
||||
@ -84,8 +83,18 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_PKEY_id(pkey) == EVP_PKEY_ED25519) {
|
||||
return X509_ALGOR_set0(algor, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
|
||||
}
|
||||
|
||||
/* Default behavior: look up the OID for the algorithm/hash pair and encode
|
||||
* that. */
|
||||
const EVP_MD *digest = EVP_MD_CTX_md(ctx);
|
||||
if (digest == NULL) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sign_nid;
|
||||
if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest),
|
||||
EVP_PKEY_id(pkey))) {
|
||||
@ -101,11 +110,8 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_digest_verify_init(EVP_PKEY_CTX *ctx, X509_ALGOR *sigalg) {
|
||||
if (!EVP_PKEY_verify_init(ctx)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
|
||||
EVP_PKEY *pkey) {
|
||||
/* Convert the signature OID into digest and public key OIDs. */
|
||||
int sigalg_nid = OBJ_obj2nid(sigalg->algorithm);
|
||||
int digest_nid, pkey_nid;
|
||||
@ -115,7 +121,6 @@ int x509_digest_verify_init(EVP_PKEY_CTX *ctx, X509_ALGOR *sigalg) {
|
||||
}
|
||||
|
||||
/* Check the public key OID matches the public key type. */
|
||||
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
|
||||
if (pkey_nid != EVP_PKEY_id(pkey)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
|
||||
return 0;
|
||||
@ -124,14 +129,14 @@ int x509_digest_verify_init(EVP_PKEY_CTX *ctx, X509_ALGOR *sigalg) {
|
||||
/* NID_undef signals that there are custom parameters to set. */
|
||||
if (digest_nid == NID_undef) {
|
||||
if (sigalg_nid == NID_rsassaPss) {
|
||||
return x509_rsa_pss_to_ctx(ctx, sigalg);
|
||||
return x509_rsa_pss_to_ctx(ctx, sigalg, pkey);
|
||||
}
|
||||
if (sigalg_nid == NID_Ed25519) {
|
||||
if (sigalg_nid == NID_ED25519) {
|
||||
if (sigalg->parameter != NULL) {
|
||||
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
return 1; /* Nothing to configure. */
|
||||
return EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey);
|
||||
}
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
|
||||
return 0;
|
||||
@ -144,5 +149,5 @@ int x509_digest_verify_init(EVP_PKEY_CTX *ctx, X509_ALGOR *sigalg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EVP_PKEY_CTX_set_signature_md(ctx, digest);
|
||||
return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey);
|
||||
}
|
||||
|
@ -28,8 +28,9 @@ extern "C" {
|
||||
|
||||
/* x509_rsa_pss_to_ctx configures |ctx| for an RSA-PSS operation based on
|
||||
* signature algorithm parameters in |sigalg| (which must have type
|
||||
* |NID_rsassaPss|). It returns one on success and zero on error. */
|
||||
int x509_rsa_pss_to_ctx(EVP_PKEY_CTX *ctx, X509_ALGOR *sigalg);
|
||||
* |NID_rsassaPss|) and key |pkey|. It returns one on success and zero on
|
||||
* error. */
|
||||
int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey);
|
||||
|
||||
/* x509_rsa_pss_to_ctx sets |algor| to the signature algorithm parameters for
|
||||
* |ctx|, which must have been configured for an RSA-PSS signing operation. It
|
||||
@ -51,9 +52,11 @@ int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
|
||||
int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
|
||||
|
||||
/* x509_digest_verify_init sets up |ctx| for a signature verification operation
|
||||
* with parameters from |algor|. The |ctx| argument must have been constructed
|
||||
* with the public key. It returns one on success, or zero on error. */
|
||||
int x509_digest_verify_init(EVP_PKEY_CTX *ctx, X509_ALGOR *sigalg);
|
||||
* with public key |pkey| and parameters from |algor|. The |ctx| argument must
|
||||
* have been initialised with |EVP_MD_CTX_init|. It returns one on success, or
|
||||
* zero on error. */
|
||||
int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
|
||||
EVP_PKEY *pkey);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
@ -242,7 +242,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int x509_rsa_pss_to_ctx(EVP_PKEY_CTX *ctx, X509_ALGOR *sigalg) {
|
||||
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 */
|
||||
@ -279,10 +279,11 @@ int x509_rsa_pss_to_ctx(EVP_PKEY_CTX *ctx, X509_ALGOR *sigalg) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_CTX_set_signature_md(ctx, md) ||
|
||||
!EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) ||
|
||||
!EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen) ||
|
||||
!EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgf1md)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/curve25519.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/err.h>
|
||||
@ -714,7 +715,7 @@ static bool SignatureRoundTrips(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
|
||||
return !!X509_verify(cert.get(), pkey);
|
||||
}
|
||||
|
||||
TEST(X509Test, TestSignCtx) {
|
||||
TEST(X509Test, RSASign) {
|
||||
bssl::UniquePtr<EVP_PKEY> pkey(PrivateKeyFromPEM(kRSAKey));
|
||||
ASSERT_TRUE(pkey);
|
||||
// Test PKCS#1 v1.5.
|
||||
@ -733,6 +734,21 @@ TEST(X509Test, TestSignCtx) {
|
||||
ASSERT_TRUE(SignatureRoundTrips(md_ctx.get(), pkey.get()));
|
||||
}
|
||||
|
||||
TEST(X509Test, Ed25519Sign) {
|
||||
uint8_t pub_bytes[32], priv_bytes[64];
|
||||
ED25519_keypair(pub_bytes, priv_bytes);
|
||||
|
||||
bssl::UniquePtr<EVP_PKEY> pub(EVP_PKEY_new_ed25519_public(pub_bytes));
|
||||
ASSERT_TRUE(pub);
|
||||
bssl::UniquePtr<EVP_PKEY> priv(EVP_PKEY_new_ed25519_private(priv_bytes));
|
||||
ASSERT_TRUE(priv);
|
||||
|
||||
bssl::ScopedEVP_MD_CTX md_ctx;
|
||||
ASSERT_TRUE(
|
||||
EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr, priv.get()));
|
||||
ASSERT_TRUE(SignatureRoundTrips(md_ctx.get(), pub.get()));
|
||||
}
|
||||
|
||||
static bool PEMToDER(bssl::UniquePtr<uint8_t> *out, size_t *out_len,
|
||||
const char *pem) {
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
|
||||
|
@ -171,7 +171,7 @@ OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new_ed25519_private(
|
||||
#define EVP_PKEY_RSA NID_rsaEncryption
|
||||
#define EVP_PKEY_DSA NID_dsa
|
||||
#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
|
||||
#define EVP_PKEY_ED25519 NID_Ed25519
|
||||
#define EVP_PKEY_ED25519 NID_ED25519
|
||||
|
||||
/* EVP_PKEY_assign sets the underlying key of |pkey| to |key|, which must be of
|
||||
* the given type. The |type| argument should be one of the |EVP_PKEY_*|
|
||||
@ -238,9 +238,9 @@ OPENSSL_EXPORT void EVP_set_buggy_rsa_parser(int buggy);
|
||||
* operation will be written to |*pctx|; this can be used to set alternative
|
||||
* signing options.
|
||||
*
|
||||
* This function performs a streaming signing operation and will fail for
|
||||
* signature algorithms which do not support this. Use |EVP_PKEY_sign_message|
|
||||
* for a single-shot operation.
|
||||
* For single-shot signing algorithms which do not use a pre-hash, such as
|
||||
* Ed25519, |type| should be NULL. The |EVP_MD_CTX| itself is unused but is
|
||||
* present so the API is uniform. See |EVP_DigestSign|.
|
||||
*
|
||||
* It returns one on success, or zero on error. */
|
||||
OPENSSL_EXPORT int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
@ -248,7 +248,11 @@ OPENSSL_EXPORT int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
EVP_PKEY *pkey);
|
||||
|
||||
/* EVP_DigestSignUpdate appends |len| bytes from |data| to the data which will
|
||||
* be signed in |EVP_DigestSignFinal|. It returns one. */
|
||||
* be signed in |EVP_DigestSignFinal|. It returns one.
|
||||
*
|
||||
* This function performs a streaming signing operation and will fail for
|
||||
* signature algorithms which do not support this. Use |EVP_DigestSign| for a
|
||||
* single-shot operation. */
|
||||
OPENSSL_EXPORT int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t len);
|
||||
|
||||
@ -259,10 +263,25 @@ OPENSSL_EXPORT int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data,
|
||||
* is successful, the signature is written to |out_sig| and |*out_sig_len| is
|
||||
* set to its length.
|
||||
*
|
||||
* This function performs a streaming signing operation and will fail for
|
||||
* signature algorithms which do not support this. Use |EVP_DigestSign| for a
|
||||
* single-shot operation.
|
||||
*
|
||||
* It returns one on success, or zero on error. */
|
||||
OPENSSL_EXPORT int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
|
||||
size_t *out_sig_len);
|
||||
|
||||
/* EVP_DigestSign signs |data_len| bytes from |data| using |ctx|. If |out_sig|
|
||||
* is NULL then |*out_sig_len| is set to the maximum number of output
|
||||
* bytes. Otherwise, on entry, |*out_sig_len| must contain the length of the
|
||||
* |out_sig| buffer. If the call is successful, the signature is written to
|
||||
* |out_sig| and |*out_sig_len| is set to its length.
|
||||
*
|
||||
* It returns one on success and zero on error. */
|
||||
OPENSSL_EXPORT int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig,
|
||||
size_t *out_sig_len, const uint8_t *data,
|
||||
size_t data_len);
|
||||
|
||||
|
||||
/* Verifying */
|
||||
|
||||
@ -272,9 +291,9 @@ OPENSSL_EXPORT int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
|
||||
* operation will be written to |*pctx|; this can be used to set alternative
|
||||
* signing options.
|
||||
*
|
||||
* This function performs streaming signature verification and will fail for
|
||||
* signature algorithms which do not support this. Use |EVP_PKEY_verify_message|
|
||||
* for a single-shot verification.
|
||||
* For single-shot signing algorithms which do not use a pre-hash, such as
|
||||
* Ed25519, |type| should be NULL. The |EVP_MD_CTX| itself is unused but is
|
||||
* present so the API is uniform. See |EVP_DigestVerify|.
|
||||
*
|
||||
* It returns one on success, or zero on error. */
|
||||
OPENSSL_EXPORT int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
@ -282,16 +301,30 @@ OPENSSL_EXPORT int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
EVP_PKEY *pkey);
|
||||
|
||||
/* EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which
|
||||
* will be verified by |EVP_DigestVerifyFinal|. It returns one. */
|
||||
* will be verified by |EVP_DigestVerifyFinal|. It returns one.
|
||||
*
|
||||
* This function performs streaming signature verification and will fail for
|
||||
* signature algorithms which do not support this. Use |EVP_PKEY_verify_message|
|
||||
* for a single-shot verification. */
|
||||
OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data,
|
||||
size_t len);
|
||||
|
||||
/* EVP_DigestVerifyFinal verifies that |sig_len| bytes of |sig| are a valid
|
||||
* signature for the data that has been included by one or more calls to
|
||||
* |EVP_DigestVerifyUpdate|. It returns one on success and zero otherwise. */
|
||||
* |EVP_DigestVerifyUpdate|. It returns one on success and zero otherwise.
|
||||
*
|
||||
* This function performs streaming signature verification and will fail for
|
||||
* signature algorithms which do not support this. Use |EVP_PKEY_verify_message|
|
||||
* for a single-shot verification. */
|
||||
OPENSSL_EXPORT int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
|
||||
size_t sig_len);
|
||||
|
||||
/* EVP_DigestVerify verifies that |sig_len| bytes from |sig| are a valid
|
||||
* signature for |data|. It returns one on success or zero on error. */
|
||||
OPENSSL_EXPORT int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig,
|
||||
size_t sig_len, const uint8_t *data,
|
||||
size_t len);
|
||||
|
||||
|
||||
/* Signing (old functions) */
|
||||
|
||||
@ -439,8 +472,8 @@ OPENSSL_EXPORT int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
|
||||
* |sig| and |*sig_len| updated with the true length.
|
||||
*
|
||||
* This function expects a pre-hashed input and will fail for signature
|
||||
* algorithms which do not support this. Use |EVP_PKEY_sign_message| or
|
||||
* |EVP_DigestSignInit| to sign an unhashed input.
|
||||
* algorithms which do not support this. Use |EVP_DigestSignInit| to sign an
|
||||
* unhashed input.
|
||||
*
|
||||
* WARNING: Setting |sig| to NULL only gives the maximum size of the
|
||||
* signature. The actual signature may be smaller.
|
||||
@ -451,21 +484,6 @@ OPENSSL_EXPORT int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, uint8_t *sig,
|
||||
size_t *sig_len, const uint8_t *digest,
|
||||
size_t digest_len);
|
||||
|
||||
/* EVP_PKEY_sign_message signs |data_len| bytes from |data| using |ctx|. If
|
||||
* |sig| is NULL, the maximum size of the signature is written to |out_sig_len|.
|
||||
* Otherwise, |*sig_len| must contain the number of bytes of space available at
|
||||
* |sig|. If sufficient, the signature will be written to |sig| and |*sig_len|
|
||||
* updated with the true length.
|
||||
*
|
||||
* WARNING: Setting |sig| to NULL only gives the maximum size of the
|
||||
* signature. The actual signature may be smaller.
|
||||
*
|
||||
* It returns one on success or zero on error. (Note: this differs from
|
||||
* OpenSSL, which can also return negative values to indicate an error. ) */
|
||||
OPENSSL_EXPORT int EVP_PKEY_sign_message(EVP_PKEY_CTX *ctx, uint8_t *sig,
|
||||
size_t *sig_len, const uint8_t *data,
|
||||
size_t data_len);
|
||||
|
||||
/* EVP_PKEY_verify_init initialises an |EVP_PKEY_CTX| for a signature
|
||||
* verification operation. It should be called before |EVP_PKEY_verify|.
|
||||
*
|
||||
@ -476,21 +494,14 @@ OPENSSL_EXPORT int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
|
||||
* signature for |digest|.
|
||||
*
|
||||
* This function expects a pre-hashed input and will fail for signature
|
||||
* algorithms which do not support this. Use |EVP_PKEY_verify_message| or
|
||||
* |EVP_DigestVerifyInit| to verify a signature given the unhashed input.
|
||||
* algorithms which do not support this. Use |EVP_DigestVerifyInit| to verify a
|
||||
* signature given the unhashed input.
|
||||
*
|
||||
* It returns one on success or zero on error. */
|
||||
OPENSSL_EXPORT int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig,
|
||||
size_t sig_len, const uint8_t *digest,
|
||||
size_t digest_len);
|
||||
|
||||
/* EVP_PKEY_verify_message verifies that |sig_len| bytes from |sig| are a valid
|
||||
* signature for |data|. It returns one on success or zero on error. */
|
||||
OPENSSL_EXPORT int EVP_PKEY_verify_message(EVP_PKEY_CTX *ctx,
|
||||
const uint8_t *sig, size_t sig_len,
|
||||
const uint8_t *data,
|
||||
size_t data_len);
|
||||
|
||||
/* EVP_PKEY_encrypt_init initialises an |EVP_PKEY_CTX| for an encryption
|
||||
* operation. It should be called before |EVP_PKEY_encrypt|.
|
||||
*
|
||||
|
@ -65,6 +65,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* The nid library provides numbered values for ASN.1 object identifiers and
|
||||
* other symbols. These values are used by other libraries to identify
|
||||
* cryptographic primitives.
|
||||
@ -78,6 +79,7 @@ extern "C" {
|
||||
* These values should not be used outside of a single process; they are not
|
||||
* stable identifiers. */
|
||||
|
||||
|
||||
#define SN_undef "UNDEF"
|
||||
#define LN_undef "undefined"
|
||||
#define NID_undef 0
|
||||
@ -4192,9 +4194,9 @@ extern "C" {
|
||||
#define SN_X25519 "X25519"
|
||||
#define NID_X25519 948
|
||||
|
||||
#define SN_Ed25519 "Ed25519"
|
||||
#define NID_Ed25519 949
|
||||
#define OBJ_Ed25519 1L, 3L, 101L, 112L
|
||||
#define SN_ED25519 "ED25519"
|
||||
#define NID_ED25519 949
|
||||
#define OBJ_ED25519 1L, 3L, 101L, 112L
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
@ -373,21 +373,27 @@ static int pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setup_ctx(SSL *ssl, EVP_PKEY_CTX *ctx, uint16_t sigalg) {
|
||||
if (!pkey_supports_algorithm(ssl, EVP_PKEY_CTX_get0_pkey(ctx), sigalg)) {
|
||||
static int setup_ctx(SSL *ssl, EVP_MD_CTX *ctx, EVP_PKEY *pkey, uint16_t sigalg,
|
||||
int is_verify) {
|
||||
if (!pkey_supports_algorithm(ssl, pkey, sigalg)) {
|
||||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
|
||||
if (alg->digest_func != NULL &&
|
||||
!EVP_PKEY_CTX_set_signature_md(ctx, alg->digest_func())) {
|
||||
const EVP_MD *digest = alg->digest_func != NULL ? alg->digest_func() : NULL;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
if (is_verify) {
|
||||
if (!EVP_DigestVerifyInit(ctx, &pctx, digest, NULL, pkey)) {
|
||||
return 0;
|
||||
}
|
||||
} else if (!EVP_DigestSignInit(ctx, &pctx, digest, NULL, pkey)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (alg->is_rsa_pss) {
|
||||
if (!EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) ||
|
||||
!EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1 /* salt len = hash len */)) {
|
||||
if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
|
||||
!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -430,24 +436,22 @@ enum ssl_private_key_result_t ssl_private_key_sign(
|
||||
}
|
||||
|
||||
*out_len = max_out;
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
|
||||
int ret = ctx != NULL &&
|
||||
EVP_PKEY_sign_init(ctx) &&
|
||||
setup_ctx(ssl, ctx, sigalg) &&
|
||||
EVP_PKEY_sign_message(ctx, out, out_len, in, in_len);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
int ret = setup_ctx(ssl, &ctx, ssl->cert->privatekey, sigalg, 0 /* sign */) &&
|
||||
EVP_DigestSign(&ctx, out, out_len, in, in_len);
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return ret ? ssl_private_key_success : ssl_private_key_failure;
|
||||
}
|
||||
|
||||
int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
|
||||
size_t signature_len, uint16_t signature_algorithm,
|
||||
EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
int ret = ctx != NULL &&
|
||||
EVP_PKEY_verify_init(ctx) &&
|
||||
setup_ctx(ssl, ctx, signature_algorithm) &&
|
||||
EVP_PKEY_verify_message(ctx, signature, signature_len, in, in_len);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
size_t signature_len, uint16_t sigalg, EVP_PKEY *pkey,
|
||||
const uint8_t *in, size_t in_len) {
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
int ret = setup_ctx(ssl, &ctx, pkey, sigalg, 1 /* verify */) &&
|
||||
EVP_DigestVerify(&ctx, signature, signature_len, in, in_len);
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -295,13 +295,6 @@ static ssl_private_key_result_t AsyncPrivateKeySign(
|
||||
abort();
|
||||
}
|
||||
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> ctx(
|
||||
EVP_PKEY_CTX_new(test_state->private_key.get(), nullptr));
|
||||
if (!ctx ||
|
||||
!EVP_PKEY_sign_init(ctx.get())) {
|
||||
return ssl_private_key_failure;
|
||||
}
|
||||
|
||||
// Determine the hash.
|
||||
const EVP_MD *md;
|
||||
switch (signature_algorithm) {
|
||||
@ -336,8 +329,10 @@ static ssl_private_key_result_t AsyncPrivateKeySign(
|
||||
return ssl_private_key_failure;
|
||||
}
|
||||
|
||||
if (md != nullptr &&
|
||||
!EVP_PKEY_CTX_set_signature_md(ctx.get(), md)) {
|
||||
bssl::ScopedEVP_MD_CTX ctx;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
if (!EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr,
|
||||
test_state->private_key.get())) {
|
||||
return ssl_private_key_failure;
|
||||
}
|
||||
|
||||
@ -346,8 +341,8 @@ static ssl_private_key_result_t AsyncPrivateKeySign(
|
||||
case SSL_SIGN_RSA_PSS_SHA256:
|
||||
case SSL_SIGN_RSA_PSS_SHA384:
|
||||
case SSL_SIGN_RSA_PSS_SHA512:
|
||||
if (!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PSS_PADDING) ||
|
||||
!EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx.get(),
|
||||
if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
|
||||
!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
|
||||
-1 /* salt len = hash len */)) {
|
||||
return ssl_private_key_failure;
|
||||
}
|
||||
@ -355,12 +350,12 @@ static ssl_private_key_result_t AsyncPrivateKeySign(
|
||||
|
||||
// Write the signature into |test_state|.
|
||||
size_t len = 0;
|
||||
if (!EVP_PKEY_sign_message(ctx.get(), nullptr, &len, in, in_len)) {
|
||||
if (!EVP_DigestSign(ctx.get(), nullptr, &len, in, in_len)) {
|
||||
return ssl_private_key_failure;
|
||||
}
|
||||
test_state->private_key_result.resize(len);
|
||||
if (!EVP_PKEY_sign_message(ctx.get(), test_state->private_key_result.data(),
|
||||
&len, in, in_len)) {
|
||||
if (!EVP_DigestSign(ctx.get(), test_state->private_key_result.data(), &len,
|
||||
in, in_len)) {
|
||||
return ssl_private_key_failure;
|
||||
}
|
||||
test_state->private_key_result.resize(len);
|
||||
|
21
tool/sign.cc
21
tool/sign.cc
@ -46,24 +46,19 @@ bool Sign(const std::vector<std::string> &args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup the signing operation.
|
||||
bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key.get(), nullptr));
|
||||
if (!ctx ||
|
||||
!EVP_PKEY_sign_init(ctx.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const EVP_MD *md = nullptr;
|
||||
if (args_map.count("-digest")) {
|
||||
const EVP_MD *md = EVP_get_digestbyname(args_map["-digest"].c_str());
|
||||
md = EVP_get_digestbyname(args_map["-digest"].c_str());
|
||||
if (md == nullptr) {
|
||||
fprintf(stderr, "Unknown digest algorithm: %s\n",
|
||||
args_map["-digest"].c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), md)) {
|
||||
return false;
|
||||
}
|
||||
bssl::ScopedEVP_MD_CTX ctx;
|
||||
if (!EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, key.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
@ -74,8 +69,8 @@ bool Sign(const std::vector<std::string> &args) {
|
||||
|
||||
size_t sig_len = EVP_PKEY_size(key.get());
|
||||
std::unique_ptr<uint8_t[]> sig(new uint8_t[sig_len]);
|
||||
if (!EVP_PKEY_sign_message(ctx.get(), sig.get(), &sig_len, data.data(),
|
||||
data.size())) {
|
||||
if (!EVP_DigestSign(ctx.get(), sig.get(), &sig_len, data.data(),
|
||||
data.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user