~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to src/tls/asn1.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * ASN.1 DER parsing
3
 
 * Copyright (c) 2006, 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
 
 
19
 
#ifdef CONFIG_INTERNAL_X509
20
 
 
21
 
#include "asn1.h"
22
 
 
23
 
int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
24
 
{
25
 
        const u8 *pos, *end;
26
 
        u8 tmp;
27
 
 
28
 
        os_memset(hdr, 0, sizeof(*hdr));
29
 
        pos = buf;
30
 
        end = buf + len;
31
 
 
32
 
        hdr->identifier = *pos++;
33
 
        hdr->class = hdr->identifier >> 6;
34
 
        hdr->constructed = !!(hdr->identifier & (1 << 5));
35
 
 
36
 
        if ((hdr->identifier & 0x1f) == 0x1f) {
37
 
                hdr->tag = 0;
38
 
                do {
39
 
                        if (pos >= end) {
40
 
                                wpa_printf(MSG_DEBUG, "ASN.1: Identifier "
41
 
                                           "underflow");
42
 
                                return -1;
43
 
                        }
44
 
                        tmp = *pos++;
45
 
                        wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: "
46
 
                                   "0x%02x", tmp);
47
 
                        hdr->tag = (hdr->tag << 7) | (tmp & 0x7f);
48
 
                } while (tmp & 0x80);
49
 
        } else
50
 
                hdr->tag = hdr->identifier & 0x1f;
51
 
 
52
 
        tmp = *pos++;
53
 
        if (tmp & 0x80) {
54
 
                if (tmp == 0xff) {
55
 
                        wpa_printf(MSG_DEBUG, "ASN.1: Reserved length "
56
 
                                   "value 0xff used");
57
 
                        return -1;
58
 
                }
59
 
                tmp &= 0x7f; /* number of subsequent octets */
60
 
                hdr->length = 0;
61
 
                while (tmp--) {
62
 
                        if (pos >= end) {
63
 
                                wpa_printf(MSG_DEBUG, "ASN.1: Length "
64
 
                                           "underflow");
65
 
                                return -1;
66
 
                        }
67
 
                        hdr->length = (hdr->length << 8) | *pos++;
68
 
                }
69
 
        } else {
70
 
                /* Short form - length 0..127 in one octet */
71
 
                hdr->length = tmp;
72
 
        }
73
 
 
74
 
        if (pos + hdr->length > end) {
75
 
                wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow");
76
 
                return -1;
77
 
        }
78
 
 
79
 
        hdr->payload = pos;
80
 
        return 0;
81
 
}
82
 
 
83
 
 
84
 
int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
85
 
                 const u8 **next)
86
 
{
87
 
        struct asn1_hdr hdr;
88
 
        const u8 *pos, *end;
89
 
        unsigned long val;
90
 
        u8 tmp;
91
 
 
92
 
        os_memset(oid, 0, sizeof(*oid));
93
 
 
94
 
        if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
95
 
                return -1;
96
 
 
97
 
        if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) {
98
 
                wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d "
99
 
                           "tag 0x%x", hdr.class, hdr.tag);
100
 
                return -1;
101
 
        }
102
 
 
103
 
        pos = hdr.payload;
104
 
        end = hdr.payload + hdr.length;
105
 
        *next = end;
106
 
 
107
 
        while (pos < end) {
108
 
                val = 0;
109
 
 
110
 
                do {
111
 
                        if (pos >= end)
112
 
                                return -1;
113
 
                        tmp = *pos++;
114
 
                        val = (val << 7) | (tmp & 0x7f);
115
 
                } while (tmp & 0x80);
116
 
 
117
 
                if (oid->len >= ASN1_MAX_OID_LEN) {
118
 
                        wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value");
119
 
                        return -1;
120
 
                }
121
 
                if (oid->len == 0) {
122
 
                        /*
123
 
                         * The first octet encodes the first two object
124
 
                         * identifier components in (X*40) + Y formula.
125
 
                         * X = 0..2.
126
 
                         */
127
 
                        oid->oid[0] = val / 40;
128
 
                        if (oid->oid[0] > 2)
129
 
                                oid->oid[0] = 2;
130
 
                        oid->oid[1] = val - oid->oid[0] * 40;
131
 
                        oid->len = 2;
132
 
                } else
133
 
                        oid->oid[oid->len++] = val;
134
 
        }
135
 
 
136
 
        return 0;
137
 
}
138
 
 
139
 
 
140
 
void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len)
141
 
{
142
 
        char *pos = buf;
143
 
        size_t i;
144
 
        int ret;
145
 
 
146
 
        if (len == 0)
147
 
                return;
148
 
 
149
 
        buf[0] = '\0';
150
 
 
151
 
        for (i = 0; i < oid->len; i++) {
152
 
                ret = os_snprintf(pos, buf + len - pos,
153
 
                                  "%s%lu",
154
 
                                  i == 0 ? "" : ".", oid->oid[i]);
155
 
                if (ret < 0 || ret >= buf + len - pos)
156
 
                        break;
157
 
                pos += ret;
158
 
        }
159
 
        buf[len - 1] = '\0';
160
 
}
161
 
 
162
 
 
163
 
static u8 rotate_bits(u8 octet)
164
 
{
165
 
        int i;
166
 
        u8 res;
167
 
 
168
 
        res = 0;
169
 
        for (i = 0; i < 8; i++) {
170
 
                res <<= 1;
171
 
                if (octet & 1)
172
 
                        res |= 1;
173
 
                octet >>= 1;
174
 
        }
175
 
 
176
 
        return res;
177
 
}
178
 
 
179
 
 
180
 
unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len)
181
 
{
182
 
        unsigned long val = 0;
183
 
        const u8 *pos = buf;
184
 
 
185
 
        /* BER requires that unused bits are zero, so we can ignore the number
186
 
         * of unused bits */
187
 
        pos++;
188
 
 
189
 
        if (len >= 2)
190
 
                val |= rotate_bits(*pos++);
191
 
        if (len >= 3)
192
 
                val |= ((unsigned long) rotate_bits(*pos++)) << 8;
193
 
        if (len >= 4)
194
 
                val |= ((unsigned long) rotate_bits(*pos++)) << 16;
195
 
        if (len >= 5)
196
 
                val |= ((unsigned long) rotate_bits(*pos++)) << 24;
197
 
        if (len >= 6)
198
 
                wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored "
199
 
                           "(BIT STRING length %lu)",
200
 
                           __func__, (unsigned long) len);
201
 
 
202
 
        return val;
203
 
}
204
 
 
205
 
#endif /* CONFIG_INTERNAL_X509 */