1 // Copyright 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Cryptography library for LMP procedures.
16 //!
17 //! IMPORTANT
18 //! These cryptography methods do not provide any security or correctness
19 //! ensurance. They should be used only in Bluetooth emulation, not including
20 //! any production environment.
21 
22 use num_bigint::{BigInt, Sign};
23 use num_integer::Integer;
24 use num_traits::{One, Signed, Zero};
25 use rand::{thread_rng, Rng};
26 use std::convert::TryInto;
27 use std::marker::PhantomData;
28 
29 #[derive(Debug, Clone, PartialEq, Eq)]
30 pub enum PublicKey {
31     P192([u8; P192r1::PUBLIC_KEY_SIZE]),
32     P256([u8; P256r1::PUBLIC_KEY_SIZE]),
33 }
34 
35 impl PublicKey {
new(size: usize) -> Option<Self>36     pub fn new(size: usize) -> Option<Self> {
37         match size {
38             P192r1::PUBLIC_KEY_SIZE => Some(Self::P192([0; P192r1::PUBLIC_KEY_SIZE])),
39             P256r1::PUBLIC_KEY_SIZE => Some(Self::P256([0; P256r1::PUBLIC_KEY_SIZE])),
40             _ => None,
41         }
42     }
43 
from_bytes(bytes: &[u8]) -> Option<Self>44     fn from_bytes(bytes: &[u8]) -> Option<Self> {
45         if let Ok(inner) = bytes.try_into() {
46             Some(PublicKey::P192(inner))
47         } else if let Ok(inner) = bytes.try_into() {
48             Some(PublicKey::P256(inner))
49         } else {
50             None
51         }
52     }
53 
as_slice(&self) -> &[u8]54     pub fn as_slice(&self) -> &[u8] {
55         match self {
56             PublicKey::P192(inner) => inner,
57             PublicKey::P256(inner) => inner,
58         }
59     }
60 
size(&self) -> usize61     pub fn size(&self) -> usize {
62         self.as_slice().len()
63     }
64 
as_mut_slice(&mut self) -> &mut [u8]65     pub fn as_mut_slice(&mut self) -> &mut [u8] {
66         match self {
67             PublicKey::P192(inner) => inner,
68             PublicKey::P256(inner) => inner,
69         }
70     }
71 
get_x(&self) -> BigInt72     fn get_x(&self) -> BigInt {
73         BigInt::from_signed_bytes_le(&self.as_slice()[0..self.size() / 2])
74     }
75 
get_y(&self) -> BigInt76     fn get_y(&self) -> BigInt {
77         BigInt::from_signed_bytes_le(&self.as_slice()[self.size() / 2..self.size()])
78     }
79 
to_point<Curve: EllipticCurve>(&self) -> Point<Curve>80     fn to_point<Curve: EllipticCurve>(&self) -> Point<Curve> {
81         Point::from_affine(self.get_x(), self.get_y())
82     }
83 }
84 
85 #[derive(Debug, Clone, PartialEq, Eq)]
86 pub enum PrivateKey {
87     P192([u8; P192r1::PRIVATE_KEY_SIZE]),
88     P256([u8; P256r1::PRIVATE_KEY_SIZE]),
89 }
90 
91 #[derive(Debug, Clone, PartialEq, Eq)]
92 pub enum DhKey {
93     P192([u8; P192r1::PUBLIC_KEY_SIZE]),
94     P256([u8; P256r1::PUBLIC_KEY_SIZE]),
95 }
96 
97 impl DhKey {
from_bytes(bytes: &[u8]) -> Option<Self>98     fn from_bytes(bytes: &[u8]) -> Option<Self> {
99         if let Ok(inner) = bytes.try_into() {
100             Some(DhKey::P192(inner))
101         } else if let Ok(inner) = bytes.try_into() {
102             Some(DhKey::P256(inner))
103         } else {
104             None
105         }
106     }
107 }
108 
109 impl PrivateKey {
110     // Generate a private key in range[1,2**191]
generate_p192() -> Self111     pub fn generate_p192() -> Self {
112         let random_bytes: [u8; P192r1::PRIVATE_KEY_SIZE] = thread_rng().gen();
113         let mut key = BigInt::from_signed_bytes_le(&random_bytes);
114 
115         if key.is_negative() {
116             key = -key;
117         }
118         if key < BigInt::one() {
119             key = BigInt::one();
120         }
121         let buf = key.to_signed_bytes_le();
122         let mut inner = [0; P192r1::PRIVATE_KEY_SIZE];
123         inner[0..buf.len()].copy_from_slice(&buf);
124         Self::P192(inner)
125     }
126 
generate_p256() -> Self127     pub fn generate_p256() -> Self {
128         let random_bytes: [u8; P256r1::PRIVATE_KEY_SIZE] = thread_rng().gen();
129         let mut key = BigInt::from_signed_bytes_le(&random_bytes);
130 
131         if key.is_negative() {
132             key = -key;
133         }
134         if key < BigInt::one() {
135             key = BigInt::one();
136         }
137         let buf = key.to_signed_bytes_le();
138         let mut inner = [0; P256r1::PRIVATE_KEY_SIZE];
139         inner[0..buf.len()].copy_from_slice(&buf);
140         Self::P256(inner)
141     }
142 
as_slice(&self) -> &[u8]143     pub fn as_slice(&self) -> &[u8] {
144         match self {
145             PrivateKey::P192(inner) => inner,
146             PrivateKey::P256(inner) => inner,
147         }
148     }
149 
to_bigint(&self) -> BigInt150     fn to_bigint(&self) -> BigInt {
151         BigInt::from_signed_bytes_le(self.as_slice())
152     }
153 
derive(&self) -> PublicKey154     pub fn derive(&self) -> PublicKey {
155         let bytes = match self {
156             PrivateKey::P192(_) => {
157                 Point::<P192r1>::generate_public_key(&self.to_bigint()).to_bytes()
158             }
159             PrivateKey::P256(_) => {
160                 Point::<P256r1>::generate_public_key(&self.to_bigint()).to_bytes()
161             }
162         }
163         .unwrap();
164         PublicKey::from_bytes(&bytes).unwrap()
165     }
166 
shared_secret(&self, peer_public_key: PublicKey) -> DhKey167     pub fn shared_secret(&self, peer_public_key: PublicKey) -> DhKey {
168         let bytes = match self {
169             PrivateKey::P192(_) => {
170                 (&peer_public_key.to_point::<P192r1>() * &self.to_bigint()).to_bytes()
171             }
172             PrivateKey::P256(_) => {
173                 (&peer_public_key.to_point::<P256r1>() * &self.to_bigint()).to_bytes()
174             }
175         }
176         .unwrap();
177         DhKey::from_bytes(&bytes).unwrap()
178     }
179 }
180 
181 // Modular Inverse
mod_inv(x: &BigInt, m: &BigInt) -> Option<BigInt>182 fn mod_inv(x: &BigInt, m: &BigInt) -> Option<BigInt> {
183     let egcd = x.extended_gcd(m);
184     if !egcd.gcd.is_one() {
185         None
186     } else {
187         Some(egcd.x % m)
188     }
189 }
190 
191 trait EllipticCurve {
192     type Param: AsRef<[u8]>;
193     const A: i32;
194     const P: Self::Param;
195     const G_X: Self::Param;
196     const G_Y: Self::Param;
197     const PRIVATE_KEY_SIZE: usize;
198     const PUBLIC_KEY_SIZE: usize;
199 
p() -> BigInt200     fn p() -> BigInt {
201         BigInt::from_bytes_be(Sign::Plus, Self::P.as_ref())
202     }
203 }
204 
205 #[derive(Debug, Clone, PartialEq)]
206 struct P192r1;
207 
208 impl EllipticCurve for P192r1 {
209     type Param = [u8; 24];
210 
211     const A: i32 = -3;
212     const P: Self::Param = [
213         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
214         0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
215     ];
216     const G_X: Self::Param = [
217         0x18, 0x8d, 0xa8, 0x0e, 0xb0, 0x30, 0x90, 0xf6, 0x7c, 0xbf, 0x20, 0xeb, 0x43, 0xa1, 0x88,
218         0x00, 0xf4, 0xff, 0x0a, 0xfd, 0x82, 0xff, 0x10, 0x12,
219     ];
220     const G_Y: Self::Param = [
221         0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, 0x6b, 0x24, 0xcd,
222         0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11,
223     ];
224     const PRIVATE_KEY_SIZE: usize = 24;
225     const PUBLIC_KEY_SIZE: usize = 48;
226 }
227 
228 #[derive(Debug, Clone, PartialEq)]
229 struct P256r1;
230 
231 impl EllipticCurve for P256r1 {
232     type Param = [u8; 32];
233 
234     const A: i32 = -3;
235     const P: Self::Param = [
236         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237         0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
238         0xff, 0xff,
239     ];
240     const G_X: Self::Param = [
241         0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40,
242         0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98,
243         0xc2, 0x96,
244     ];
245     const G_Y: Self::Param = [
246         0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
247         0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf,
248         0x51, 0xf5,
249     ];
250     const PRIVATE_KEY_SIZE: usize = 32;
251     const PUBLIC_KEY_SIZE: usize = 64;
252 }
253 
254 // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
255 #[derive(Debug, PartialEq)]
256 enum Point<Curve> {
257     Infinite(PhantomData<Curve>),
258     Finite { x: BigInt, y: BigInt, z: BigInt, _curve: PhantomData<Curve> },
259 }
260 
261 impl<Curve> Point<Curve>
262 where
263     Curve: EllipticCurve,
264 {
o() -> Self265     fn o() -> Self {
266         Point::Infinite(PhantomData)
267     }
268 
generate_public_key(private_key: &BigInt) -> Self269     fn generate_public_key(private_key: &BigInt) -> Self {
270         &Self::g() * private_key
271     }
272 
new(x: BigInt, y: BigInt, z: BigInt) -> Self273     fn new(x: BigInt, y: BigInt, z: BigInt) -> Self {
274         Point::Finite { x, y, z, _curve: PhantomData }
275     }
276 
from_affine(x: BigInt, y: BigInt) -> Self277     fn from_affine(x: BigInt, y: BigInt) -> Self {
278         Self::new(x, y, BigInt::from(1))
279     }
280 
g() -> Self281     fn g() -> Self {
282         Self::from_affine(
283             BigInt::from_bytes_be(Sign::Plus, Curve::G_X.as_ref()),
284             BigInt::from_bytes_be(Sign::Plus, Curve::G_Y.as_ref()),
285         )
286     }
287 
to_affine(&self) -> Option<(BigInt, BigInt)>288     fn to_affine(&self) -> Option<(BigInt, BigInt)> {
289         match self {
290             Point::Infinite(_) => None,
291             Point::Finite { x, y, z, _curve } => {
292                 let p = &Curve::p();
293                 let inv_z = mod_inv(z, p).unwrap();
294                 let affine_x = (x * inv_z.pow(2)) % p;
295                 let affine_y = (y * inv_z.pow(3)) % p;
296                 Some((affine_x, affine_y))
297             }
298         }
299     }
300 
to_bytes(&self) -> Option<Vec<u8>>301     fn to_bytes(&self) -> Option<Vec<u8>> {
302         self.to_affine().map(|(x, y)| {
303             let mut x = x.to_signed_bytes_le();
304             x.resize(Curve::PRIVATE_KEY_SIZE, 0);
305             let mut y = y.to_signed_bytes_le();
306             y.resize(Curve::PRIVATE_KEY_SIZE, 0);
307             x.append(&mut y);
308             x
309         })
310     }
311 
double(&self) -> Self312     fn double(&self) -> Self {
313         // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates#Point_Doubling_(4M_+_6S_or_4M_+_4S)
314         match self {
315             Point::Infinite(_) => Point::o(),
316             Point::Finite { y, .. } if y.is_zero() => Point::o(),
317             Point::Finite { x, y, z, _curve } => {
318                 let s = 4 * x * y.pow(2);
319                 let m: BigInt = 3 * x.pow(2) + Curve::A * z.pow(4);
320 
321                 let rx = m.pow(2) - 2 * &s;
322                 let ry = m * (s - &rx) - 8 * y.pow(4);
323                 let rz = 2 * y * z;
324 
325                 let p = &Curve::p();
326 
327                 Point::new(rx % p, ry % p, rz % p)
328             }
329         }
330     }
331 }
332 
333 impl<Curve> Clone for Point<Curve>
334 where
335     Curve: EllipticCurve,
336 {
clone(&self) -> Self337     fn clone(&self) -> Self {
338         match self {
339             Point::Infinite(_) => Point::o(),
340             Point::Finite { x, y, z, _curve } => Point::new(x.clone(), y.clone(), z.clone()),
341         }
342     }
343 }
344 
345 // Elliptic Curve Group Addition
346 // https://mathworld.wolfram.com/EllipticCurve.html
347 impl<Curve> std::ops::Add<&Point<Curve>> for &Point<Curve>
348 where
349     Curve: EllipticCurve,
350 {
351     type Output = Point<Curve>;
352 
add(self, rhs: &Point<Curve>) -> Self::Output353     fn add(self, rhs: &Point<Curve>) -> Self::Output {
354         // P + O = O + P = P
355         match (self, rhs) {
356             (Point::Infinite(_), Point::Infinite(_)) => Point::o(),
357             (Point::Infinite(_), Point::Finite { .. }) => rhs.clone(),
358             (Point::Finite { .. }, Point::Infinite(_)) => self.clone(),
359             (
360                 Point::Finite { _curve: _, x: x1, y: y1, z: z1 },
361                 Point::Finite { _curve: _, x: x2, y: y2, z: z2 },
362             ) => {
363                 // https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates#Point_Addition_(12M_+_4S)
364                 let p = &Curve::p();
365                 let u1 = (x1 * z2.pow(2)) % p;
366                 let u2 = (x2 * z1.pow(2)) % p;
367                 let s1 = (y1 * z2.pow(3)) % p;
368                 let s2 = (y2 * z1.pow(3)) % p;
369 
370                 if u1 == u2 {
371                     if s1 != s2 {
372                         Point::o()
373                     } else {
374                         self.double()
375                     }
376                 } else {
377                     let h = &u2 - &u1;
378                     let r = &s2 - &s1;
379 
380                     let h3 = h.pow(3) % p;
381                     let u1h2 = (u1 * h.pow(2)) % p;
382                     let x3 = r.pow(2) - &h3 - 2 * &u1h2;
383                     let y3 = r * (u1h2 - &x3) - s1 * h3;
384                     let z3 = h * z1 * z2;
385 
386                     Point::new(x3 % p, y3 % p, z3 % p)
387                 }
388             }
389         }
390     }
391 }
392 
393 impl<Curve> std::ops::Mul<&BigInt> for &Point<Curve>
394 where
395     Curve: EllipticCurve,
396 {
397     type Output = Point<Curve>;
398 
mul(self, rhs: &BigInt) -> Self::Output399     fn mul(self, rhs: &BigInt) -> Self::Output {
400         let mut addend = self.clone();
401         let mut result = Point::o();
402         let mut i = rhs.clone();
403 
404         // O(logN) double-and-add multiplication
405         while !i.is_zero() {
406             if i.is_odd() {
407                 result = &result + &addend;
408             }
409             addend = addend.double();
410             i /= 2;
411         }
412         result
413     }
414 }
415 
416 #[cfg(test)]
417 mod tests {
418     use crate::lmp::ec::*;
419     use num_bigint::BigInt;
420 
421     struct EcTestCase<const N: usize> {
422         pub priv_a: [u8; N],
423         pub priv_b: [u8; N],
424         pub pub_a: [u8; N],
425         pub dh_x: [u8; N],
426     }
427 
428     // Private A, Private B, Public A(x), DHKey
429     const P192_TEST_CASES: [EcTestCase<48>; 4] = [
430         EcTestCase::<48> {
431             priv_a: *b"07915f86918ddc27005df1d6cf0c142b625ed2eff4a518ff",
432             priv_b: *b"1e636ca790b50f68f15d8dbe86244e309211d635de00e16d",
433             pub_a: *b"15207009984421a6586f9fc3fe7e4329d2809ea51125f8ed",
434             dh_x: *b"fb3ba2012c7e62466e486e229290175b4afebc13fdccee46",
435         },
436         EcTestCase::<48> {
437             priv_a: *b"52ec1ca6e0ec973c29065c3ca10be80057243002f09bb43e",
438             priv_b: *b"57231203533e9efe18cc622fd0e34c6a29c6e0fa3ab3bc53",
439             pub_a: *b"45571f027e0d690795d61560804da5de789a48f94ab4b07e",
440             dh_x: *b"a20a34b5497332aa7a76ab135cc0c168333be309d463c0c0",
441         },
442         EcTestCase::<48> {
443             priv_a: *b"00a0df08eaf51e6e7be519d67c6749ea3f4517cdd2e9e821",
444             priv_b: *b"2bf5e0d1699d50ca5025e8e2d9b13244b4d322a328be1821",
445             pub_a: *b"2ed35b430fa45f9d329186d754eeeb0495f0f653127f613d",
446             dh_x: *b"3b3986ba70790762f282a12a6d3bcae7a2ca01e25b87724e",
447         },
448         EcTestCase::<48> {
449             priv_a: *b"030a4af66e1a4d590a83e0284fca5cdf83292b84f4c71168",
450             priv_b: *b"12448b5c69ecd10c0471060f2bf86345c5e83c03d16bae2c",
451             pub_a: *b"f24a6899218fa912e7e4a8ba9357cb8182958f9fa42c968c",
452             dh_x: *b"4a78f83fba757c35f94abea43e92effdd2bc700723c61939",
453         },
454     ];
455 
456     // Private A, Private B, Public A(x), DHKey
457     const P256_TEST_CASES: [EcTestCase<64>; 2] = [
458         EcTestCase::<64> {
459             priv_a: *b"3f49f6d4a3c55f3874c9b3e3d2103f504aff607beb40b7995899b8a6cd3c1abd",
460             priv_b: *b"55188b3d32f6bb9a900afcfbeed4e72a59cb9ac2f19d7cfb6b4fdd49f47fc5fd",
461             pub_a: *b"20b003d2f297be2c5e2c83a7e9f9a5b9eff49111acf4fddbcc0301480e359de6",
462             dh_x: *b"ec0234a357c8ad05341010a60a397d9b99796b13b4f866f1868d34f373bfa698",
463         },
464         EcTestCase::<64> {
465             priv_a: *b"06a516693c9aa31a6084545d0c5db641b48572b97203ddffb7ac73f7d0457663",
466             priv_b: *b"529aa0670d72cd6497502ed473502b037e8803b5c60829a5a3caa219505530ba",
467             pub_a: *b"2c31a47b5779809ef44cb5eaaf5c3e43d5f8faad4a8794cb987e9b03745c78dd",
468             dh_x: *b"ab85843a2f6d883f62e5684b38e307335fe6e1945ecd19604105c6f23221eb69",
469         },
470     ];
471 
472     #[test]
p192()473     fn p192() {
474         for test_case in P192_TEST_CASES {
475             let priv_a = BigInt::parse_bytes(&test_case.priv_a, 16).unwrap();
476             let priv_b = BigInt::parse_bytes(&test_case.priv_b, 16).unwrap();
477             let pub_a = Point::<P192r1>::generate_public_key(&priv_a);
478             let pub_b = Point::<P192r1>::generate_public_key(&priv_b);
479             assert_eq!(
480                 pub_a.to_affine().unwrap().0,
481                 BigInt::parse_bytes(&test_case.pub_a, 16).unwrap()
482             );
483             let shared = &pub_a * &priv_b;
484             assert_eq!(
485                 shared.to_affine().unwrap().0,
486                 BigInt::parse_bytes(&test_case.dh_x, 16).unwrap()
487             );
488             assert_eq!(
489                 (&pub_a * &priv_b).to_affine().unwrap().0,
490                 (&pub_b * &priv_a).to_affine().unwrap().0
491             );
492         }
493     }
494 
495     #[test]
p256()496     fn p256() {
497         for test_case in P256_TEST_CASES {
498             let priv_a = BigInt::parse_bytes(&test_case.priv_a, 16).unwrap();
499             let priv_b = BigInt::parse_bytes(&test_case.priv_b, 16).unwrap();
500             let pub_a = Point::<P256r1>::generate_public_key(&priv_a);
501             let pub_b = Point::<P256r1>::generate_public_key(&priv_b);
502             assert_eq!(
503                 pub_a.to_affine().unwrap().0,
504                 BigInt::parse_bytes(&test_case.pub_a, 16).unwrap()
505             );
506             let shared = &pub_a * &priv_b;
507             assert_eq!(
508                 shared.to_affine().unwrap().0,
509                 BigInt::parse_bytes(&test_case.dh_x, 16).unwrap()
510             );
511             assert_eq!(
512                 (&pub_a * &priv_b).to_affine().unwrap().0,
513                 (&pub_b * &priv_a).to_affine().unwrap().0
514             );
515         }
516     }
517 }
518