~ubuntu-branches/ubuntu/saucy/wpasupplicant/saucy

« back to all changes in this revision

Viewing changes to src/wps/wps_common.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-22 09:43:43 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122094343-qgsxaojvmswfri77
Tags: 0.7.3-0ubuntu1
* Get wpasupplicant 0.7.3 from Debian's SVN. Leaving 0.7.3-1 as unreleased
  for now.
* Build-Depend on debhelper 8, since the packaging from Debian uses compat 8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Wi-Fi Protected Setup - common functionality
3
 
 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
 
3
 * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License version 2 as
15
15
#include "includes.h"
16
16
 
17
17
#include "common.h"
18
 
#include "dh_groups.h"
19
 
#include "sha256.h"
20
 
#include "aes_wrap.h"
21
 
#include "crypto.h"
 
18
#include "crypto/aes_wrap.h"
 
19
#include "crypto/crypto.h"
 
20
#include "crypto/dh_group5.h"
 
21
#include "crypto/sha1.h"
 
22
#include "crypto/sha256.h"
22
23
#include "wps_i.h"
23
24
#include "wps_dev_attr.h"
24
25
 
80
81
                return -1;
81
82
        }
82
83
 
83
 
        dh_shared = dh_derive_shared(pubkey, wps->dh_privkey,
84
 
                                     dh_groups_get(WPS_DH_GROUP));
 
84
        dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey);
 
85
        dh5_free(wps->dh_ctx);
 
86
        wps->dh_ctx = NULL;
85
87
        dh_shared = wpabuf_zeropad(dh_shared, 192);
86
88
        if (dh_shared == NULL) {
87
89
                wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
303
305
 
304
306
        wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL);
305
307
}
 
308
 
 
309
 
 
310
#ifdef CONFIG_WPS_OOB
 
311
 
 
312
static struct wpabuf * wps_get_oob_cred(struct wps_context *wps)
 
313
{
 
314
        struct wps_data data;
 
315
        struct wpabuf *plain;
 
316
 
 
317
        plain = wpabuf_alloc(500);
 
318
        if (plain == NULL) {
 
319
                wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
 
320
                           "credential");
 
321
                return NULL;
 
322
        }
 
323
 
 
324
        os_memset(&data, 0, sizeof(data));
 
325
        data.wps = wps;
 
326
        data.auth_type = wps->auth_types;
 
327
        data.encr_type = wps->encr_types;
 
328
        if (wps_build_version(plain) || wps_build_cred(&data, plain)) {
 
329
                wpabuf_free(plain);
 
330
                return NULL;
 
331
        }
 
332
 
 
333
        return plain;
 
334
}
 
335
 
 
336
 
 
337
static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps)
 
338
{
 
339
        struct wpabuf *data;
 
340
 
 
341
        data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN);
 
342
        if (data == NULL) {
 
343
                wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
 
344
                           "device password attribute");
 
345
                return NULL;
 
346
        }
 
347
 
 
348
        wpabuf_free(wps->oob_conf.dev_password);
 
349
        wps->oob_conf.dev_password =
 
350
                wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
 
351
        if (wps->oob_conf.dev_password == NULL) {
 
352
                wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
 
353
                           "device password");
 
354
                wpabuf_free(data);
 
355
                return NULL;
 
356
        }
 
357
 
 
358
        if (wps_build_version(data) ||
 
359
            wps_build_oob_dev_password(data, wps)) {
 
360
                wpa_printf(MSG_ERROR, "WPS: Build OOB device password "
 
361
                           "attribute error");
 
362
                wpabuf_free(data);
 
363
                return NULL;
 
364
        }
 
365
 
 
366
        return data;
 
367
}
 
368
 
 
369
 
 
370
static int wps_parse_oob_dev_pwd(struct wps_context *wps,
 
371
                                 struct wpabuf *data)
 
372
{
 
373
        struct oob_conf_data *oob_conf = &wps->oob_conf;
 
374
        struct wps_parse_attr attr;
 
375
        const u8 *pos;
 
376
 
 
377
        if (wps_parse_msg(data, &attr) < 0 ||
 
378
            attr.oob_dev_password == NULL) {
 
379
                wpa_printf(MSG_ERROR, "WPS: OOB device password not found");
 
380
                return -1;
 
381
        }
 
382
 
 
383
        pos = attr.oob_dev_password;
 
384
 
 
385
        oob_conf->pubkey_hash =
 
386
                wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN);
 
387
        if (oob_conf->pubkey_hash == NULL) {
 
388
                wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
 
389
                           "public key hash");
 
390
                return -1;
 
391
        }
 
392
        pos += WPS_OOB_PUBKEY_HASH_LEN;
 
393
 
 
394
        wps->oob_dev_pw_id = WPA_GET_BE16(pos);
 
