diff options
Diffstat (limited to 'libs/libsignal/src/curve25519/ed25519/additions/xeddsa.c')
-rw-r--r-- | libs/libsignal/src/curve25519/ed25519/additions/xeddsa.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/libs/libsignal/src/curve25519/ed25519/additions/xeddsa.c b/libs/libsignal/src/curve25519/ed25519/additions/xeddsa.c new file mode 100644 index 0000000000..63b73bf2ed --- /dev/null +++ b/libs/libsignal/src/curve25519/ed25519/additions/xeddsa.c @@ -0,0 +1,80 @@ +#include <string.h> +#include "ge.h" +#include "crypto_additions.h" +#include "zeroize.h" +#include "xeddsa.h" +#include "crypto_verify_32.h" + +int xed25519_sign(unsigned char* signature_out, + const unsigned char* curve25519_privkey, + const unsigned char* msg, const unsigned long msg_len, + const unsigned char* random) +{ + unsigned char a[32], aneg[32]; + unsigned char A[32]; + ge_p3 ed_pubkey_point; + unsigned char *sigbuf; /* working buffer */ + unsigned char sign_bit = 0; + + if ((sigbuf = malloc(msg_len + 128)) == 0) { + memset(signature_out, 0, 64); + return -1; + } + + /* Convert the Curve25519 privkey to an Ed25519 public key */ + ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey); + ge_p3_tobytes(A, &ed_pubkey_point); + + /* Force Edwards sign bit to zero */ + sign_bit = (A[31] & 0x80) >> 7; + memcpy(a, curve25519_privkey, 32); + sc_neg(aneg, a); + sc_cmov(a, aneg, sign_bit); + A[31] &= 0x7F; + + /* Perform an Ed25519 signature with explicit private key */ + crypto_sign_modified(sigbuf, msg, msg_len, a, A, random); + memmove(signature_out, sigbuf, 64); + + zeroize(a, 32); + zeroize(aneg, 32); + free(sigbuf); + return 0; +} + +int xed25519_verify(const unsigned char* signature, + const unsigned char* curve25519_pubkey, + const unsigned char* msg, const unsigned long msg_len) +{ + fe u; + fe y; + unsigned char ed_pubkey[32]; + unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */ + unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */ + + if (msg_len > MAX_MSG_LEN) { + return -1; + } + + /* Convert the Curve25519 public key into an Ed25519 public key. + + y = (u - 1) / (u + 1) + + NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp + */ + if (!fe_isreduced(curve25519_pubkey)) + return -1; + fe_frombytes(u, curve25519_pubkey); + fe_montx_to_edy(y, u); + fe_tobytes(ed_pubkey, y); + + memmove(verifybuf, signature, 64); + memmove(verifybuf+64, msg, msg_len); + + /* Then perform a normal Ed25519 verification, return 0 on success */ + /* The below call has a strange API: */ + /* verifybuf = R || S || message */ + /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets + replaced with pubkey for hashing */ + return crypto_sign_open_modified(verifybuf2, verifybuf, 64 + msg_len, ed_pubkey); +} |