summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2022-11-09 17:39:29 +0000
committerjsing <>2022-11-09 17:39:29 +0000
commit390601a304fd7ed95013cfc05628a1a33f115b25 (patch)
treef0cbe11399d675629473425a560232c59fa77acb
parentba67559fec418c6b97834e077e96f2392244261d (diff)
downloadopenbsd-390601a304fd7ed95013cfc05628a1a33f115b25.tar.gz
openbsd-390601a304fd7ed95013cfc05628a1a33f115b25.tar.bz2
openbsd-390601a304fd7ed95013cfc05628a1a33f115b25.zip
Rework ED25519 API.
BoringSSL implemented a compound private key, which includes a copy of the public key as a performance optimisation for signing. However, this does not readily match with how EVP works, makes the ED25519 API inconsistent with the X25519 API, diverges from th RFC and does not align with the OpenSSL API. Instead, the caller can readily compute the public key and pass this in to the signing process. ok tb@
-rw-r--r--src/lib/libcrypto/curve25519/curve25519.c51
-rw-r--r--src/lib/libcrypto/curve25519/curve25519.h28
-rw-r--r--src/lib/libcrypto/curve25519/curve25519_internal.h6
3 files changed, 40 insertions, 45 deletions
diff --git a/src/lib/libcrypto/curve25519/curve25519.c b/src/lib/libcrypto/curve25519/curve25519.c
index 8d29379eb2..56373db923 100644
--- a/src/lib/libcrypto/curve25519/curve25519.c
+++ b/src/lib/libcrypto/curve25519/curve25519.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: curve25519.c,v 1.10 2022/11/08 17:07:17 jsing Exp $ */ 1/* $OpenBSD: curve25519.c,v 1.11 2022/11/09 17:39:29 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2015, Google Inc. 3 * Copyright (c) 2015, Google Inc.
4 * 4 *
@@ -4615,14 +4615,30 @@ sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
4615 s[31] = s11 >> 17; 4615 s[31] = s11 >> 17;
4616} 4616}
4617 4617
4618void ED25519_keypair(uint8_t out_public_key[32], uint8_t out_private_key[64]) { 4618void ED25519_public_from_private(uint8_t out_public_key[ED25519_PUBLIC_KEY_LENGTH],
4619 uint8_t seed[32]; 4619 const uint8_t private_key[ED25519_PRIVATE_KEY_LENGTH]) {
4620 arc4random_buf(seed, 32); 4620 uint8_t az[SHA512_DIGEST_LENGTH];
4621 ED25519_keypair_from_seed(out_public_key, out_private_key, seed); 4621 SHA512(private_key, 32, az);
4622
4623 az[0] &= 248;
4624 az[31] &= 63;
4625 az[31] |= 64;
4626
4627 ge_p3 A;
4628 x25519_ge_scalarmult_base(&A, az);
4629 ge_p3_tobytes(out_public_key, &A);
4630}
4631
4632void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LENGTH],
4633 uint8_t out_private_key[ED25519_PRIVATE_KEY_LENGTH]) {
4634 arc4random_buf(out_private_key, 32);
4635
4636 ED25519_public_from_private(out_public_key, out_private_key);
4622} 4637}
4623 4638
4624int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, 4639int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
4625 const uint8_t private_key[64]) { 4640 const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH],
4641 const uint8_t private_key[ED25519_PRIVATE_KEY_LENGTH]) {
4626 uint8_t az[SHA512_DIGEST_LENGTH]; 4642 uint8_t az[SHA512_DIGEST_LENGTH];
4627 SHA512(private_key, 32, az); 4643 SHA512(private_key, 32, az);
4628 4644
@@ -4644,7 +4660,7 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
4644 4660
4645 SHA512_Init(&hash_ctx); 4661 SHA512_Init(&hash_ctx);
4646 SHA512_Update(&hash_ctx, out_sig, 32); 4662 SHA512_Update(&hash_ctx, out_sig, 32);
4647 SHA512_Update(&hash_ctx, private_key + 32, 32); 4663 SHA512_Update(&hash_ctx, public_key, 32);
4648 SHA512_Update(&hash_ctx, message, message_len); 4664 SHA512_Update(&hash_ctx, message, message_len);
4649 uint8_t hram[SHA512_DIGEST_LENGTH]; 4665 uint8_t hram[SHA512_DIGEST_LENGTH];
4650 SHA512_Final(hram, &hash_ctx); 4666 SHA512_Final(hram, &hash_ctx);
@@ -4656,7 +4672,8 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
4656} 4672}
4657 4673
4658int ED25519_verify(const uint8_t *message, size_t message_len, 4674int ED25519_verify(const uint8_t *message, size_t message_len,
4659 const uint8_t signature[64], const uint8_t public_key[32]) { 4675 const uint8_t signature[ED25519_SIGNATURE_LENGTH],
4676 const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH]) {
4660 ge_p3 A; 4677 ge_p3 A;
4661 if ((signature[63] & 224) != 0 || 4678 if ((signature[63] & 224) != 0 ||
4662 x25519_ge_frombytes_vartime(&A, public_key) != 0) { 4679 x25519_ge_frombytes_vartime(&A, public_key) != 0) {
@@ -4692,24 +4709,6 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
4692 return timingsafe_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0; 4709 return timingsafe_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0;
4693} 4710}
4694 4711
4695void ED25519_keypair_from_seed(uint8_t out_public_key[32],
4696 uint8_t out_private_key[64],
4697 const uint8_t seed[32]) {
4698 uint8_t az[SHA512_DIGEST_LENGTH];
4699 SHA512(seed, 32, az);
4700
4701 az[0] &= 248;
4702 az[31] &= 63;
4703 az[31] |= 64;
4704
4705 ge_p3 A;
4706 x25519_ge_scalarmult_base(&A, az);
4707 ge_p3_tobytes(out_public_key, &A);
4708
4709 memcpy(out_private_key, seed, 32);
4710 memcpy(out_private_key + 32, out_public_key, 32);
4711}
4712
4713/* Replace (f,g) with (g,f) if b == 1; 4712/* Replace (f,g) with (g,f) if b == 1;
4714 * replace (f,g) with (f,g) if b == 0. 4713 * replace (f,g) with (f,g) if b == 0.
4715 * 4714 *
diff --git a/src/lib/libcrypto/curve25519/curve25519.h b/src/lib/libcrypto/curve25519/curve25519.h
index 164f2e9e7f..8b84c889cd 100644
--- a/src/lib/libcrypto/curve25519/curve25519.h
+++ b/src/lib/libcrypto/curve25519/curve25519.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: curve25519.h,v 1.4 2022/11/06 16:31:19 jsing Exp $ */ 1/* $OpenBSD: curve25519.h,v 1.5 2022/11/09 17:39:29 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2015, Google Inc. 3 * Copyright (c) 2015, Google Inc.
4 * 4 *
@@ -67,31 +67,27 @@ int X25519(uint8_t out_shared_key[X25519_KEY_LENGTH],
67 * 67 *
68 * Ed25519 is a signature scheme using a twisted Edwards curve that is 68 * Ed25519 is a signature scheme using a twisted Edwards curve that is
69 * birationally equivalent to curve25519. 69 * birationally equivalent to curve25519.
70 *
71 * Note that, unlike RFC 8032's formulation, our private key representation
72 * includes a public key suffix to make multiple key signing operations with the
73 * same key more efficient. The RFC 8032 private key is referred to in this
74 * implementation as the "seed" and is the first 32 bytes of our private key.
75 */ 70 */
76 71
77#define ED25519_PRIVATE_KEY_LEN 64 72#define ED25519_PRIVATE_KEY_LENGTH 32
78#define ED25519_PUBLIC_KEY_LEN 32 73#define ED25519_PUBLIC_KEY_LENGTH 32
79#define ED25519_SIGNATURE_LEN 64 74#define ED25519_SIGNATURE_LENGTH 64
80 75
81/* 76/*
82 * ED25519_keypair sets |out_public_key| and |out_private_key| to a freshly 77 * ED25519_keypair sets |out_public_key| and |out_private_key| to a freshly
83 * generated, public/private key pair. 78 * generated, public/private key pair.
84 */ 79 */
85void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN], 80void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LENGTH],
86 uint8_t out_private_key[ED25519_PRIVATE_KEY_LEN]); 81 uint8_t out_private_key[ED25519_PRIVATE_KEY_LENGTH]);
87 82
88/* 83/*
89 * ED25519_sign sets |out_sig| to be a signature of |message_len| bytes from 84 * ED25519_sign sets |out_sig| to be a signature of |message_len| bytes from
90 * |message| using |private_key|. It returns one on success or zero on 85 * |message| using |public_key| and |private_key|. It returns one on success
91 * allocation failure. 86 * or zero on allocation failure.
92 */ 87 */
93int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, 88int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
94 const uint8_t private_key[ED25519_PRIVATE_KEY_LEN]); 89 const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH],
90 const uint8_t private_key_seed[ED25519_PRIVATE_KEY_LENGTH]);
95 91
96/* 92/*
97 * ED25519_verify returns one iff |signature| is a valid signature by 93 * ED25519_verify returns one iff |signature| is a valid signature by
@@ -99,8 +95,8 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
99 * otherwise. 95 * otherwise.
100 */ 96 */
101int ED25519_verify(const uint8_t *message, size_t message_len, 97int ED25519_verify(const uint8_t *message, size_t message_len,
102 const uint8_t signature[ED25519_SIGNATURE_LEN], 98 const uint8_t signature[ED25519_SIGNATURE_LENGTH],
103 const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]); 99 const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH]);
104#endif 100#endif
105 101
106#if defined(__cplusplus) 102#if defined(__cplusplus)
diff --git a/src/lib/libcrypto/curve25519/curve25519_internal.h b/src/lib/libcrypto/curve25519/curve25519_internal.h
index 9d2ee9b4d7..0a98781651 100644
--- a/src/lib/libcrypto/curve25519/curve25519_internal.h
+++ b/src/lib/libcrypto/curve25519/curve25519_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: curve25519_internal.h,v 1.4 2022/11/08 17:07:17 jsing Exp $ */ 1/* $OpenBSD: curve25519_internal.h,v 1.5 2022/11/09 17:39:29 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2015, Google Inc. 3 * Copyright (c) 2015, Google Inc.
4 * 4 *
@@ -94,8 +94,8 @@ void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
94void x25519_scalar_mult_generic(uint8_t out[32], const uint8_t scalar[32], 94void x25519_scalar_mult_generic(uint8_t out[32], const uint8_t scalar[32],
95 const uint8_t point[32]); 95 const uint8_t point[32]);
96 96
97void ED25519_keypair_from_seed(uint8_t out_public_key[32], 97void ED25519_public_from_private(uint8_t out_public_key[32],
98 uint8_t out_private_key[64], const uint8_t seed[32]); 98 const uint8_t private_key[32]);
99 99
100__END_HIDDEN_DECLS 100__END_HIDDEN_DECLS
101 101