signcryption/
verify.rs

1use crate::*;
2use libsodium_sys::*;
3use subtle::ConstantTimeEq;
4use std::ptr;
5
6/// Convenience function for [`verify_before`]
7pub 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 
19/// Convenience function for [`verify_before`]
20pub 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
32/// Message verification before decryption
33pub 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
92/// Message verification after decryption
93pub 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  // Subtle constant time equality
140  let eq: bool = expected[..SCALARBYTES].ct_eq(&found[..SCALARBYTES]).into();
141  if !eq { return Err(SignCryptError::Mismatch) }
142  Ok(())
143}
144
145
146/// Verifies the data was signed by a specific sender to a receiver without enabling
147/// the ability to decrypt the ciphertext 
148pub 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}