1use crate::*;
2use libsodium_sys::*;
3use subtle::ConstantTimeEq;
4use std::ptr;
5
6pub fn ed25519_verify_before(
8 st: &mut SignState, shared_key: &mut[u8; SHAREDBYTES], sig: &[u8; SIGNBYTES],
9 sender_id: &[u8], recipient_id: &[u8], info: &[u8],
10 sender_pk: &[u8; BYTES], recipient_sk: &[u8; BYTES]
11) -> Result<(), SignCryptError>
12{
13 verify_before(
14 st, shared_key, sig, sender_id, recipient_id,
15 info, sender_pk, recipient_sk, Curve::Ed25519
16 )
17}
18
19pub fn ristretto255_verify_before(
21 st: &mut SignState, shared_key: &mut[u8; SHAREDBYTES], sig: &[u8; SIGNBYTES],
22 sender_id: &[u8], recipient_id: &[u8], info: &[u8],
23 sender_pk: &[u8; BYTES], recipient_sk: &[u8; BYTES]
24) -> Result<(), SignCryptError>
25{
26 verify_before(
27 st, shared_key, sig, sender_id, recipient_id,
28 info, sender_pk, recipient_sk, Curve::Ristretto255
29 )
30}
31
32pub fn verify_before(
34 st: &mut SignState, shared_key: &mut[u8; SHAREDBYTES], sig: &[u8; SIGNBYTES],
35 sender_id: &[u8], recipient_id: &[u8], info: &[u8],
36 sender_pk: &[u8; BYTES], recipient_sk: &[u8; BYTES], curve: Curve
37) -> Result<(), SignCryptError>
38{
39 let mut kp = [0u8; BYTES];
40 let mut rs = [0u8; NONREDUCEDSCALARBYTES];
41
42 if sender_id.len() > 0xff || recipient_id.len() > 0xff || info.len() > 0xff {
43 return Err(SignCryptError::InvalidLength)
44 }
45 if !sc25519_is_canonical(&sig[BYTES..]) {
46 return Err(SignCryptError::NonCanonicalSig)
47 }
48 rs[..SCALARBYTES].copy_from_slice(&sig[..SCALARBYTES]);
49
50 unsafe {
51 match curve {
52 Curve::Ed25519 => {
53 crypto_core_ed25519_scalar_reduce(rs.as_mut_ptr(), rs.as_ptr());
54 if crypto_scalarmult_ed25519_noclamp(kp.as_mut_ptr(), rs.as_ptr(), sender_pk.as_ptr()) != 0 {
55 return Err(SignCryptError::Generic)
56 }
57 crypto_core_ed25519_add(kp.as_mut_ptr(), sig.as_ptr(), kp.as_ptr());
58 if crypto_scalarmult_ed25519_noclamp(kp.as_mut_ptr(), recipient_sk.as_ptr(), kp.as_ptr()) != 0 {
59 return Err(SignCryptError::Generic)
60 }
61 },
62 Curve::Ristretto255 => {
63 if crypto_scalarmult_ristretto255(kp.as_mut_ptr(), rs.as_ptr(), sender_pk.as_ptr()) != 0 {
64 return Err(SignCryptError::Generic)
65 }
66 crypto_core_ristretto255_add(kp.as_mut_ptr(), sig.as_ptr(), kp.as_ptr());
67 if crypto_scalarmult_ristretto255(kp.as_mut_ptr(), recipient_sk.as_ptr(), kp.as_ptr()) != 0 {
68 return Err(SignCryptError::Generic)
69 }
70 }
71 }
72
73 crypto_generichash_init(&mut st.h, ptr::null(), 0, SHAREDBYTES);
74 crypto_generichash_update(&mut st.h, b"shared_key".as_ptr(),"shared_key".len() as u64);
75 crypto_generichash_update(&mut st.h, kp.as_ptr(), kp.len() as u64);
76 lp_update(&mut st.h, sender_id);
77 lp_update(&mut st.h, recipient_id);
78 lp_update(&mut st.h, info);
79 crypto_generichash_final(&mut st.h, shared_key.as_mut_ptr(), SHAREDBYTES);
80
81 crypto_generichash_init(&mut st.h, ptr::null(), 0, NONREDUCEDSCALARBYTES);
82 crypto_generichash_update(&mut st.h, b"sign_key".as_ptr(), "sign_key".len() as u64);
83 crypto_generichash_update(&mut st.h, sig.as_ptr(), BYTES as u64);
84 lp_update(&mut st.h, sender_id);
85 lp_update(&mut st.h, recipient_id);
86 lp_update(&mut st.h, info);
87 }
88 Ok(())
89}
90
91
92pub fn verify_after(
94 st: &mut SignState, sig: &[u8; SIGNBYTES],
95 sender_pk: &[u8; BYTES], c: &[u8], curve: Curve
96) -> Result<(), SignCryptError>
97{
98 let mut expected = [0u8; BYTES];
99 let mut found = [0u8; BYTES];
100 let mut nonreduced = [0u8; NONREDUCEDSCALARBYTES];
101
102 unsafe {
103 crypto_generichash_update(&mut st.h, c.as_ptr(), c.len() as u64);
104 crypto_generichash_final(&mut st.h, nonreduced.as_mut_ptr(), nonreduced.len());
105
106 match curve {
107 Curve::Ed25519 => {
108 crypto_core_ed25519_scalar_reduce(st.challenge.as_mut_ptr(), nonreduced.as_ptr());
109
110 crypto_scalarmult_ed25519_base_noclamp(
111 expected.as_mut_ptr(), sig[BYTES..].as_ptr()
112 );
113 crypto_core_ed25519_add(
114 expected.as_mut_ptr(), expected.as_ptr(), sig.as_ptr()
115 );
116 if crypto_scalarmult_ed25519_noclamp(
117 found.as_mut_ptr(), st.challenge.as_ptr(), sender_pk.as_ptr()
118 ) != 0 {
119 return Err(SignCryptError::Generic)
120 }
121 },
122 Curve::Ristretto255 => {
123 crypto_core_ristretto255_scalar_reduce(st.challenge.as_mut_ptr(), nonreduced.as_ptr());
124
125 crypto_scalarmult_ristretto255_base(
126 expected.as_mut_ptr(), sig[BYTES..].as_ptr()
127 );
128 crypto_core_ristretto255_add(
129 expected.as_mut_ptr(), expected.as_ptr(), sig.as_ptr()
130 );
131 if crypto_scalarmult_ristretto255(
132 found.as_mut_ptr(), st.challenge.as_ptr(), sender_pk.as_ptr()
133 ) != 0 {
134 return Err(SignCryptError::Generic)
135 }
136 }
137 }
138 }
139 let eq: bool = expected[..SCALARBYTES].ct_eq(&found[..SCALARBYTES]).into();
141 if !eq { return Err(SignCryptError::Mismatch) }
142 Ok(())
143}
144
145
146pub fn verify_public(
149 sig: &[u8; SIGNBYTES],
150 sender_id: &[u8], recipient_id: &[u8], info: &[u8],
151 sender_pk: &[u8; BYTES], c: &[u8], curve: Curve
152) -> Result<(), SignCryptError>
153{
154 let mut st = SignState::default();
155
156 if sender_id.len() > 0xff || recipient_id.len() > 0xff || info.len() > 0xff {
157 return Err(SignCryptError::InvalidLength)
158 }
159 if !sc25519_is_canonical(&sig[BYTES..]) {
160 return Err(SignCryptError::NonCanonicalSig)
161 }
162 unsafe {
163 crypto_generichash_init(&mut st.h, ptr::null(), 0, NONREDUCEDSCALARBYTES);
164 crypto_generichash_update(&mut st.h, b"sign_key".as_ptr(), "sign_key".len() as u64);
165 crypto_generichash_update(&mut st.h, sig.as_ptr(), BYTES as u64);
166 lp_update(&mut st.h, sender_id);
167 lp_update(&mut st.h, recipient_id);
168 lp_update(&mut st.h, info);
169 }
170 verify_after(&mut st, sig, sender_pk, c, curve)
171}