summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2022-11-17 19:01:59 +0000
committertb <>2022-11-17 19:01:59 +0000
commit39401085a3fd36d7c2ad32db5f56ac0b9fb95069 (patch)
tree31369c0b26bbeb131ae8a6b5a206ecb70d1c214b /src
parentad8ed8f2cc739b8c0024967dceb20a06ff5cd86a (diff)
downloadopenbsd-39401085a3fd36d7c2ad32db5f56ac0b9fb95069.tar.gz
openbsd-39401085a3fd36d7c2ad32db5f56ac0b9fb95069.tar.bz2
openbsd-39401085a3fd36d7c2ad32db5f56ac0b9fb95069.zip
Prevent Ed25519 signature malleability
Add a check that ensures that the upper half s of an Ed25519 signature is bounded by the group order, i.e, 0 <= s < order. This is required by the Verify procedure in RFC 8032, section 5.1.7, step 1, and prevents simple modifications of signatures such as adding (a multiple of) the group order to the upper half of the signature. Found with EdDSA testcase 63 of project Wycheproof. ok beck jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/curve25519/curve25519.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/lib/libcrypto/curve25519/curve25519.c b/src/lib/libcrypto/curve25519/curve25519.c
index c35863ef87..cd1b0c5802 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.13 2022/11/09 17:45:55 jsing Exp $ */ 1/* $OpenBSD: curve25519.c,v 1.14 2022/11/17 19:01:59 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2015, Google Inc. 3 * Copyright (c) 2015, Google Inc.
4 * 4 *
@@ -24,6 +24,7 @@
24 * The field functions are shared by Ed25519 and X25519 where possible. 24 * The field functions are shared by Ed25519 and X25519 where possible.
25 */ 25 */
26 26
27#include <stdio.h>
27#include <stdlib.h> 28#include <stdlib.h>
28#include <string.h> 29#include <string.h>
29 30
@@ -4671,10 +4672,22 @@ int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
4671 return 1; 4672 return 1;
4672} 4673}
4673 4674
4675/*
4676 * Little endian representation of the order of edwards25519,
4677 * see https://www.rfc-editor.org/rfc/rfc7748#section-4.1
4678 */
4679static const uint8_t order[] = {
4680 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
4681 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
4682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
4684};
4685
4674int ED25519_verify(const uint8_t *message, size_t message_len, 4686int ED25519_verify(const uint8_t *message, size_t message_len,
4675 const uint8_t signature[ED25519_SIGNATURE_LENGTH], 4687 const uint8_t signature[ED25519_SIGNATURE_LENGTH],
4676 const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH]) { 4688 const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH]) {
4677 ge_p3 A; 4689 ge_p3 A;
4690 int i;
4678 if ((signature[63] & 224) != 0 || 4691 if ((signature[63] & 224) != 0 ||
4679 x25519_ge_frombytes_vartime(&A, public_key) != 0) { 4692 x25519_ge_frombytes_vartime(&A, public_key) != 0) {
4680 return 0; 4693 return 0;
@@ -4690,6 +4703,20 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
4690 uint8_t scopy[32]; 4703 uint8_t scopy[32];
4691 memcpy(scopy, signature + 32, 32); 4704 memcpy(scopy, signature + 32, 32);
4692 4705
4706 /*
4707 * https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that scopy be
4708 * in the range [0, order) to prevent signature malleability. This value is
4709 * public, so there is no need to make this constant time.
4710 */
4711 for (i = 31; i >= 0; i--) {
4712 if (scopy[i] > order[i])
4713 return 0;
4714 if (scopy[i] < order[i])
4715 break;
4716 if (i == 0)
4717 return 0;
4718 }
4719
4693 SHA512_CTX hash_ctx; 4720 SHA512_CTX hash_ctx;
4694 SHA512_Init(&hash_ctx); 4721 SHA512_Init(&hash_ctx);
4695 SHA512_Update(&hash_ctx, signature, 32); 4722 SHA512_Update(&hash_ctx, signature, 32);