395
        pos += sizeof(wps->oob_dev_pw_id);
 
396
 
 
397
        oob_conf->dev_password =
 
398
                wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
 
399
        if (oob_conf->dev_password == NULL) {
 
400
                wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
 
401
                           "device password");
 
402
                return -1;
 
403
        }
 
404
        wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password,
 
405
                                   wpabuf_size(oob_conf->dev_password)),
 
406
                                   wpabuf_size(oob_conf->dev_password), pos,
 
407
                                   WPS_OOB_DEVICE_PASSWORD_LEN);
 
408
 
 
409
        return 0;
 
410
}
 
411
 
 
412
 
 
413
static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data)
 
414
{
 
415
        struct wpabuf msg;
 
416
        struct wps_parse_attr attr;
 
417
        size_t i;
 
418
 
 
419
        if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) {
 
420
                wpa_printf(MSG_ERROR, "WPS: OOB credential not found");
 
421
                return -1;
 
422
        }
 
423
 
 
424
        for (i = 0; i < attr.num_cred; i++) {
 
425
                struct wps_credential local_cred;
 
426
                struct wps_parse_attr cattr;
 
427
 
 
428
                os_memset(&local_cred, 0, sizeof(local_cred));
 
429
                wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]);
 
430
                if (wps_parse_msg(&msg, &cattr) < 0 ||
 
431
                    wps_process_cred(&cattr, &local_cred)) {
 
432
                        wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB "
 
433
                                   "credential");
 
434
                        return -1;
 
435
                }
 
436
                wps->cred_cb(wps->cb_ctx, &local_cred);
 
437
        }
 
438
 
 
439
        return 0;
 
440
}
 
441
 
 
442
 
 
443
int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
 
444
                    int registrar)
 
445
{
 
446
        struct wpabuf *data;
 
447
        int ret, write_f, oob_method = wps->oob_conf.oob_method;
 
448
        void *oob_priv;
 
449
 
 
450
        write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar;
 
451
 
 
452
        oob_priv = oob_dev->init_func(wps, oob_dev, registrar);
 
453
        if (oob_priv == NULL) {
 
454
                wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device");
 
455
                return -1;
 
456
        }
 
457
 
 
458
        if (write_f) {
 
459
                if (oob_method == OOB_METHOD_CRED)
 
460
                        data = wps_get_oob_cred(wps);
 
461
                else
 
462
                        data = wps_get_oob_dev_pwd(wps);
 
463
 
 
464
                ret = 0;
 
465
                if (data == NULL || oob_dev->write_func(oob_priv, data) < 0)
 
466
                        ret = -1;
 
467
        } else {
 
468
                data = oob_dev->read_func(oob_priv);
 
469
                if (data == NULL)
 
470
                        ret = -1;
 
471
                else {
 
472
                        if (oob_method == OOB_METHOD_CRED)
 
473
                                ret = wps_parse_oob_cred(wps, data);
 
474
                        else
 
475
                                ret = wps_parse_oob_dev_pwd(wps, data);
 
476
                }
 
477
        }
 
478
        wpabuf_free(data);
 
479
        oob_dev->deinit_func(oob_priv);
 
480
 
 
481
        if (ret < 0) {
 
482
                wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data");
 
483
                return -1;
 
484
        }
 
485
 
 
486
        return 0;
 
487
}
 
488
 
 
489
 
 
490
struct oob_device_data * wps_get_oob_device(char *device_type)
 
491
{
 
492
#ifdef CONFIG_WPS_UFD
 
493
        if (os_strstr(device_type, "ufd") != NULL)
 
494
                return &oob_ufd_device_data;
 
495
#endif /* CONFIG_WPS_UFD */
 
496
#ifdef CONFIG_WPS_NFC
 
497
        if (os_strstr(device_type, "nfc") != NULL)
 
498
                return &oob_nfc_device_data;
 
499
#endif /* CONFIG_WPS_NFC */
 
500
 
 
501
        return NULL;
 
502
}
 
503
 
 
504
 
 
505
#ifdef CONFIG_WPS_NFC
 
506
struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name)
 
507
{
 
508
        if (device_name == NULL)
 
509
                return NULL;
 
510
#ifdef CONFIG_WPS_NFC_PN531
 
511
        if (os_strstr(device_name, "pn531") != NULL)
 
512
                return &oob_nfc_pn531_device_data;
 
513
#endif /* CONFIG_WPS_NFC_PN531 */
 
514
 
 
515
        return NULL;
 
516
}
 
517
#endif /* CONFIG_WPS_NFC */
 
518
 
 
519
 
 
520
int wps_get_oob_method(char *method)
 
