e0abd82767f6c9fd51dc0a7e425f7236631a0f67
[rust-lightning] / lightning / src / offers / signer.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 //! Utilities for signing offer messages and verifying metadata.
11
12 use bitcoin::hashes::{Hash, HashEngine};
13 use bitcoin::hashes::cmp::fixed_time_eq;
14 use bitcoin::hashes::hmac::{Hmac, HmacEngine};
15 use bitcoin::hashes::sha256::Hash as Sha256;
16 use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey, self};
17 use core::convert::TryFrom;
18 use core::fmt;
19 use crate::ln::channelmanager::PaymentId;
20 use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce};
21 use crate::offers::merkle::TlvRecord;
22 use crate::util::ser::Writeable;
23
24 use crate::prelude::*;
25
26 // Use a different HMAC input for each derivation. Otherwise, an attacker could:
27 // - take an Offer that has metadata consisting of a nonce and HMAC
28 // - strip off the HMAC and replace the signing_pubkey where the privkey is the HMAC,
29 // - generate and sign an invoice using the new signing_pubkey, and
30 // - claim they paid it since they would know the preimage of the invoice's payment_hash
31 const DERIVED_METADATA_HMAC_INPUT: &[u8; 16] = &[1; 16];
32 const DERIVED_METADATA_AND_KEYS_HMAC_INPUT: &[u8; 16] = &[2; 16];
33
34 // Additional HMAC inputs to distinguish use cases, either Offer or Refund/InvoiceRequest, where
35 // metadata for the latter contain an encrypted PaymentId.
36 const WITHOUT_ENCRYPTED_PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[3; 16];
37 const WITH_ENCRYPTED_PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[4; 16];
38
39 /// Message metadata which possibly is derived from [`MetadataMaterial`] such that it can be
40 /// verified.
41 #[derive(Clone)]
42 pub(super) enum Metadata {
43         /// Metadata as parsed, supplied by the user, or derived from the message contents.
44         Bytes(Vec<u8>),
45
46         /// Metadata to be derived from message contents and given material.
47         Derived(MetadataMaterial),
48
49         /// Metadata and signing pubkey to be derived from message contents and given material.
50         DerivedSigningPubkey(MetadataMaterial),
51 }
52
53 impl Metadata {
54         pub fn as_bytes(&self) -> Option<&Vec<u8>> {
55                 match self {
56                         Metadata::Bytes(bytes) => Some(bytes),
57                         Metadata::Derived(_) => None,
58                         Metadata::DerivedSigningPubkey(_) => None,
59                 }
60         }
61
62         pub fn has_derivation_material(&self) -> bool {
63                 match self {
64                         Metadata::Bytes(_) => false,
65                         Metadata::Derived(_) => true,
66                         Metadata::DerivedSigningPubkey(_) => true,
67                 }
68         }
69
70         pub fn derives_payer_keys(&self) -> bool {
71                 match self {
72                         // Infer whether Metadata::derived_from was called on Metadata::DerivedSigningPubkey to
73                         // produce Metadata::Bytes. This is merely to determine which fields should be included
74                         // when verifying a message. It doesn't necessarily indicate that keys were in fact
75                         // derived, as wouldn't be the case if a Metadata::Bytes with length PaymentId::LENGTH +
76                         // Nonce::LENGTH had been set explicitly.
77                         Metadata::Bytes(bytes) => bytes.len() == PaymentId::LENGTH + Nonce::LENGTH,
78                         Metadata::Derived(_) => false,
79                         Metadata::DerivedSigningPubkey(_) => true,
80                 }
81         }
82
83         pub fn derives_recipient_keys(&self) -> bool {
84                 match self {
85                         // Infer whether Metadata::derived_from was called on Metadata::DerivedSigningPubkey to
86                         // produce Metadata::Bytes. This is merely to determine which fields should be included
87                         // when verifying a message. It doesn't necessarily indicate that keys were in fact
88                         // derived, as wouldn't be the case if a Metadata::Bytes with length Nonce::LENGTH had
89                         // been set explicitly.
90                         Metadata::Bytes(bytes) => bytes.len() == Nonce::LENGTH,
91                         Metadata::Derived(_) => false,
92                         Metadata::DerivedSigningPubkey(_) => true,
93                 }
94         }
95
96         pub fn without_keys(self) -> Self {
97                 match self {
98                         Metadata::Bytes(_) => self,
99                         Metadata::Derived(_) => self,
100                         Metadata::DerivedSigningPubkey(material) => Metadata::Derived(material),
101                 }
102         }
103
104         pub fn derive_from<W: Writeable, T: secp256k1::Signing>(
105                 self, tlv_stream: W, secp_ctx: Option<&Secp256k1<T>>
106         ) -> (Self, Option<KeyPair>) {
107                 match self {
108                         Metadata::Bytes(_) => (self, None),
109                         Metadata::Derived(mut metadata_material) => {
110                                 tlv_stream.write(&mut metadata_material.hmac).unwrap();
111                                 (Metadata::Bytes(metadata_material.derive_metadata()), None)
112                         },
113                         Metadata::DerivedSigningPubkey(mut metadata_material) => {
114                                 tlv_stream.write(&mut metadata_material.hmac).unwrap();
115                                 let secp_ctx = secp_ctx.unwrap();
116                                 let (metadata, keys) = metadata_material.derive_metadata_and_keys(secp_ctx);
117                                 (Metadata::Bytes(metadata), Some(keys))
118                         },
119                 }
120         }
121 }
122
123 impl Default for Metadata {
124         fn default() -> Self {
125                 Metadata::Bytes(vec![])
126         }
127 }
128
129 impl fmt::Debug for Metadata {
130         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131                 match self {
132                         Metadata::Bytes(bytes) => bytes.fmt(f),
133                         Metadata::Derived(_) => f.write_str("Derived"),
134                         Metadata::DerivedSigningPubkey(_) => f.write_str("DerivedSigningPubkey"),
135                 }
136         }
137 }
138
139 #[cfg(test)]
140 impl PartialEq for Metadata {
141         fn eq(&self, other: &Self) -> bool {
142                 match self {
143                         Metadata::Bytes(bytes) => if let Metadata::Bytes(other_bytes) = other {
144                                 bytes == other_bytes
145                         } else {
146                                 false
147                         },
148                         Metadata::Derived(_) => false,
149                         Metadata::DerivedSigningPubkey(_) => false,
150                 }
151         }
152 }
153
154 /// Material used to create metadata for a message.
155 #[derive(Clone)]
156 pub(super) struct MetadataMaterial {
157         nonce: Nonce,
158         hmac: HmacEngine<Sha256>,
159         // Some for payer metadata and None for offer metadata
160         encrypted_payment_id: Option<[u8; PaymentId::LENGTH]>,
161 }
162
163 impl MetadataMaterial {
164         pub fn new(
165                 nonce: Nonce, expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN],
166                 payment_id: Option<PaymentId>
167         ) -> Self {
168                 // Encrypt payment_id
169                 let encrypted_payment_id = payment_id.map(|payment_id| {
170                         expanded_key.crypt_for_offer(payment_id.0, nonce)
171                 });
172
173                 Self {
174                         nonce,
175                         hmac: expanded_key.hmac_for_offer(nonce, iv_bytes),
176                         encrypted_payment_id,
177                 }
178         }
179
180         fn derive_metadata(mut self) -> Vec<u8> {
181                 self.hmac.input(DERIVED_METADATA_HMAC_INPUT);
182                 self.maybe_include_encrypted_payment_id();
183
184                 let mut bytes = self.encrypted_payment_id.map(|id| id.to_vec()).unwrap_or(vec![]);
185                 bytes.extend_from_slice(self.nonce.as_slice());
186                 bytes.extend_from_slice(Hmac::from_engine(self.hmac).as_byte_array());
187                 bytes
188         }
189
190         fn derive_metadata_and_keys<T: secp256k1::Signing>(
191                 mut self, secp_ctx: &Secp256k1<T>
192         ) -> (Vec<u8>, KeyPair) {
193                 self.hmac.input(DERIVED_METADATA_AND_KEYS_HMAC_INPUT);
194                 self.maybe_include_encrypted_payment_id();
195
196                 let mut bytes = self.encrypted_payment_id.map(|id| id.to_vec()).unwrap_or(vec![]);
197                 bytes.extend_from_slice(self.nonce.as_slice());
198
199                 let hmac = Hmac::from_engine(self.hmac);
200                 let privkey = SecretKey::from_slice(hmac.as_byte_array()).unwrap();
201                 let keys = KeyPair::from_secret_key(secp_ctx, &privkey);
202
203                 (bytes, keys)
204         }
205
206         fn maybe_include_encrypted_payment_id(&mut self) {
207                 match self.encrypted_payment_id {
208                         None => self.hmac.input(WITHOUT_ENCRYPTED_PAYMENT_ID_HMAC_INPUT),
209                         Some(encrypted_payment_id) => {
210                                 self.hmac.input(WITH_ENCRYPTED_PAYMENT_ID_HMAC_INPUT);
211                                 self.hmac.input(&encrypted_payment_id)
212                         },
213                 }
214         }
215 }
216
217 pub(super) fn derive_keys(nonce: Nonce, expanded_key: &ExpandedKey) -> KeyPair {
218         const IV_BYTES: &[u8; IV_LEN] = b"LDK Invoice ~~~~";
219         let secp_ctx = Secp256k1::new();
220         let hmac = Hmac::from_engine(expanded_key.hmac_for_offer(nonce, IV_BYTES));
221         let privkey = SecretKey::from_slice(hmac.as_byte_array()).unwrap();
222         KeyPair::from_secret_key(&secp_ctx, &privkey)
223 }
224
225 /// Verifies data given in a TLV stream was used to produce the given metadata, consisting of:
226 /// - a 256-bit [`PaymentId`],
227 /// - a 128-bit [`Nonce`], and possibly
228 /// - a [`Sha256`] hash of the nonce and the TLV records using the [`ExpandedKey`].
229 ///
230 /// If the latter is not included in the metadata, the TLV stream is used to check if the given
231 /// `signing_pubkey` can be derived from it.
232 ///
233 /// Returns the [`PaymentId`] that should be used for sending the payment.
234 pub(super) fn verify_payer_metadata<'a, T: secp256k1::Signing>(
235         metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN],
236         signing_pubkey: PublicKey, tlv_stream: impl core::iter::Iterator<Item = TlvRecord<'a>>,
237         secp_ctx: &Secp256k1<T>
238 ) -> Result<PaymentId, ()> {
239         if metadata.len() < PaymentId::LENGTH {
240                 return Err(());
241         }
242
243         let mut encrypted_payment_id = [0u8; PaymentId::LENGTH];
244         encrypted_payment_id.copy_from_slice(&metadata[..PaymentId::LENGTH]);
245
246         let mut hmac = hmac_for_message(
247                 &metadata[PaymentId::LENGTH..], expanded_key, iv_bytes, tlv_stream
248         )?;
249         hmac.input(WITH_ENCRYPTED_PAYMENT_ID_HMAC_INPUT);
250         hmac.input(&encrypted_payment_id);
251
252         verify_metadata(
253                 &metadata[PaymentId::LENGTH..], Hmac::from_engine(hmac), signing_pubkey, secp_ctx
254         )?;
255
256         let nonce = Nonce::try_from(&metadata[PaymentId::LENGTH..][..Nonce::LENGTH]).unwrap();
257         let payment_id = expanded_key.crypt_for_offer(encrypted_payment_id, nonce);
258
259         Ok(PaymentId(payment_id))
260 }
261
262 /// Verifies data given in a TLV stream was used to produce the given metadata, consisting of:
263 /// - a 128-bit [`Nonce`] and possibly
264 /// - a [`Sha256`] hash of the nonce and the TLV records using the [`ExpandedKey`].
265 ///
266 /// If the latter is not included in the metadata, the TLV stream is used to check if the given
267 /// `signing_pubkey` can be derived from it.
268 ///
269 /// Returns the [`KeyPair`] for signing the invoice, if it can be derived from the metadata.
270 pub(super) fn verify_recipient_metadata<'a, T: secp256k1::Signing>(
271         metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN],
272         signing_pubkey: PublicKey, tlv_stream: impl core::iter::Iterator<Item = TlvRecord<'a>>,
273         secp_ctx: &Secp256k1<T>
274 ) -> Result<Option<KeyPair>, ()> {
275         let mut hmac = hmac_for_message(metadata, expanded_key, iv_bytes, tlv_stream)?;
276         hmac.input(WITHOUT_ENCRYPTED_PAYMENT_ID_HMAC_INPUT);
277
278         verify_metadata(metadata, Hmac::from_engine(hmac), signing_pubkey, secp_ctx)
279 }
280
281 fn verify_metadata<T: secp256k1::Signing>(
282         metadata: &[u8], hmac: Hmac<Sha256>, signing_pubkey: PublicKey, secp_ctx: &Secp256k1<T>
283 ) -> Result<Option<KeyPair>, ()> {
284         if metadata.len() == Nonce::LENGTH {
285                 let derived_keys = KeyPair::from_secret_key(
286                         secp_ctx, &SecretKey::from_slice(hmac.as_byte_array()).unwrap()
287                 );
288                 if fixed_time_eq(&signing_pubkey.serialize(), &derived_keys.public_key().serialize()) {
289                         Ok(Some(derived_keys))
290                 } else {
291                         Err(())
292                 }
293         } else if metadata[Nonce::LENGTH..].len() == Sha256::LEN {
294                 if fixed_time_eq(&metadata[Nonce::LENGTH..], &hmac.to_byte_array()) {
295                         Ok(None)
296                 } else {
297                         Err(())
298                 }
299         } else {
300                 Err(())
301         }
302 }
303
304 fn hmac_for_message<'a>(
305         metadata: &[u8], expanded_key: &ExpandedKey, iv_bytes: &[u8; IV_LEN],
306         tlv_stream: impl core::iter::Iterator<Item = TlvRecord<'a>>
307 ) -> Result<HmacEngine<Sha256>, ()> {
308         if metadata.len() < Nonce::LENGTH {
309                 return Err(());
310         }
311
312         let nonce = match Nonce::try_from(&metadata[..Nonce::LENGTH]) {
313                 Ok(nonce) => nonce,
314                 Err(_) => return Err(()),
315         };
316         let mut hmac = expanded_key.hmac_for_offer(nonce, iv_bytes);
317
318         for record in tlv_stream {
319                 hmac.input(record.record_bytes);
320         }
321
322         if metadata.len() == Nonce::LENGTH {
323                 hmac.input(DERIVED_METADATA_AND_KEYS_HMAC_INPUT);
324         } else {
325                 hmac.input(DERIVED_METADATA_HMAC_INPUT);
326         }
327
328         Ok(hmac)
329 }