diff options
author | jsing <> | 2022-11-09 17:39:29 +0000 |
---|---|---|
committer | jsing <> | 2022-11-09 17:39:29 +0000 |
commit | 390601a304fd7ed95013cfc05628a1a33f115b25 (patch) | |
tree | f0cbe11399d675629473425a560232c59fa77acb | |
parent | ba67559fec418c6b97834e077e96f2392244261d (diff) | |
download | openbsd-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.c | 51 | ||||
-rw-r--r-- | src/lib/libcrypto/curve25519/curve25519.h | 28 | ||||
-rw-r--r-- | src/lib/libcrypto/curve25519/curve25519_internal.h | 6 |
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 | ||
4618 | void ED25519_keypair(uint8_t out_public_key[32], uint8_t out_private_key[64]) { | 4618 | void 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 | |||
4632 | void 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 | ||
4624 | int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, | 4639 | int 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 | ||
4658 | int ED25519_verify(const uint8_t *message, size_t message_len, | 4674 | int 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 | ||
4695 | void 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 | */ |
85 | void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN], | 80 | void 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 | */ |
93 | int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, | 88 | int 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 | */ |
101 | int ED25519_verify(const uint8_t *message, size_t message_len, | 97 | int 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], | |||
94 | void x25519_scalar_mult_generic(uint8_t out[32], const uint8_t scalar[32], | 94 | void 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 | ||
97 | void ED25519_keypair_from_seed(uint8_t out_public_key[32], | 97 | void 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 | ||