521
{
 
522
        if (os_strstr(method, "pin-e") != NULL)
 
523
                return OOB_METHOD_DEV_PWD_E;
 
524
        if (os_strstr(method, "pin-r") != NULL)
 
525
                return OOB_METHOD_DEV_PWD_R;
 
526
        if (os_strstr(method, "cred") != NULL)
 
527
                return OOB_METHOD_CRED;
 
528
        return OOB_METHOD_UNKNOWN;
 
529
}
 
530
 
 
531
#endif /* CONFIG_WPS_OOB */
 
532
 
 
533
 
 
534
int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN])
 
535
{
 
536
        const char *pos;
 
537
 
 
538
        /* <categ>-<OUI>-<subcateg> */
 
539
        WPA_PUT_BE16(dev_type, atoi(str));
 
540
        pos = os_strchr(str, '-');
 
541
        if (pos == NULL)
 
542
                return -1;
 
543
        pos++;
 
544
        if (hexstr2bin(pos, &dev_type[2], 4))
 
545
                return -1;
 
546
        pos = os_strchr(pos, '-');
 
547
        if (pos == NULL)
 
548
                return -1;
 
549
        pos++;
 
550
        WPA_PUT_BE16(&dev_type[6], atoi(pos));
 
551
 
 
552
 
 
553
        return 0;
 
554
}
 
555
 
 
556
 
 
557
char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
 
558
                            size_t buf_len)
 
559
{
 
560
        int ret;
 
561
 
 
562
        ret = os_snprintf(buf, buf_len, "%u-%08X-%u",
 
563
                          WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]),
 
564
                          WPA_GET_BE16(&dev_type[6]));
 
565
        if (ret < 0 || (unsigned int) ret >= buf_len)
 
566
                return NULL;
 
567
 
 
568
        return buf;
 
569
}
 
570
 
 
571
 
 
572
void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid)
 
573
{
 
574
        const u8 *addr[2];
 
575
        size_t len[2];
 
576
        u8 hash[SHA1_MAC_LEN];
 
577
        u8 nsid[16] = {
 
578
                0x52, 0x64, 0x80, 0xf8,
 
579
                0xc9, 0x9b,
 
580
                0x4b, 0xe5,
 
581
                0xa6, 0x55,
 
582
                0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84
 
583
        };
 
584
 
 
585
        addr[0] = nsid;
 
586
        len[0] = sizeof(nsid);
 
587
        addr[1] = mac_addr;
 
588
        len[1] = 6;
 
589
        sha1_vector(2, addr, len, hash);
 
590
        os_memcpy(uuid, hash, 16);
 
591
 
 
592
        /* Version: 5 = named-based version using SHA-1 */
 
593
        uuid[6] = (5 << 4) | (uuid[6] & 0x0f);
 
594
 
 
595
        /* Variant specified in RFC 4122 */
 
596
        uuid[8] = 0x80 | (uuid[8] & 0x3f);
 
597
}
 
598
 
 
599
 
 
600
u16 wps_config_methods_str2bin(const char *str)
 
601
{
 
602
        u16 methods = 0;
 
603
 
 
604
        if (str == NULL) {
 
605
                /* Default to enabling methods based on build configuration */
 
606
                methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
 
607
#ifdef CONFIG_WPS_UFD
 
608
                methods |= WPS_CONFIG_USBA;
 
609
#endif /* CONFIG_WPS_UFD */
 
610
#ifdef CONFIG_WPS_NFC
 
611
                methods |= WPS_CONFIG_NFC_INTERFACE;
 
612
#endif /* CONFIG_WPS_NFC */
 
613
        } else {
 
614
                if (os_strstr(str, "usba"))
 
615
                        methods |= WPS_CONFIG_USBA;
 
616
                if (os_strstr(str, "ethernet"))
 
617
                        methods |= WPS_CONFIG_ETHERNET;
 
618
                if (os_strstr(str, "label"))
 
619
                        methods |= WPS_CONFIG_LABEL;
 
620
                if (os_strstr(str, "display"))
 
621
                        methods |= WPS_CONFIG_DISPLAY;
 
622
                if (os_strstr(str, "ext_nfc_token"))
 
623
                        methods |= WPS_CONFIG_EXT_NFC_TOKEN;
 
624
                if (os_strstr(str, "int_nfc_token"))
 
625
                        methods |= WPS_CONFIG_INT_NFC_TOKEN;
 
626
                if (os_strstr(str, "nfc_interface"))
 
627
                        methods |= WPS_CONFIG_NFC_INTERFACE;
 
628
                if (os_strstr(str, "push_button"))
 
629
                        methods |= WPS_CONFIG_PUSHBUTTON;
 
630
                if (os_strstr(str, "keypad"))
 
631
                        methods |= WPS_CONFIG_KEYPAD;
 
632
        }
 
633
 
 
634
        return methods;
 
635
}