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