diff options
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r-- | net/bluetooth/smp.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index aa20bee97501..57fc7d0cadf3 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -24,6 +24,123 @@ | |||
24 | #include <net/bluetooth/hci_core.h> | 24 | #include <net/bluetooth/hci_core.h> |
25 | #include <net/bluetooth/l2cap.h> | 25 | #include <net/bluetooth/l2cap.h> |
26 | #include <net/bluetooth/smp.h> | 26 | #include <net/bluetooth/smp.h> |
27 | #include <linux/crypto.h> | ||
28 | #include <crypto/b128ops.h> | ||
29 | |||
30 | static inline void swap128(u8 src[16], u8 dst[16]) | ||
31 | { | ||
32 | int i; | ||
33 | for (i = 0; i < 16; i++) | ||
34 | dst[15 - i] = src[i]; | ||
35 | } | ||
36 | |||
37 | static inline void swap56(u8 src[7], u8 dst[7]) | ||
38 | { | ||
39 | int i; | ||
40 | for (i = 0; i < 7; i++) | ||
41 | dst[6 - i] = src[i]; | ||
42 | } | ||
43 | |||
44 | static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | ||
45 | { | ||
46 | struct blkcipher_desc desc; | ||
47 | struct scatterlist sg; | ||
48 | int err, iv_len; | ||
49 | unsigned char iv[128]; | ||
50 | |||
51 | if (tfm == NULL) { | ||
52 | BT_ERR("tfm %p", tfm); | ||
53 | return -EINVAL; | ||
54 | } | ||
55 | |||
56 | desc.tfm = tfm; | ||
57 | desc.flags = 0; | ||
58 | |||
59 | err = crypto_blkcipher_setkey(tfm, k, 16); | ||
60 | if (err) { | ||
61 | BT_ERR("cipher setkey failed: %d", err); | ||
62 | return err; | ||
63 | } | ||
64 | |||
65 | sg_init_one(&sg, r, 16); | ||
66 | |||
67 | iv_len = crypto_blkcipher_ivsize(tfm); | ||
68 | if (iv_len) { | ||
69 | memset(&iv, 0xff, iv_len); | ||
70 | crypto_blkcipher_set_iv(tfm, iv, iv_len); | ||
71 | } | ||
72 | |||
73 | err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); | ||
74 | if (err) | ||
75 | BT_ERR("Encrypt data error %d", err); | ||
76 | |||
77 | return err; | ||
78 | } | ||
79 | |||
80 | static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | ||
81 | u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, | ||
82 | u8 _rat, bdaddr_t *ra, u8 res[16]) | ||
83 | { | ||
84 | u8 p1[16], p2[16]; | ||
85 | int err; | ||
86 | |||
87 | memset(p1, 0, 16); | ||
88 | |||
89 | /* p1 = pres || preq || _rat || _iat */ | ||
90 | swap56(pres, p1); | ||
91 | swap56(preq, p1 + 7); | ||
92 | p1[14] = _rat; | ||
93 | p1[15] = _iat; | ||
94 | |||
95 | memset(p2, 0, 16); | ||
96 | |||
97 | /* p2 = padding || ia || ra */ | ||
98 | baswap((bdaddr_t *) (p2 + 4), ia); | ||
99 | baswap((bdaddr_t *) (p2 + 10), ra); | ||
100 | |||
101 | /* res = r XOR p1 */ | ||
102 | u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); | ||
103 | |||
104 | /* res = e(k, res) */ | ||
105 | err = smp_e(tfm, k, res); | ||
106 | if (err) { | ||
107 | BT_ERR("Encrypt data error"); | ||
108 | return err; | ||
109 | } | ||
110 | |||
111 | /* res = res XOR p2 */ | ||
112 | u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); | ||
113 | |||
114 | /* res = e(k, res) */ | ||
115 | err = smp_e(tfm, k, res); | ||
116 | if (err) | ||
117 | BT_ERR("Encrypt data error"); | ||
118 | |||
119 | return err; | ||
120 | } | ||
121 | |||
122 | static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], | ||
123 | u8 r1[16], u8 r2[16], u8 _r[16]) | ||
124 | { | ||
125 | int err; | ||
126 | |||
127 | /* Just least significant octets from r1 and r2 are considered */ | ||
128 | memcpy(_r, r1 + 8, 8); | ||
129 | memcpy(_r + 8, r2 + 8, 8); | ||
130 | |||
131 | err = smp_e(tfm, k, _r); | ||
132 | if (err) | ||
133 | BT_ERR("Encrypt data error"); | ||
134 | |||
135 | return err; | ||
136 | } | ||
137 | |||
138 | static int smp_rand(u8 *buf) | ||
139 | { | ||
140 | get_random_bytes(buf, 16); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
27 | 144 | ||
28 | static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, | 145 | static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, |
29 | u16 dlen, void *data) | 146 | u16 dlen, void *data) |