ed25519 support
diff --git a/include/picotls.h b/include/picotls.h
index ee3b941..fc605b7 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -124,6 +124,7 @@
#define PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256 0x0804
#define PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384 0x0805
#define PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512 0x0806
+#define PTLS_SIGNATURE_ED25519 0x0807
/* ESNI */
#define PTLS_ESNI_VERSION_DRAFT03 0xff02
diff --git a/lib/openssl.c b/lib/openssl.c
index 3221a7e..16f4f9e 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -624,38 +624,61 @@
ret = PTLS_ERROR_NO_MEMORY;
goto Exit;
}
+
if (EVP_DigestSignInit(ctx, &pkey_ctx, md, NULL, key) != 1) {
ret = PTLS_ERROR_LIBRARY;
goto Exit;
}
- if (EVP_PKEY_id(key) == EVP_PKEY_RSA) {
- if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) {
+
+#if defined EVP_PKEY_ED25519
+ if (EVP_PKEY_id(key) == EVP_PKEY_ED25519)
+ {
+ if (EVP_DigestSign(ctx, NULL, &siglen, input.base, input.len) != 1) {
ret = PTLS_ERROR_LIBRARY;
goto Exit;
}
- if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) != 1) {
- ret = PTLS_ERROR_LIBRARY;
+
+ if ((ret = ptls_buffer_reserve(outbuf, siglen)) != 0)
goto Exit;
- }
- if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha256()) != 1) {
+
+ if (EVP_DigestSign(ctx, outbuf->base + outbuf->off, &siglen, input.base, input.len) != 1) {
ret = PTLS_ERROR_LIBRARY;
goto Exit;
}
}
- if (EVP_DigestSignUpdate(ctx, input.base, input.len) != 1) {
- ret = PTLS_ERROR_LIBRARY;
- goto Exit;
+ else
+#endif
+ {
+ if (EVP_PKEY_id(key) == EVP_PKEY_RSA) {
+ if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha256()) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ }
+ if (EVP_DigestSignUpdate(ctx, input.base, input.len) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_DigestSignFinal(ctx, NULL, &siglen) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if ((ret = ptls_buffer_reserve(outbuf, siglen)) != 0)
+ goto Exit;
+ if (EVP_DigestSignFinal(ctx, outbuf->base + outbuf->off, &siglen) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
}
- if (EVP_DigestSignFinal(ctx, NULL, &siglen) != 1) {
- ret = PTLS_ERROR_LIBRARY;
- goto Exit;
- }
- if ((ret = ptls_buffer_reserve(outbuf, siglen)) != 0)
- goto Exit;
- if (EVP_DigestSignFinal(ctx, outbuf->base + outbuf->off, &siglen) != 1) {
- ret = PTLS_ERROR_LIBRARY;
- goto Exit;
- }
+
outbuf->off += siglen;
ret = 0;
@@ -964,7 +987,7 @@
return d2i_X509(NULL, &p, (long)vec.len);
}
-static int verify_sign(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t signature)
+static int verify_sign(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t signature, const EVP_MD *md)
{
EVP_PKEY *key = verify_ctx;
EVP_MD_CTX *ctx = NULL;
@@ -978,32 +1001,46 @@
ret = PTLS_ERROR_NO_MEMORY;
goto Exit;
}
- if (EVP_DigestVerifyInit(ctx, &pkey_ctx, EVP_sha256(), NULL, key) != 1) {
+ if (EVP_DigestVerifyInit(ctx, &pkey_ctx, md, NULL, key) != 1) {
ret = PTLS_ERROR_LIBRARY;
goto Exit;
}
- if (EVP_PKEY_id(key) == EVP_PKEY_RSA) {
- if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) {
- ret = PTLS_ERROR_LIBRARY;
- goto Exit;
- }
- if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) != 1) {
- ret = PTLS_ERROR_LIBRARY;
- goto Exit;
- }
- if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha256()) != 1) {
+
+#if defined EVP_PKEY_ED25519
+ if (EVP_PKEY_id(key) == EVP_PKEY_ED25519)
+ {
+ if (EVP_DigestVerify(ctx, signature.base, signature.len, data.base, data.len) != 1) {
ret = PTLS_ERROR_LIBRARY;
goto Exit;
}
}
- if (EVP_DigestVerifyUpdate(ctx, data.base, data.len) != 1) {
- ret = PTLS_ERROR_LIBRARY;
- goto Exit;
+ else
+#endif
+ {
+ if (EVP_PKEY_id(key) == EVP_PKEY_RSA) {
+ if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha256()) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ }
+ if (EVP_DigestVerifyUpdate(ctx, data.base, data.len) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_DigestVerifyFinal(ctx, signature.base, signature.len) != 1) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
}
- if (EVP_DigestVerifyFinal(ctx, signature.base, signature.len) != 1) {
- ret = PTLS_ALERT_DECRYPT_ERROR;
- goto Exit;
- }
+
ret = 0;
Exit:
@@ -1052,6 +1089,11 @@
}
EC_KEY_free(eckey);
} break;
+#if defined EVP_PKEY_ED25519
+ case EVP_PKEY_ED25519:
+ PUSH_SCHEME(PTLS_SIGNATURE_ED25519, EVP_sha512());
+ break;
+#endif
default:
return PTLS_ERROR_INCOMPATIBLE_KEY;
}
@@ -1200,7 +1242,7 @@
return ret;
}
-static int verify_cert(ptls_verify_certificate_t *_self, ptls_t *tls, int (**verifier)(void *, ptls_iovec_t, ptls_iovec_t),
+static int verify_cert(ptls_verify_certificate_t *_self, ptls_t *tls, int (**verifier)(void *, ptls_iovec_t, ptls_iovec_t, const EVP_MD *),
void **verify_data, ptls_iovec_t *certs, size_t num_certs)
{
ptls_openssl_verify_certificate_t *self = (ptls_openssl_verify_certificate_t *)_self;
@@ -1286,7 +1328,7 @@
return NULL;
}
-static int verify_raw_cert(ptls_verify_certificate_t *_self, ptls_t *tls, int (**verifier)(void *, ptls_iovec_t, ptls_iovec_t),
+static int verify_raw_cert(ptls_verify_certificate_t *_self, ptls_t *tls, int (**verifier)(void *, ptls_iovec_t, ptls_iovec_t, const EVP_MD *),
void **verify_data, ptls_iovec_t *certs, size_t num_certs)
{
ptls_openssl_raw_pubkey_verify_certificate_t *self = (ptls_openssl_raw_pubkey_verify_certificate_t *)_self;
diff --git a/t/openssl.c b/t/openssl.c
index fb52775..f4d0be0 100644
--- a/t/openssl.c
+++ b/t/openssl.c
@@ -170,6 +170,31 @@
EVP_PKEY_free(pkey);
}
+static void test_ed25519_sign(void)
+{
+ EVP_PKEY *pkey = NULL;
+
+ { /* create pkey */
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
+ EVP_PKEY_keygen_init(pctx);
+ EVP_PKEY_keygen(pctx, &pkey);
+ EVP_PKEY_CTX_free(pctx);
+ }
+
+ const char *message = "hello world";
+ ptls_buffer_t sigbuf;
+
+ uint8_t sigbuf_small[1024];
+
+ ptls_buffer_init(&sigbuf, sigbuf_small, sizeof(sigbuf_small));
+ ok(do_sign(pkey, &sigbuf, ptls_iovec_init(message, strlen(message)), NULL) == 0);
+ EVP_PKEY_up_ref(pkey);
+ ok(verify_sign(pkey, ptls_iovec_init(message, strlen(message)), ptls_iovec_init(sigbuf.base, sigbuf.off), NULL) == 0);
+
+ ptls_buffer_dispose(&sigbuf);
+ EVP_PKEY_free(pkey);
+}
+
static X509 *x509_from_pem(const char *pem)
{
BIO *bio = BIO_new_mem_buf((void *)pem, (int)strlen(pem));
@@ -308,6 +333,7 @@
subtest("rsa-sign", test_rsa_sign);
subtest("ecdsa-sign", test_ecdsa_sign);
+ subtest("ed25519-sign", test_ed25519_sign);
subtest("cert-verify", test_cert_verify);
subtest("picotls", test_picotls);
test_picotls_esni(esni_private_keys);