WPS: Split wps_common.c into parts
[libeap.git] / src / wps / wps_attr_build.c
1 /*
2  * Wi-Fi Protected Setup - attribute building
3  * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "dh_groups.h"
19 #include "sha256.h"
20 #include "aes_wrap.h"
21 #include "wps_i.h"
22
23
24 int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
25 {
26         struct wpabuf *pubkey;
27
28         wpa_printf(MSG_DEBUG, "WPS:  * Public Key");
29         pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey);
30         if (pubkey == NULL) {
31                 wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
32                            "Diffie-Hellman handshake");
33                 return -1;
34         }
35
36         wpabuf_put_be16(msg, ATTR_PUBLIC_KEY);
37         wpabuf_put_be16(msg, wpabuf_len(pubkey));
38         wpabuf_put_buf(msg, pubkey);
39
40         if (wps->registrar) {
41                 wpabuf_free(wps->dh_pubkey_r);
42                 wps->dh_pubkey_r = pubkey;
43         } else {
44                 wpabuf_free(wps->dh_pubkey_e);
45                 wps->dh_pubkey_e = pubkey;
46         }
47
48         return 0;
49 }
50
51
52 int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type)
53 {
54         wpa_printf(MSG_DEBUG, "WPS:  * Request Type");
55         wpabuf_put_be16(msg, ATTR_REQUEST_TYPE);
56         wpabuf_put_be16(msg, 1);
57         wpabuf_put_u8(msg, type);
58         return 0;
59 }
60
61
62 int wps_build_config_methods(struct wpabuf *msg, u16 methods)
63 {
64         wpa_printf(MSG_DEBUG, "WPS:  * Config Methods (%x)", methods);
65         wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
66         wpabuf_put_be16(msg, 2);
67         wpabuf_put_be16(msg, methods);
68         return 0;
69 }
70
71
72 int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
73 {
74         wpa_printf(MSG_DEBUG, "WPS:  * UUID-E");
75         wpabuf_put_be16(msg, ATTR_UUID_E);
76         wpabuf_put_be16(msg, WPS_UUID_LEN);
77         wpabuf_put_data(msg, uuid, WPS_UUID_LEN);
78         return 0;
79 }
80
81
82 int wps_build_dev_password_id(struct wpabuf *msg, u16 id)
83 {
84         wpa_printf(MSG_DEBUG, "WPS:  * Device Password ID (%d)", id);
85         wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
86         wpabuf_put_be16(msg, 2);
87         wpabuf_put_be16(msg, id);
88         return 0;
89 }
90
91
92 int wps_build_config_error(struct wpabuf *msg, u16 err)
93 {
94         wpa_printf(MSG_DEBUG, "WPS:  * Configuration Error (%d)", err);
95         wpabuf_put_be16(msg, ATTR_CONFIG_ERROR);
96         wpabuf_put_be16(msg, 2);
97         wpabuf_put_be16(msg, err);
98         return 0;
99 }
100
101
102 int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
103 {
104         u8 hash[SHA256_MAC_LEN];
105         const u8 *addr[2];
106         size_t len[2];
107
108         if (wps->last_msg == NULL) {
109                 wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
110                            "building authenticator");
111                 return -1;
112         }
113
114         /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
115          * (M_curr* is M_curr without the Authenticator attribute)
116          */
117         addr[0] = wpabuf_head(wps->last_msg);
118         len[0] = wpabuf_len(wps->last_msg);
119         addr[1] = wpabuf_head(msg);
120         len[1] = wpabuf_len(msg);
121         hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
122
123         wpa_printf(MSG_DEBUG, "WPS:  * Authenticator");
124         wpabuf_put_be16(msg, ATTR_AUTHENTICATOR);
125         wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN);
126         wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN);
127
128         return 0;
129 }
130
131
132 int wps_build_version(struct wpabuf *msg)
133 {
134         wpa_printf(MSG_DEBUG, "WPS:  * Version");
135         wpabuf_put_be16(msg, ATTR_VERSION);
136         wpabuf_put_be16(msg, 1);
137         wpabuf_put_u8(msg, WPS_VERSION);
138         return 0;
139 }
140
141
142 int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type)
143 {
144         wpa_printf(MSG_DEBUG, "WPS:  * Message Type (%d)", msg_type);
145         wpabuf_put_be16(msg, ATTR_MSG_TYPE);
146         wpabuf_put_be16(msg, 1);
147         wpabuf_put_u8(msg, msg_type);
148         return 0;
149 }
150
151
152 int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg)
153 {
154         wpa_printf(MSG_DEBUG, "WPS:  * Enrollee Nonce");
155         wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
156         wpabuf_put_be16(msg, WPS_NONCE_LEN);
157         wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN);
158         return 0;
159 }
160
161
162 int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg)
163 {
164         wpa_printf(MSG_DEBUG, "WPS:  * Registrar Nonce");
165         wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
166         wpabuf_put_be16(msg, WPS_NONCE_LEN);
167         wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN);
168         return 0;
169 }
170
171
172 int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
173 {
174         wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type Flags");
175         wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
176         wpabuf_put_be16(msg, 2);
177         wpabuf_put_be16(msg, WPS_AUTH_TYPES);
178         return 0;
179 }
180
181
182 int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
183 {
184         wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type Flags");
185         wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
186         wpabuf_put_be16(msg, 2);
187         wpabuf_put_be16(msg, WPS_ENCR_TYPES);
188         return 0;
189 }
190
191
192 int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg)
193 {
194         wpa_printf(MSG_DEBUG, "WPS:  * Connection Type Flags");
195         wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS);
196         wpabuf_put_be16(msg, 1);
197         wpabuf_put_u8(msg, WPS_CONN_ESS);
198         return 0;
199 }
200
201
202 int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg)
203 {
204         wpa_printf(MSG_DEBUG, "WPS:  * Association State");
205         wpabuf_put_be16(msg, ATTR_ASSOC_STATE);
206         wpabuf_put_be16(msg, 2);
207         wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC);
208         return 0;
209 }
210
211
212 int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg)
213 {
214         u8 hash[SHA256_MAC_LEN];
215
216         wpa_printf(MSG_DEBUG, "WPS:  * Key Wrap Authenticator");
217         hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg),
218                     wpabuf_len(msg), hash);
219
220         wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH);
221         wpabuf_put_be16(msg, WPS_KWA_LEN);
222         wpabuf_put_data(msg, hash, WPS_KWA_LEN);
223         return 0;
224 }
225
226
227 int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
228                             struct wpabuf *plain)
229 {
230         size_t pad_len;
231         const size_t block_size = 16;
232         u8 *iv, *data;
233
234         wpa_printf(MSG_DEBUG, "WPS:  * Encrypted Settings");
235
236         /* PKCS#5 v2.0 pad */
237         pad_len = block_size - wpabuf_len(plain) % block_size;
238         os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len);
239
240         wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS);
241         wpabuf_put_be16(msg, block_size + wpabuf_len(plain));
242
243         iv = wpabuf_put(msg, block_size);
244         if (os_get_random(iv, block_size) < 0)
245                 return -1;
246
247         data = wpabuf_put(msg, 0);
248         wpabuf_put_buf(msg, plain);
249         if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain)))
250                 return -1;
251
252         return 0;
253 }