171 lines
4.4 KiB
C
171 lines
4.4 KiB
C
// Copyright (c) 2017, Google Inc.
|
|
// SPDX-License-Identifier: ISC
|
|
|
|
#include <openssl/evp.h>
|
|
|
|
#include <openssl/curve25519.h>
|
|
#include <openssl/err.h>
|
|
#include <openssl/mem.h>
|
|
|
|
#include "../../internal.h"
|
|
#include "internal.h"
|
|
|
|
typedef struct {
|
|
uint8_t context[255];
|
|
size_t context_len;
|
|
} ED25519PH_PKEY_CTX;
|
|
|
|
static int pkey_ed25519ph_init(EVP_PKEY_CTX *ctx) {
|
|
ED25519PH_PKEY_CTX *dctx = OPENSSL_zalloc(sizeof(ED25519PH_PKEY_CTX));
|
|
if (dctx == NULL) {
|
|
return 0;
|
|
}
|
|
ctx->data = dctx;
|
|
return 1;
|
|
}
|
|
|
|
static void pkey_ed25519ph_cleanup(EVP_PKEY_CTX *ctx) {
|
|
ED25519PH_PKEY_CTX *dctx = ctx->data;
|
|
if (!dctx) {
|
|
return;
|
|
}
|
|
|
|
OPENSSL_free(dctx);
|
|
}
|
|
|
|
static int pkey_ed25519ph_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
|
|
if (!pkey_ed25519ph_init(dst)) {
|
|
return 0;
|
|
}
|
|
|
|
ED25519PH_PKEY_CTX *dctx = dst->data;
|
|
ED25519PH_PKEY_CTX *sctx = src->data;
|
|
GUARD_PTR(dctx);
|
|
GUARD_PTR(sctx);
|
|
|
|
OPENSSL_memcpy(dctx->context, sctx->context, sizeof(sctx->context));
|
|
dctx->context_len = sctx->context_len;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int pkey_ed25519ph_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
|
|
const uint8_t *tbs, size_t tbslen) {
|
|
ED25519_KEY *key = ctx->pkey->pkey.ptr;
|
|
if (!key->has_private) {
|
|
OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
|
|
return 0;
|
|
}
|
|
|
|
if (sig == NULL) {
|
|
*siglen = ED25519_SIGNATURE_LEN;
|
|
return 1;
|
|
}
|
|
|
|
if (*siglen < ED25519_SIGNATURE_LEN) {
|
|
OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
|
|
return 0;
|
|
}
|
|
|
|
if (tbslen < SHA512_DIGEST_LENGTH) {
|
|
OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
|
|
return 0;
|
|
}
|
|
|
|
ED25519PH_PKEY_CTX *dctx = ctx->data;
|
|
GUARD_PTR(dctx);
|
|
|
|
if (!ED25519ph_sign_digest(sig, tbs, key->key, dctx->context,
|
|
dctx->context_len)) {
|
|
return 0;
|
|
}
|
|
|
|
*siglen = ED25519_SIGNATURE_LEN;
|
|
return 1;
|
|
}
|
|
|
|
static int pkey_ed25519ph_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig,
|
|
size_t siglen, const uint8_t *tbs,
|
|
size_t tbslen) {
|
|
ED25519_KEY *key = ctx->pkey->pkey.ptr;
|
|
ED25519PH_PKEY_CTX *dctx = ctx->data;
|
|
GUARD_PTR(dctx);
|
|
|
|
if (siglen != ED25519_SIGNATURE_LEN || tbslen < SHA512_DIGEST_LENGTH ||
|
|
!ED25519ph_verify_digest(tbs, sig, key->key + ED25519_PUBLIC_KEY_OFFSET,
|
|
dctx->context, dctx->context_len)) {
|
|
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SIGNATURE);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int pkey_ed25519ph_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
|
|
GUARD_PTR(ctx);
|
|
ED25519PH_PKEY_CTX *dctx = (ED25519PH_PKEY_CTX *)ctx->data;
|
|
switch (type) {
|
|
case EVP_PKEY_CTRL_MD: {
|
|
const EVP_MD *md = p2;
|
|
int md_type = EVP_MD_type(md);
|
|
// MUST be SHA-512
|
|
if (md_type != NID_sha512) {
|
|
OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
case EVP_PKEY_CTRL_SIGNING_CONTEXT: {
|
|
EVP_PKEY_CTX_SIGNATURE_CONTEXT_PARAMS *params = p2;
|
|
if (!params || !dctx || params->context_len > sizeof(dctx->context)) {
|
|
return 0;
|
|
}
|
|
OPENSSL_memcpy(dctx->context, params->context, params->context_len);
|
|
dctx->context_len = params->context_len;
|
|
break;
|
|
}
|
|
case EVP_PKEY_CTRL_GET_SIGNING_CONTEXT: {
|
|
EVP_PKEY_CTX_SIGNATURE_CONTEXT_PARAMS *params = p2;
|
|
if (!params || !dctx) {
|
|
return 0;
|
|
}
|
|
if (dctx->context_len == 0) {
|
|
params->context = NULL;
|
|
params->context_len = 0;
|
|
} else {
|
|
params->context = dctx->context;
|
|
params->context_len = dctx->context_len;
|
|
}
|
|
return 1;
|
|
}
|
|
default:
|
|
OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_ed25519ph_pkey_meth) {
|
|
out->pkey_id = EVP_PKEY_ED25519PH;
|
|
out->init = pkey_ed25519ph_init;
|
|
out->copy = pkey_ed25519ph_copy;
|
|
out->cleanup = pkey_ed25519ph_cleanup;
|
|
out->keygen = NULL;
|
|
out->sign_init = NULL;
|
|
out->sign = pkey_ed25519ph_sign;
|
|
out->verify_init = NULL;
|
|
out->verify = pkey_ed25519ph_verify;
|
|
out->verify_message = NULL;
|
|
out->verify_recover = NULL;
|
|
out->encrypt = NULL;
|
|
out->decrypt = NULL;
|
|
out->derive = NULL;
|
|
out->paramgen = NULL;
|
|
out->ctrl = pkey_ed25519ph_ctrl;
|
|
out->ctrl_str = NULL;
|
|
out->keygen_deterministic = NULL;
|
|
out->encapsulate_deterministic = NULL;
|
|
out->encapsulate = NULL;
|
|
out->decapsulate = NULL;
|
|
}
|