diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-14 16:39:34 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-14 16:39:34 -0400 |
| commit | d25282d1c9b9bc4cda7f9d3c0205108e99aa7a9d (patch) | |
| tree | f414482d768b015a609924293b779b4ad0b8f764 /lib | |
| parent | b6eea87fc6850d3531a64a27d2323a4498cd4e43 (diff) | |
| parent | dbadc17683e6c673a69b236c0f041b931cc55c42 (diff) | |
Merge branch 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull module signing support from Rusty Russell:
"module signing is the highlight, but it's an all-over David Howells frenzy..."
Hmm "Magrathea: Glacier signing key". Somebody has been reading too much HHGTTG.
* 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: (37 commits)
X.509: Fix indefinite length element skip error handling
X.509: Convert some printk calls to pr_devel
asymmetric keys: fix printk format warning
MODSIGN: Fix 32-bit overflow in X.509 certificate validity date checking
MODSIGN: Make mrproper should remove generated files.
MODSIGN: Use utf8 strings in signer's name in autogenerated X.509 certs
MODSIGN: Use the same digest for the autogen key sig as for the module sig
MODSIGN: Sign modules during the build process
MODSIGN: Provide a script for generating a key ID from an X.509 cert
MODSIGN: Implement module signature checking
MODSIGN: Provide module signing public keys to the kernel
MODSIGN: Automatically generate module signing keys if missing
MODSIGN: Provide Kconfig options
MODSIGN: Provide gitignore and make clean rules for extra files
MODSIGN: Add FIPS policy
module: signature checking hook
X.509: Add a crypto key parser for binary (DER) X.509 certificates
MPILIB: Provide a function to read raw data into an MPI
X.509: Add an ASN.1 decoder
X.509: Add simple ASN.1 grammar compiler
...
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/.gitignore | 2 | ||||
| -rw-r--r-- | lib/Kconfig | 5 | ||||
| -rw-r--r-- | lib/Makefile | 18 | ||||
| -rw-r--r-- | lib/asn1_decoder.c | 487 | ||||
| -rwxr-xr-x | lib/build_OID_registry | 209 | ||||
| -rw-r--r-- | lib/mpi/Makefile | 1 | ||||
| -rw-r--r-- | lib/mpi/longlong.h | 138 | ||||
| -rw-r--r-- | lib/mpi/mpi-bit.c | 2 | ||||
| -rw-r--r-- | lib/mpi/mpi-cmp.c | 70 | ||||
| -rw-r--r-- | lib/mpi/mpi-pow.c | 4 | ||||
| -rw-r--r-- | lib/mpi/mpicoder.c | 55 | ||||
| -rw-r--r-- | lib/oid_registry.c | 170 |
12 files changed, 1021 insertions, 140 deletions
diff --git a/lib/.gitignore b/lib/.gitignore index 3bef1ea94c99..09aae85418ab 100644 --- a/lib/.gitignore +++ b/lib/.gitignore | |||
| @@ -3,4 +3,4 @@ | |||
| 3 | # | 3 | # |
| 4 | gen_crc32table | 4 | gen_crc32table |
| 5 | crc32table.h | 5 | crc32table.h |
| 6 | 6 | oid_registry_data.c | |
diff --git a/lib/Kconfig b/lib/Kconfig index bb94c1ba616a..4b31a46fb307 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
| @@ -396,4 +396,9 @@ config SIGNATURE | |||
| 396 | config LIBFDT | 396 | config LIBFDT |
| 397 | bool | 397 | bool |
| 398 | 398 | ||
| 399 | config OID_REGISTRY | ||
| 400 | tristate | ||
| 401 | help | ||
| 402 | Enable fast lookup object identifier registry. | ||
| 403 | |||
| 399 | endmenu | 404 | endmenu |
diff --git a/lib/Makefile b/lib/Makefile index 3128e357e286..821a16229111 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -145,6 +145,8 @@ obj-$(CONFIG_INTERVAL_TREE_TEST) += interval_tree_test.o | |||
| 145 | 145 | ||
| 146 | interval_tree_test-objs := interval_tree_test_main.o interval_tree.o | 146 | interval_tree_test-objs := interval_tree_test_main.o interval_tree.o |
| 147 | 147 | ||
| 148 | obj-$(CONFIG_ASN1) += asn1_decoder.o | ||
| 149 | |||
| 148 | hostprogs-y := gen_crc32table | 150 | hostprogs-y := gen_crc32table |
| 149 | clean-files := crc32table.h | 151 | clean-files := crc32table.h |
| 150 | 152 | ||
| @@ -155,3 +157,19 @@ quiet_cmd_crc32 = GEN $@ | |||
| 155 | 157 | ||
| 156 | $(obj)/crc32table.h: $(obj)/gen_crc32table | 158 | $(obj)/crc32table.h: $(obj)/gen_crc32table |
| 157 | $(call cmd,crc32) | 159 | $(call cmd,crc32) |
| 160 | |||
| 161 | # | ||
| 162 | # Build a fast OID lookip registry from include/linux/oid_registry.h | ||
| 163 | # | ||
| 164 | obj-$(CONFIG_OID_REGISTRY) += oid_registry.o | ||
| 165 | |||
| 166 | $(obj)/oid_registry.c: $(obj)/oid_registry_data.c | ||
| 167 | |||
| 168 | $(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \ | ||
| 169 | $(src)/build_OID_registry | ||
| 170 | $(call cmd,build_OID_registry) | ||
| 171 | |||
| 172 | quiet_cmd_build_OID_registry = GEN $@ | ||
| 173 | cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ | ||
| 174 | |||
| 175 | clean-files += oid_registry_data.c | ||
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c new file mode 100644 index 000000000000..de2c8b5a715b --- /dev/null +++ b/lib/asn1_decoder.c | |||
| @@ -0,0 +1,487 @@ | |||
| 1 | /* Decoder for ASN.1 BER/DER/CER encoded bytestream | ||
| 2 | * | ||
| 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/export.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/errno.h> | ||
| 15 | #include <linux/asn1_decoder.h> | ||
| 16 | #include <linux/asn1_ber_bytecode.h> | ||
| 17 | |||
| 18 | static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { | ||
| 19 | /* OPC TAG JMP ACT */ | ||
| 20 | [ASN1_OP_MATCH] = 1 + 1, | ||
| 21 | [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, | ||
| 22 | [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, | ||
| 23 | [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, | ||
| 24 | [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, | ||
| 25 | [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, | ||
| 26 | [ASN1_OP_MATCH_ANY] = 1, | ||
| 27 | [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, | ||
| 28 | [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, | ||
| 29 | [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, | ||
| 30 | [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, | ||
| 31 | [ASN1_OP_COND_MATCH_ANY] = 1, | ||
| 32 | [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, | ||
| 33 | [ASN1_OP_COND_FAIL] = 1, | ||
| 34 | [ASN1_OP_COMPLETE] = 1, | ||
| 35 | [ASN1_OP_ACT] = 1 + 1, | ||
| 36 | [ASN1_OP_RETURN] = 1, | ||
| 37 | [ASN1_OP_END_SEQ] = 1, | ||
| 38 | [ASN1_OP_END_SEQ_OF] = 1 + 1, | ||
| 39 | [ASN1_OP_END_SET] = 1, | ||
| 40 | [ASN1_OP_END_SET_OF] = 1 + 1, | ||
| 41 | [ASN1_OP_END_SEQ_ACT] = 1 + 1, | ||
| 42 | [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, | ||
| 43 | [ASN1_OP_END_SET_ACT] = 1 + 1, | ||
| 44 | [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Find the length of an indefinite length object | ||
| 49 | * @data: The data buffer | ||
| 50 | * @datalen: The end of the innermost containing element in the buffer | ||
| 51 | * @_dp: The data parse cursor (updated before returning) | ||
| 52 | * @_len: Where to return the size of the element. | ||
| 53 | * @_errmsg: Where to return a pointer to an error message on error | ||
| 54 | */ | ||
| 55 | static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, | ||
| 56 | size_t *_dp, size_t *_len, | ||
| 57 | const char **_errmsg) | ||
| 58 | { | ||
| 59 | unsigned char tag, tmp; | ||
| 60 | size_t dp = *_dp, len, n; | ||
| 61 | int indef_level = 1; | ||
| 62 | |||
| 63 | next_tag: | ||
| 64 | if (unlikely(datalen - dp < 2)) { | ||
| 65 | if (datalen == dp) | ||
| 66 | goto missing_eoc; | ||
| 67 | goto data_overrun_error; | ||
| 68 | } | ||
| 69 | |||
| 70 | /* Extract a tag from the data */ | ||
| 71 | tag = data[dp++]; | ||
| 72 | if (tag == 0) { | ||
| 73 | /* It appears to be an EOC. */ | ||
| 74 | if (data[dp++] != 0) | ||
| 75 | goto invalid_eoc; | ||
| 76 | if (--indef_level <= 0) { | ||
| 77 | *_len = dp - *_dp; | ||
| 78 | *_dp = dp; | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | goto next_tag; | ||
| 82 | } | ||
| 83 | |||
| 84 | if (unlikely((tag & 0x1f) == 0x1f)) { | ||
| 85 | do { | ||
| 86 | if (unlikely(datalen - dp < 2)) | ||
| 87 | goto data_overrun_error; | ||
| 88 | tmp = data[dp++]; | ||
| 89 | } while (tmp & 0x80); | ||
| 90 | } | ||
| 91 | |||
| 92 | /* Extract the length */ | ||
| 93 | len = data[dp++]; | ||
| 94 | if (len < 0x7f) { | ||
| 95 | dp += len; | ||
| 96 | goto next_tag; | ||
| 97 | } | ||
| 98 | |||
| 99 | if (unlikely(len == 0x80)) { | ||
| 100 | /* Indefinite length */ | ||
| 101 | if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) | ||
| 102 | goto indefinite_len_primitive; | ||
| 103 | indef_level++; | ||
| 104 | goto next_tag; | ||
| 105 | } | ||
| 106 | |||
| 107 | n = len - 0x80; | ||
| 108 | if (unlikely(n > sizeof(size_t) - 1)) | ||
| 109 | goto length_too_long; | ||
| 110 | if (unlikely(n > datalen - dp)) | ||
| 111 | goto data_overrun_error; | ||
| 112 | for (len = 0; n > 0; n--) { | ||
| 113 | len <<= 8; | ||
| 114 | len |= data[dp++]; | ||
| 115 | } | ||
| 116 | dp += len; | ||
| 117 | goto next_tag; | ||
| 118 | |||
| 119 | length_too_long: | ||
| 120 | *_errmsg = "Unsupported length"; | ||
| 121 | goto error; | ||
| 122 | indefinite_len_primitive: | ||
| 123 | *_errmsg = "Indefinite len primitive not permitted"; | ||
| 124 | goto error; | ||
| 125 | invalid_eoc: | ||
| 126 | *_errmsg = "Invalid length EOC"; | ||
| 127 | goto error; | ||
| 128 | data_overrun_error: | ||
| 129 | *_errmsg = "Data overrun error"; | ||
| 130 | goto error; | ||
| 131 | missing_eoc: | ||
| 132 | *_errmsg = "Missing EOC in indefinite len cons"; | ||
| 133 | error: | ||
| 134 | *_dp = dp; | ||
| 135 | return -1; | ||
| 136 | } | ||
| 137 | |||
| 138 | /** | ||
| 139 | * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern | ||
| 140 | * @decoder: The decoder definition (produced by asn1_compiler) | ||
| 141 | * @context: The caller's context (to be passed to the action functions) | ||
| 142 | * @data: The encoded data | ||
| 143 | * @datasize: The size of the encoded data | ||
| 144 | * | ||
| 145 | * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern | ||
| 146 | * produced by asn1_compiler. Action functions are called on marked tags to | ||
| 147 | * allow the caller to retrieve significant data. | ||
| 148 | * | ||
| 149 | * LIMITATIONS: | ||
| 150 | * | ||
| 151 | * To keep down the amount of stack used by this function, the following limits | ||
| 152 | * have been imposed: | ||
| 153 | * | ||
| 154 | * (1) This won't handle datalen > 65535 without increasing the size of the | ||
| 155 | * cons stack elements and length_too_long checking. | ||
| 156 | * | ||
| 157 | * (2) The stack of constructed types is 10 deep. If the depth of non-leaf | ||
| 158 | * constructed types exceeds this, the decode will fail. | ||
| 159 | * | ||
| 160 | * (3) The SET type (not the SET OF type) isn't really supported as tracking | ||
| 161 | * what members of the set have been seen is a pain. | ||
| 162 | */ | ||
| 163 | int asn1_ber_decoder(const struct asn1_decoder *decoder, | ||
| 164 | void *context, | ||
| 165 | const unsigned char *data, | ||
| 166 | size_t datalen) | ||
| 167 | { | ||
| 168 | const unsigned char *machine = decoder->machine; | ||
| 169 | const asn1_action_t *actions = decoder->actions; | ||
| 170 | size_t machlen = decoder->machlen; | ||
| 171 | enum asn1_opcode op; | ||
| 172 | unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; | ||
| 173 | const char *errmsg; | ||
| 174 | size_t pc = 0, dp = 0, tdp = 0, len = 0; | ||
| 175 | int ret; | ||
| 176 | |||
| 177 | unsigned char flags = 0; | ||
| 178 | #define FLAG_INDEFINITE_LENGTH 0x01 | ||
| 179 | #define FLAG_MATCHED 0x02 | ||
| 180 | #define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag | ||
| 181 | * - ie. whether or not we are going to parse | ||
| 182 | * a compound type. | ||
| 183 | */ | ||
| 184 | |||
| 185 | #define NR_CONS_STACK 10 | ||
| 186 | unsigned short cons_dp_stack[NR_CONS_STACK]; | ||
| 187 | unsigned short cons_datalen_stack[NR_CONS_STACK]; | ||
| 188 | unsigned char cons_hdrlen_stack[NR_CONS_STACK]; | ||
| 189 | #define NR_JUMP_STACK 10 | ||
| 190 | unsigned char jump_stack[NR_JUMP_STACK]; | ||
| 191 | |||
| 192 | if (datalen > 65535) | ||
| 193 | return -EMSGSIZE; | ||
| 194 | |||
| 195 | next_op: | ||
| 196 | pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", | ||
| 197 | pc, machlen, dp, datalen, csp, jsp); | ||
| 198 | if (unlikely(pc >= machlen)) | ||
| 199 | goto machine_overrun_error; | ||
| 200 | op = machine[pc]; | ||
| 201 | if (unlikely(pc + asn1_op_lengths[op] > machlen)) | ||
| 202 | goto machine_overrun_error; | ||
| 203 | |||
| 204 | /* If this command is meant to match a tag, then do that before | ||
| 205 | * evaluating the command. | ||
| 206 | */ | ||
| 207 | if (op <= ASN1_OP__MATCHES_TAG) { | ||
| 208 | unsigned char tmp; | ||
| 209 | |||
| 210 | /* Skip conditional matches if possible */ | ||
| 211 | if ((op & ASN1_OP_MATCH__COND && | ||
| 212 | flags & FLAG_MATCHED) || | ||
| 213 | dp == datalen) { | ||
| 214 | pc += asn1_op_lengths[op]; | ||
| 215 | goto next_op; | ||
| 216 | } | ||
| 217 | |||
| 218 | flags = 0; | ||
| 219 | hdr = 2; | ||
| 220 | |||
| 221 | /* Extract a tag from the data */ | ||
| 222 | if (unlikely(dp >= datalen - 1)) | ||
| 223 | goto data_overrun_error; | ||
| 224 | tag = data[dp++]; | ||
| 225 | if (unlikely((tag & 0x1f) == 0x1f)) | ||
| 226 | goto long_tag_not_supported; | ||
| 227 | |||
| 228 | if (op & ASN1_OP_MATCH__ANY) { | ||
| 229 | pr_debug("- any %02x\n", tag); | ||
| 230 | } else { | ||
| 231 | /* Extract the tag from the machine | ||
| 232 | * - Either CONS or PRIM are permitted in the data if | ||
| 233 | * CONS is not set in the op stream, otherwise CONS | ||
| 234 | * is mandatory. | ||
| 235 | */ | ||
| 236 | optag = machine[pc + 1]; | ||
| 237 | flags |= optag & FLAG_CONS; | ||
| 238 | |||
| 239 | /* Determine whether the tag matched */ | ||
| 240 | tmp = optag ^ tag; | ||
| 241 | tmp &= ~(optag & ASN1_CONS_BIT); | ||
| 242 | pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); | ||
| 243 | if (tmp != 0) { | ||
| 244 | /* All odd-numbered tags are MATCH_OR_SKIP. */ | ||
| 245 | if (op & ASN1_OP_MATCH__SKIP) { | ||
| 246 | pc += asn1_op_lengths[op]; | ||
| 247 | dp--; | ||
| 248 | goto next_op; | ||
| 249 | } | ||
| 250 | goto tag_mismatch; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | flags |= FLAG_MATCHED; | ||
| 254 | |||
| 255 | len = data[dp++]; | ||
| 256 | if (len > 0x7f) { | ||
| 257 | if (unlikely(len == 0x80)) { | ||
| 258 | /* Indefinite length */ | ||
| 259 | if (unlikely(!(tag & ASN1_CONS_BIT))) | ||
| 260 | goto indefinite_len_primitive; | ||
| 261 | flags |= FLAG_INDEFINITE_LENGTH; | ||
| 262 | if (unlikely(2 > datalen - dp)) | ||
| 263 | goto data_overrun_error; | ||
| 264 | } else { | ||
| 265 | int n = len - 0x80; | ||
| 266 | if (unlikely(n > 2)) | ||
| 267 | goto length_too_long; | ||
| 268 | if (unlikely(dp >= datalen - n)) | ||
| 269 | goto data_overrun_error; | ||
| 270 | hdr += n; | ||
| 271 | for (len = 0; n > 0; n--) { | ||
| 272 | len <<= 8; | ||
| 273 | len |= data[dp++]; | ||
| 274 | } | ||
| 275 | if (unlikely(len > datalen - dp)) | ||
| 276 | goto data_overrun_error; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | if (flags & FLAG_CONS) { | ||
| 281 | /* For expected compound forms, we stack the positions | ||
| 282 | * of the start and end of the data. | ||
| 283 | */ | ||
| 284 | if (unlikely(csp >= NR_CONS_STACK)) | ||
| 285 | goto cons_stack_overflow; | ||
| 286 | cons_dp_stack[csp] = dp; | ||
| 287 | cons_hdrlen_stack[csp] = hdr; | ||
| 288 | if (!(flags & FLAG_INDEFINITE_LENGTH)) { | ||
| 289 | cons_datalen_stack[csp] = datalen; | ||
| 290 | datalen = dp + len; | ||
| 291 | } else { | ||
| 292 | cons_datalen_stack[csp] = 0; | ||
| 293 | } | ||
| 294 | csp++; | ||
| 295 | } | ||
| 296 | |||
| 297 | pr_debug("- TAG: %02x %zu%s\n", | ||
| 298 | tag, len, flags & FLAG_CONS ? " CONS" : ""); | ||
| 299 | tdp = dp; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* Decide how to handle the operation */ | ||
| 303 | switch (op) { | ||
| 304 | case ASN1_OP_MATCH_ANY_ACT: | ||
| 305 | case ASN1_OP_COND_MATCH_ANY_ACT: | ||
| 306 | ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); | ||
| 307 | if (ret < 0) | ||
| 308 | return ret; | ||
| 309 | goto skip_data; | ||
| 310 | |||
| 311 | case ASN1_OP_MATCH_ACT: | ||
| 312 | case ASN1_OP_MATCH_ACT_OR_SKIP: | ||
| 313 | case ASN1_OP_COND_MATCH_ACT_OR_SKIP: | ||
| 314 | ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); | ||
| 315 | if (ret < 0) | ||
| 316 | return ret; | ||
| 317 | goto skip_data; | ||
| 318 | |||
| 319 | case ASN1_OP_MATCH: | ||
| 320 | case ASN1_OP_MATCH_OR_SKIP: | ||
| 321 | case ASN1_OP_MATCH_ANY: | ||
| 322 | case ASN1_OP_COND_MATCH_OR_SKIP: | ||
| 323 | case ASN1_OP_COND_MATCH_ANY: | ||
| 324 | skip_data: | ||
| 325 | if (!(flags & FLAG_CONS)) { | ||
| 326 | if (flags & FLAG_INDEFINITE_LENGTH) { | ||
| 327 | ret = asn1_find_indefinite_length( | ||
| 328 | data, datalen, &dp, &len, &errmsg); | ||
| 329 | if (ret < 0) | ||
| 330 | goto error; | ||
| 331 | } else { | ||
| 332 | dp += len; | ||
| 333 | } | ||
| 334 | pr_debug("- LEAF: %zu\n", len); | ||
| 335 | } | ||
| 336 | pc += asn1_op_lengths[op]; | ||
| 337 | goto next_op; | ||
| 338 | |||
| 339 | case ASN1_OP_MATCH_JUMP: | ||
| 340 | case ASN1_OP_MATCH_JUMP_OR_SKIP: | ||
| 341 | case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: | ||
| 342 | pr_debug("- MATCH_JUMP\n"); | ||
| 343 | if (unlikely(jsp == NR_JUMP_STACK)) | ||
| 344 | goto jump_stack_overflow; | ||
| 345 | jump_stack[jsp++] = pc + asn1_op_lengths[op]; | ||
| 346 | pc = machine[pc + 2]; | ||
| 347 | goto next_op; | ||
| 348 | |||
| 349 | case ASN1_OP_COND_FAIL: | ||
| 350 | if (unlikely(!(flags & FLAG_MATCHED))) | ||
| 351 | goto tag_mismatch; | ||
| 352 | pc += asn1_op_lengths[op]; | ||
| 353 | goto next_op; | ||
| 354 | |||
| 355 | case ASN1_OP_COMPLETE: | ||
| 356 | if (unlikely(jsp != 0 || csp != 0)) { | ||
| 357 | pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", | ||
| 358 | jsp, csp); | ||
| 359 | return -EBADMSG; | ||
| 360 | } | ||
| 361 | return 0; | ||
| 362 | |||
| 363 | case ASN1_OP_END_SET: | ||
| 364 | case ASN1_OP_END_SET_ACT: | ||
| 365 | if (unlikely(!(flags & FLAG_MATCHED))) | ||
| 366 | goto tag_mismatch; | ||
| 367 | case ASN1_OP_END_SEQ: | ||
| 368 | case ASN1_OP_END_SET_OF: | ||
| 369 | case ASN1_OP_END_SEQ_OF: | ||
| 370 | case ASN1_OP_END_SEQ_ACT: | ||
| 371 | case ASN1_OP_END_SET_OF_ACT: | ||
| 372 | case ASN1_OP_END_SEQ_OF_ACT: | ||
| 373 | if (unlikely(csp <= 0)) | ||
| 374 | goto cons_stack_underflow; | ||
| 375 | csp--; | ||
| 376 | tdp = cons_dp_stack[csp]; | ||
| 377 | hdr = cons_hdrlen_stack[csp]; | ||
| 378 | len = datalen; | ||
| 379 | datalen = cons_datalen_stack[csp]; | ||
| 380 | pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", | ||
| 381 | tdp, dp, len, datalen); | ||
| 382 | if (datalen == 0) { | ||
| 383 | /* Indefinite length - check for the EOC. */ | ||
| 384 | datalen = len; | ||
| 385 | if (unlikely(datalen - dp < 2)) | ||
| 386 | goto data_overrun_error; | ||
| 387 | if (data[dp++] != 0) { | ||
| 388 | if (op & ASN1_OP_END__OF) { | ||
| 389 | dp--; | ||
| 390 | csp++; | ||
| 391 | pc = machine[pc + 1]; | ||
| 392 | pr_debug("- continue\n"); | ||
| 393 | goto next_op; | ||
| 394 | } | ||
| 395 | goto missing_eoc; | ||
| 396 | } | ||
| 397 | if (data[dp++] != 0) | ||
| 398 | goto invalid_eoc; | ||
| 399 | len = dp - tdp - 2; | ||
| 400 | } else { | ||
| 401 | if (dp < len && (op & ASN1_OP_END__OF)) { | ||
| 402 | datalen = len; | ||
| 403 | csp++; | ||
| 404 | pc = machine[pc + 1]; | ||
| 405 | pr_debug("- continue\n"); | ||
| 406 | goto next_op; | ||
| 407 | } | ||
| 408 | if (dp != len) | ||
| 409 | goto cons_length_error; | ||
| 410 | len -= tdp; | ||
| 411 | pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); | ||
| 412 | } | ||
| 413 | |||
| 414 | if (op & ASN1_OP_END__ACT) { | ||
| 415 | unsigned char act; | ||
| 416 | if (op & ASN1_OP_END__OF) | ||
| 417 | act = machine[pc + 2]; | ||
| 418 | else | ||
| 419 | act = machine[pc + 1]; | ||
| 420 | ret = actions[act](context, hdr, 0, data + tdp, len); | ||
| 421 | } | ||
| 422 | pc += asn1_op_lengths[op]; | ||
| 423 | goto next_op; | ||
| 424 | |||
| 425 | case ASN1_OP_ACT: | ||
| 426 | ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); | ||
| 427 | pc += asn1_op_lengths[op]; | ||
| 428 | goto next_op; | ||
| 429 | |||
| 430 | case ASN1_OP_RETURN: | ||
| 431 | if (unlikely(jsp <= 0)) | ||
| 432 | goto jump_stack_underflow; | ||
| 433 | pc = jump_stack[--jsp]; | ||
| 434 | goto next_op; | ||
| 435 | |||
| 436 | default: | ||
| 437 | break; | ||
| 438 | } | ||
| 439 | |||
| 440 | /* Shouldn't reach here */ | ||
| 441 | pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); | ||
| 442 | return -EBADMSG; | ||
| 443 | |||
| 444 | data_overrun_error: | ||
| 445 | errmsg = "Data overrun error"; | ||
| 446 | goto error; | ||
| 447 | machine_overrun_error: | ||
| 448 | errmsg = "Machine overrun error"; | ||
| 449 | goto error; | ||
| 450 | jump_stack_underflow: | ||
| 451 | errmsg = "Jump stack underflow"; | ||
| 452 | goto error; | ||
| 453 | jump_stack_overflow: | ||
| 454 | errmsg = "Jump stack overflow"; | ||
| 455 | goto error; | ||
| 456 | cons_stack_underflow: | ||
| 457 | errmsg = "Cons stack underflow"; | ||
| 458 | goto error; | ||
| 459 | cons_stack_overflow: | ||
| 460 | errmsg = "Cons stack overflow"; | ||
| 461 | goto error; | ||
| 462 | cons_length_error: | ||
| 463 | errmsg = "Cons length error"; | ||
| 464 | goto error; | ||
| 465 | missing_eoc: | ||
| 466 | errmsg = "Missing EOC in indefinite len cons"; | ||
| 467 | goto error; | ||
| 468 | invalid_eoc: | ||
| 469 | errmsg = "Invalid length EOC"; | ||
| 470 | goto error; | ||
| 471 | length_too_long: | ||
| 472 | errmsg = "Unsupported length"; | ||
| 473 | goto error; | ||
| 474 | indefinite_len_primitive: | ||
| 475 | errmsg = "Indefinite len primitive not permitted"; | ||
| 476 | goto error; | ||
| 477 | tag_mismatch: | ||
| 478 | errmsg = "Unexpected tag"; | ||
| 479 | goto error; | ||
| 480 | long_tag_not_supported: | ||
| 481 | errmsg = "Long tag not supported"; | ||
| 482 | error: | ||
| 483 | pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", | ||
| 484 | errmsg, pc, dp, optag, tag, len); | ||
| 485 | return -EBADMSG; | ||
| 486 | } | ||
| 487 | EXPORT_SYMBOL_GPL(asn1_ber_decoder); | ||
diff --git a/lib/build_OID_registry b/lib/build_OID_registry new file mode 100755 index 000000000000..dfbdaab81bc8 --- /dev/null +++ b/lib/build_OID_registry | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | #!/usr/bin/perl -w | ||
| 2 | # | ||
| 3 | # Build a static ASN.1 Object Identified (OID) registry | ||
| 4 | # | ||
| 5 | # Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
| 6 | # Written by David Howells (dhowells@redhat.com) | ||
| 7 | # | ||
| 8 | # This program is free software; you can redistribute it and/or | ||
| 9 | # modify it under the terms of the GNU General Public Licence | ||
| 10 | # as published by the Free Software Foundation; either version | ||
| 11 | # 2 of the Licence, or (at your option) any later version. | ||
| 12 | # | ||
| 13 | |||
| 14 | use strict; | ||
| 15 | |||
| 16 | my @names = (); | ||
| 17 | my @oids = (); | ||
| 18 | |||
| 19 | if ($#ARGV != 1) { | ||
| 20 | print STDERR "Format: ", $0, " <in-h-file> <out-c-file>\n"; | ||
| 21 | exit(2); | ||
| 22 | } | ||
| 23 | |||
| 24 | # | ||
| 25 | # Open the file to read from | ||
| 26 | # | ||
| 27 | open IN_FILE, "<$ARGV[0]" || die; | ||
| 28 | while (<IN_FILE>) { | ||
| 29 | chomp; | ||
| 30 | if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) { | ||
| 31 | push @names, $1; | ||
| 32 | push @oids, $2; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | close IN_FILE || die; | ||
| 36 | |||
| 37 | # | ||
| 38 | # Open the files to write into | ||
| 39 | # | ||
| 40 | open C_FILE, ">$ARGV[1]" or die; | ||
| 41 | print C_FILE "/*\n"; | ||
| 42 | print C_FILE " * Automatically generated by ", $0, ". Do not edit\n"; | ||
| 43 | print C_FILE " */\n"; | ||
| 44 | |||
| 45 | # | ||
| 46 | # Split the data up into separate lists and also determine the lengths of the | ||
| 47 | # encoded data arrays. | ||
| 48 | # | ||
| 49 | my @indices = (); | ||
| 50 | my @lengths = (); | ||
| 51 | my $total_length = 0; | ||
| 52 | |||
| 53 | print "Compiling ", $#names + 1, " OIDs\n"; | ||
| 54 | |||
| 55 | for (my $i = 0; $i <= $#names; $i++) { | ||
| 56 | my $name = $names[$i]; | ||
| 57 | my $oid = $oids[$i]; | ||
| 58 | |||
| 59 | my @components = split(/[.]/, $oid); | ||
| 60 | |||
| 61 | # Determine the encoded length of this OID | ||
| 62 | my $size = $#components; | ||
| 63 | for (my $loop = 2; $loop <= $#components; $loop++) { | ||
| 64 | my $c = $components[$loop]; | ||
| 65 | |||
| 66 | # We will base128 encode the number | ||
| 67 | my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); | ||
| 68 | $tmp = int($tmp / 7); | ||
| 69 | $size += $tmp; | ||
| 70 | } | ||
| 71 | push @lengths, $size; | ||
| 72 | push @indices, $total_length; | ||
| 73 | $total_length += $size; | ||
| 74 | } | ||
| 75 | |||
| 76 | # | ||
| 77 | # Emit the look-up-by-OID index table | ||
| 78 | # | ||
| 79 | print C_FILE "\n"; | ||
| 80 | if ($total_length <= 255) { | ||
| 81 | print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n"; | ||
| 82 | } else { | ||
| 83 | print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n"; | ||
| 84 | } | ||
| 85 | for (my $i = 0; $i <= $#names; $i++) { | ||
| 86 | print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n" | ||
| 87 | } | ||
| 88 | print C_FILE "\t[OID__NR] = ", $total_length, "\n"; | ||
| 89 | print C_FILE "};\n"; | ||
| 90 | |||
| 91 | # | ||
| 92 | # Encode the OIDs | ||
| 93 | # | ||
| 94 | my @encoded_oids = (); | ||
| 95 | |||
| 96 | for (my $i = 0; $i <= $#names; $i++) { | ||
| 97 | my @octets = (); | ||
| 98 | |||
| 99 | my @components = split(/[.]/, $oids[$i]); | ||
| 100 | |||
| 101 | push @octets, $components[0] * 40 + $components[1]; | ||
| 102 | |||
| 103 | for (my $loop = 2; $loop <= $#components; $loop++) { | ||
| 104 | my $c = $components[$loop]; | ||
| 105 | |||
| 106 | # Base128 encode the number | ||
| 107 | my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); | ||
| 108 | $tmp = int($tmp / 7); | ||
| 109 | |||
| 110 | for (; $tmp > 0; $tmp--) { | ||
| 111 | push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80; | ||
| 112 | } | ||
| 113 | push @octets, $c & 0x7f; | ||
| 114 | } | ||
| 115 | |||
| 116 | push @encoded_oids, \@octets; | ||
| 117 | } | ||
| 118 | |||
| 119 | # | ||
| 120 | # Create a hash value for each OID | ||
| 121 | # | ||
| 122 | my @hash_values = (); | ||
| 123 | for (my $i = 0; $i <= $#names; $i++) { | ||
| 124 | my @octets = @{$encoded_oids[$i]}; | ||
| 125 | |||
| 126 | my $hash = $#octets; | ||
| 127 | foreach (@octets) { | ||
| 128 | $hash += $_ * 33; | ||
| 129 | } | ||
| 130 | |||
| 131 | $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash); | ||
| 132 | |||
| 133 | push @hash_values, $hash & 0xff; | ||
| 134 | } | ||
| 135 | |||
| 136 | # | ||
| 137 | # Emit the OID data | ||
| 138 | # | ||
| 139 | print C_FILE "\n"; | ||
| 140 | print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n"; | ||
| 141 | for (my $i = 0; $i <= $#names; $i++) { | ||
| 142 | my @octets = @{$encoded_oids[$i]}; | ||
| 143 | print C_FILE "\t"; | ||
| 144 | print C_FILE $_, ", " foreach (@octets); | ||
| 145 | print C_FILE "\t// ", $names[$i]; | ||
| 146 | print C_FILE "\n"; | ||
| 147 | } | ||
| 148 | print C_FILE "};\n"; | ||
| 149 | |||
| 150 | # | ||
| 151 | # Build the search index table (ordered by length then hash then content) | ||
| 152 | # | ||
| 153 | my @index_table = ( 0 .. $#names ); | ||
| 154 | |||
| 155 | @index_table = sort { | ||
| 156 | my @octets_a = @{$encoded_oids[$a]}; | ||
| 157 | my @octets_b = @{$encoded_oids[$b]}; | ||
| 158 | |||
| 159 | return $hash_values[$a] <=> $hash_values[$b] | ||
| 160 | if ($hash_values[$a] != $hash_values[$b]); | ||
| 161 | return $#octets_a <=> $#octets_b | ||
| 162 | if ($#octets_a != $#octets_b); | ||
| 163 | for (my $i = $#octets_a; $i >= 0; $i--) { | ||
| 164 | return $octets_a[$i] <=> $octets_b[$i] | ||
| 165 | if ($octets_a[$i] != $octets_b[$i]); | ||
| 166 | } | ||
| 167 | return 0; | ||
| 168 | |||
| 169 | } @index_table; | ||
| 170 | |||
| 171 | # | ||
| 172 | # Emit the search index and hash value table | ||
| 173 | # | ||
| 174 | print C_FILE "\n"; | ||
| 175 | print C_FILE "static const struct {\n"; | ||
| 176 | print C_FILE "\tunsigned char hash;\n"; | ||
| 177 | if ($#names <= 255) { | ||
| 178 | print C_FILE "\tenum OID oid : 8;\n"; | ||
| 179 | } else { | ||
| 180 | print C_FILE "\tenum OID oid : 16;\n"; | ||
| 181 | } | ||
| 182 | print C_FILE "} oid_search_table[OID__NR] = {\n"; | ||
| 183 | for (my $i = 0; $i <= $#names; $i++) { | ||
| 184 | my @octets = @{$encoded_oids[$index_table[$i]]}; | ||
| 185 | printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ", | ||
| 186 | $i, | ||
| 187 | $hash_values[$index_table[$i]], | ||
| 188 | $names[$index_table[$i]]); | ||
| 189 | printf C_FILE "%02x", $_ foreach (@octets); | ||
| 190 | print C_FILE "\n"; | ||
| 191 | } | ||
| 192 | print C_FILE "};\n"; | ||
| 193 | |||
| 194 | # | ||
| 195 | # Emit the OID debugging name table | ||
| 196 | # | ||
| 197 | #print C_FILE "\n"; | ||
| 198 | #print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n"; | ||
| 199 | # | ||
| 200 | #for (my $i = 0; $i <= $#names; $i++) { | ||
| 201 | # print C_FILE "\t\"", $names[$i], "\",\n" | ||
| 202 | #} | ||
| 203 | #print C_FILE "\t\"Unknown-OID\"\n"; | ||
| 204 | #print C_FILE "};\n"; | ||
| 205 | |||
| 206 | # | ||
| 207 | # Polish off | ||
| 208 | # | ||
| 209 | close C_FILE or die; | ||
diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile index 45ca90a8639c..019a68c90144 100644 --- a/lib/mpi/Makefile +++ b/lib/mpi/Makefile | |||
| @@ -14,6 +14,7 @@ mpi-y = \ | |||
| 14 | generic_mpih-add1.o \ | 14 | generic_mpih-add1.o \ |
| 15 | mpicoder.o \ | 15 | mpicoder.o \ |
| 16 | mpi-bit.o \ | 16 | mpi-bit.o \ |
| 17 | mpi-cmp.o \ | ||
| 17 | mpih-cmp.o \ | 18 | mpih-cmp.o \ |
| 18 | mpih-div.o \ | 19 | mpih-div.o \ |
| 19 | mpih-mul.o \ | 20 | mpih-mul.o \ |
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index 29f98624ef93..678ce4f1e124 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | 19 | * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
| 20 | * MA 02111-1307, USA. */ | 20 | * MA 02111-1307, USA. */ |
| 21 | 21 | ||
| 22 | #include <asm-generic/bitops/count_zeros.h> | ||
| 23 | |||
| 22 | /* You have to define the following before including this file: | 24 | /* You have to define the following before including this file: |
| 23 | * | 25 | * |
| 24 | * UWtype -- An unsigned type, default type for operations (typically a "word") | 26 | * UWtype -- An unsigned type, default type for operations (typically a "word") |
| @@ -146,12 +148,6 @@ do { \ | |||
| 146 | : "1" ((USItype)(n1)), \ | 148 | : "1" ((USItype)(n1)), \ |
| 147 | "r" ((USItype)(n0)), \ | 149 | "r" ((USItype)(n0)), \ |
| 148 | "r" ((USItype)(d))) | 150 | "r" ((USItype)(d))) |
| 149 | |||
| 150 | #define count_leading_zeros(count, x) \ | ||
| 151 | __asm__ ("clz %0,%1" \ | ||
| 152 | : "=r" ((USItype)(count)) \ | ||
| 153 | : "r" ((USItype)(x))) | ||
| 154 | #define COUNT_LEADING_ZEROS_0 32 | ||
| 155 | #endif /* __a29k__ */ | 151 | #endif /* __a29k__ */ |
| 156 | 152 | ||
| 157 | #if defined(__alpha) && W_TYPE_SIZE == 64 | 153 | #if defined(__alpha) && W_TYPE_SIZE == 64 |
| @@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd(); | |||
| 298 | : "1" ((USItype)(nh)), \ | 294 | : "1" ((USItype)(nh)), \ |
| 299 | "0" ((USItype)(nl)), \ | 295 | "0" ((USItype)(nl)), \ |
| 300 | "g" ((USItype)(d))) | 296 | "g" ((USItype)(d))) |
| 301 | #define count_leading_zeros(count, x) \ | ||
| 302 | __asm__ ("bsch/1 %1,%0" \ | ||
| 303 | : "=g" (count) \ | ||
| 304 | : "g" ((USItype)(x)), \ | ||
| 305 | "0" ((USItype)0)) | ||
| 306 | #endif | 297 | #endif |
| 307 | 298 | ||
| 308 | /*************************************** | 299 | /*************************************** |
| @@ -354,27 +345,6 @@ do { USItype __r; \ | |||
| 354 | } while (0) | 345 | } while (0) |
| 355 | extern USItype __udiv_qrnnd(); | 346 | extern USItype __udiv_qrnnd(); |
| 356 | #endif /* LONGLONG_STANDALONE */ | 347 | #endif /* LONGLONG_STANDALONE */ |
| 357 | #define count_leading_zeros(count, x) \ | ||
| 358 | do { \ | ||
| 359 | USItype __tmp; \ | ||
| 360 | __asm__ ( \ | ||
| 361 | "ldi 1,%0\n" \ | ||
| 362 | "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ | ||
| 363 | "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ | ||
| 364 | "ldo 16(%0),%0 ; Yes. Perform add.\n" \ | ||
| 365 | "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ | ||
| 366 | "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ | ||
| 367 | "ldo 8(%0),%0 ; Yes. Perform add.\n" \ | ||
| 368 | "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ | ||
| 369 | "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ | ||
| 370 | "ldo 4(%0),%0 ; Yes. Perform add.\n" \ | ||
| 371 | "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ | ||
| 372 | "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ | ||
| 373 | "ldo 2(%0),%0 ; Yes. Perform add.\n" \ | ||
| 374 | "extru %1,30,1,%1 ; Extract bit 1.\n" \ | ||
| 375 | "sub %0,%1,%0 ; Subtract it. " \ | ||
| 376 | : "=r" (count), "=r" (__tmp) : "1" (x)); \ | ||
| 377 | } while (0) | ||
| 378 | #endif /* hppa */ | 348 | #endif /* hppa */ |
| 379 | 349 | ||
| 380 | /*************************************** | 350 | /*************************************** |
| @@ -457,15 +427,6 @@ do { \ | |||
| 457 | : "0" ((USItype)(n0)), \ | 427 | : "0" ((USItype)(n0)), \ |
| 458 | "1" ((USItype)(n1)), \ | 428 | "1" ((USItype)(n1)), \ |
| 459 | "rm" ((USItype)(d))) | 429 | "rm" ((USItype)(d))) |
| 460 | #define count_leading_zeros(count, x) \ | ||
| 461 | do { \ | ||
| 462 | USItype __cbtmp; \ | ||
| 463 | __asm__ ("bsrl %1,%0" \ | ||
| 464 | : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ | ||
| 465 | (count) = __cbtmp ^ 31; \ | ||
| 466 | } while (0) | ||
| 467 | #define count_trailing_zeros(count, x) \ | ||
| 468 | __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) | ||
| 469 | #ifndef UMUL_TIME | 430 | #ifndef UMUL_TIME |
| 470 | #define UMUL_TIME 40 | 431 | #define UMUL_TIME 40 |
| 471 | #endif | 432 | #endif |
| @@ -536,15 +497,6 @@ do { \ | |||
| 536 | "dI" ((USItype)(d))); \ | 497 | "dI" ((USItype)(d))); \ |
| 537 | (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ | 498 | (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ |
| 538 | } while (0) | 499 | } while (0) |
| 539 | #define count_leading_zeros(count, x) \ | ||
| 540 | do { \ | ||
| 541 | USItype __cbtmp; \ | ||
| 542 | __asm__ ("scanbit %1,%0" \ | ||
| 543 | : "=r" (__cbtmp) \ | ||
| 544 | : "r" ((USItype)(x))); \ | ||
| 545 | (count) = __cbtmp ^ 31; \ | ||
| 546 | } while (0) | ||
| 547 | #define COUNT_LEADING_ZEROS_0 (-32) /* sic */ | ||
| 548 | #if defined(__i960mx) /* what is the proper symbol to test??? */ | 500 | #if defined(__i960mx) /* what is the proper symbol to test??? */ |
| 549 | #define rshift_rhlc(r, h, l, c) \ | 501 | #define rshift_rhlc(r, h, l, c) \ |
| 550 | do { \ | 502 | do { \ |
| @@ -603,11 +555,6 @@ do { \ | |||
| 603 | : "0" ((USItype)(n0)), \ | 555 | : "0" ((USItype)(n0)), \ |
| 604 | "1" ((USItype)(n1)), \ | 556 | "1" ((USItype)(n1)), \ |
| 605 | "dmi" ((USItype)(d))) | 557 | "dmi" ((USItype)(d))) |
| 606 | #define count_leading_zeros(count, x) \ | ||
| 607 | __asm__ ("bfffo %1{%b2:%b2},%0" \ | ||
| 608 | : "=d" ((USItype)(count)) \ | ||
| 609 | : "od" ((USItype)(x)), "n" (0)) | ||
| 610 | #define COUNT_LEADING_ZEROS_0 32 | ||
| 611 | #else /* not mc68020 */ | 558 | #else /* not mc68020 */ |
| 612 | #define umul_ppmm(xh, xl, a, b) \ | 559 | #define umul_ppmm(xh, xl, a, b) \ |
| 613 | do { USItype __umul_tmp1, __umul_tmp2; \ | 560 | do { USItype __umul_tmp1, __umul_tmp2; \ |
| @@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \ | |||
| 664 | "rJ" ((USItype)(bh)), \ | 611 | "rJ" ((USItype)(bh)), \ |
| 665 | "rJ" ((USItype)(al)), \ | 612 | "rJ" ((USItype)(al)), \ |
| 666 | "rJ" ((USItype)(bl))) | 613 | "rJ" ((USItype)(bl))) |
| 667 | #define count_leading_zeros(count, x) \ | ||
| 668 | do { \ | ||
| 669 | USItype __cbtmp; \ | ||
| 670 | __asm__ ("ff1 %0,%1" \ | ||
| 671 | : "=r" (__cbtmp) \ | ||
| 672 | : "r" ((USItype)(x))); \ | ||
| 673 | (count) = __cbtmp ^ 31; \ | ||
| 674 | } while (0) | ||
| 675 | #define COUNT_LEADING_ZEROS_0 63 /* sic */ | ||
| 676 | #if defined(__m88110__) | 614 | #if defined(__m88110__) |
| 677 | #define umul_ppmm(wh, wl, u, v) \ | 615 | #define umul_ppmm(wh, wl, u, v) \ |
| 678 | do { \ | 616 | do { \ |
| @@ -779,12 +717,6 @@ do { \ | |||
| 779 | : "0" (__xx.__ll), \ | 717 | : "0" (__xx.__ll), \ |
| 780 | "g" ((USItype)(d))); \ | 718 | "g" ((USItype)(d))); \ |
| 781 | (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) | 719 | (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) |
| 782 | #define count_trailing_zeros(count, x) \ | ||
| 783 | do { \ | ||
| 784 | __asm__("ffsd %2,%0" \ | ||
| 785 | : "=r"((USItype) (count)) \ | ||
| 786 | : "0"((USItype) 0), "r"((USItype) (x))); \ | ||
| 787 | } while (0) | ||
| 788 | #endif /* __ns32000__ */ | 720 | #endif /* __ns32000__ */ |
| 789 | 721 | ||
| 790 | /*************************************** | 722 | /*************************************** |
| @@ -855,11 +787,6 @@ do { \ | |||
| 855 | "rI" ((USItype)(al)), \ | 787 | "rI" ((USItype)(al)), \ |
| 856 | "r" ((USItype)(bl))); \ | 788 | "r" ((USItype)(bl))); \ |
| 857 | } while (0) | 789 | } while (0) |
| 858 | #define count_leading_zeros(count, x) \ | ||
| 859 | __asm__ ("{cntlz|cntlzw} %0,%1" \ | ||
| 860 | : "=r" ((USItype)(count)) \ | ||
| 861 | : "r" ((USItype)(x))) | ||
| 862 | #define COUNT_LEADING_ZEROS_0 32 | ||
| 863 | #if defined(_ARCH_PPC) | 790 | #if defined(_ARCH_PPC) |
| 864 | #define umul_ppmm(ph, pl, m0, m1) \ | 791 | #define umul_ppmm(ph, pl, m0, m1) \ |
| 865 | do { \ | 792 | do { \ |
| @@ -1001,19 +928,6 @@ do { \ | |||
| 1001 | } while (0) | 928 | } while (0) |
| 1002 | #define UMUL_TIME 20 | 929 | #define UMUL_TIME 20 |
| 1003 | #define UDIV_TIME 200 | 930 | #define UDIV_TIME 200 |
| 1004 | #define count_leading_zeros(count, x) \ | ||
| 1005 | do { \ | ||
| 1006 | if ((x) >= 0x10000) \ | ||
| 1007 | __asm__ ("clz %0,%1" \ | ||
| 1008 | : "=r" ((USItype)(count)) \ | ||
| 1009 | : "r" ((USItype)(x) >> 16)); \ | ||
| 1010 | else { \ | ||
| 1011 | __asm__ ("clz %0,%1" \ | ||
| 1012 | : "=r" ((USItype)(count)) \ | ||
| 1013 | : "r" ((USItype)(x))); \ | ||
| 1014 | (count) += 16; \ | ||
| 1015 | } \ | ||
| 1016 | } while (0) | ||
| 1017 | #endif /* RT/ROMP */ | 931 | #endif /* RT/ROMP */ |
| 1018 | 932 | ||
| 1019 | /*************************************** | 933 | /*************************************** |
| @@ -1142,13 +1056,6 @@ do { \ | |||
| 1142 | "rI" ((USItype)(d)) \ | 1056 | "rI" ((USItype)(d)) \ |
| 1143 | : "%g1" __AND_CLOBBER_CC) | 1057 | : "%g1" __AND_CLOBBER_CC) |
| 1144 | #define UDIV_TIME 37 | 1058 | #define UDIV_TIME 37 |
| 1145 | #define count_leading_zeros(count, x) \ | ||
| 1146 | __asm__ ("scan %1,0,%0" \ | ||
| 1147 | : "=r" ((USItype)(x)) \ | ||
| 1148 | : "r" ((USItype)(count))) | ||
| 1149 | /* Early sparclites return 63 for an argument of 0, but they warn that future | ||
| 1150 | implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 | ||
| 1151 | undefined. */ | ||
| 1152 | #endif /* __sparclite__ */ | 1059 | #endif /* __sparclite__ */ |
| 1153 | #endif /* __sparc_v8__ */ | 1060 | #endif /* __sparc_v8__ */ |
| 1154 | /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ | 1061 | /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ |
| @@ -1454,47 +1361,6 @@ do { \ | |||
| 1454 | #define udiv_qrnnd __udiv_qrnnd_c | 1361 | #define udiv_qrnnd __udiv_qrnnd_c |
| 1455 | #endif | 1362 | #endif |
| 1456 | 1363 | ||
| 1457 | #undef count_leading_zeros | ||
| 1458 | #if !defined(count_leading_zeros) | ||
| 1459 | extern | ||
| 1460 | #ifdef __STDC__ | ||
| 1461 | const | ||
| 1462 | #endif | ||
| 1463 | unsigned char __clz_tab[]; | ||
| 1464 | #define count_leading_zeros(count, x) \ | ||
| 1465 | do { \ | ||
| 1466 | UWtype __xr = (x); \ | ||
| 1467 | UWtype __a; \ | ||
| 1468 | \ | ||
| 1469 | if (W_TYPE_SIZE <= 32) { \ | ||
| 1470 | __a = __xr < ((UWtype) 1 << 2*__BITS4) \ | ||
| 1471 | ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ | ||
| 1472 | : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ | ||
| 1473 | } \ | ||
| 1474 | else { \ | ||
| 1475 | for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ | ||
| 1476 | if (((__xr >> __a) & 0xff) != 0) \ | ||
| 1477 | break; \ | ||
| 1478 | } \ | ||
| 1479 | \ | ||
| 1480 | (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ | ||
| 1481 | } while (0) | ||
| 1482 | /* This version gives a well-defined value for zero. */ | ||
| 1483 | #define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE | ||
| 1484 | #endif | ||
| 1485 | |||
| 1486 | #if !defined(count_trailing_zeros) | ||
| 1487 | /* Define count_trailing_zeros using count_leading_zeros. The latter might be | ||
| 1488 | defined in asm, but if it is not, the C version above is good enough. */ | ||
| 1489 | #define count_trailing_zeros(count, x) \ | ||
| 1490 | do { \ | ||
| 1491 | UWtype __ctz_x = (x); \ | ||
| 1492 | UWtype __ctz_c; \ | ||
| 1493 | count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ | ||
| 1494 | (count) = W_TYPE_SIZE - 1 - __ctz_c; \ | ||
| 1495 | } while (0) | ||
| 1496 | #endif | ||
| 1497 | |||
| 1498 | #ifndef UDIV_NEEDS_NORMALIZATION | 1364 | #ifndef UDIV_NEEDS_NORMALIZATION |
| 1499 | #define UDIV_NEEDS_NORMALIZATION 0 | 1365 | #define UDIV_NEEDS_NORMALIZATION 0 |
| 1500 | #endif | 1366 | #endif |
diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c index 568724804f29..503537e08436 100644 --- a/lib/mpi/mpi-bit.c +++ b/lib/mpi/mpi-bit.c | |||
| @@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a) | |||
| 45 | if (a->nlimbs) { | 45 | if (a->nlimbs) { |
| 46 | mpi_limb_t alimb = a->d[a->nlimbs - 1]; | 46 | mpi_limb_t alimb = a->d[a->nlimbs - 1]; |
| 47 | if (alimb) | 47 | if (alimb) |
| 48 | count_leading_zeros(n, alimb); | 48 | n = count_leading_zeros(alimb); |
| 49 | else | 49 | else |
| 50 | n = BITS_PER_MPI_LIMB; | 50 | n = BITS_PER_MPI_LIMB; |
| 51 | n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; | 51 | n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; |
diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c new file mode 100644 index 000000000000..1871e7b61ca0 --- /dev/null +++ b/lib/mpi/mpi-cmp.c | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* mpi-cmp.c - MPI functions | ||
| 2 | * Copyright (C) 1998, 1999 Free Software Foundation, Inc. | ||
| 3 | * | ||
| 4 | * This file is part of GnuPG. | ||
| 5 | * | ||
| 6 | * GnuPG is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * GnuPG is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include "mpi-internal.h" | ||
| 22 | |||
| 23 | int mpi_cmp_ui(MPI u, unsigned long v) | ||
| 24 | { | ||
| 25 | mpi_limb_t limb = v; | ||
| 26 | |||
| 27 | mpi_normalize(u); | ||
| 28 | if (!u->nlimbs && !limb) | ||
| 29 | return 0; | ||
| 30 | if (u->sign) | ||
| 31 | return -1; | ||
| 32 | if (u->nlimbs > 1) | ||
| 33 | return 1; | ||
| 34 | |||
| 35 | if (u->d[0] == limb) | ||
| 36 | return 0; | ||
| 37 | else if (u->d[0] > limb) | ||
| 38 | return 1; | ||
| 39 | else | ||
| 40 | return -1; | ||
| 41 | } | ||
| 42 | EXPORT_SYMBOL_GPL(mpi_cmp_ui); | ||
| 43 | |||
| 44 | int mpi_cmp(MPI u, MPI v) | ||
| 45 | { | ||
| 46 | mpi_size_t usize, vsize; | ||
| 47 | int cmp; | ||
| 48 | |||
| 49 | mpi_normalize(u); | ||
| 50 | mpi_normalize(v); | ||
| 51 | usize = u->nlimbs; | ||
| 52 | vsize = v->nlimbs; | ||
| 53 | if (!u->sign && v->sign) | ||
| 54 | return 1; | ||
| 55 | if (u->sign && !v->sign) | ||
| 56 | return -1; | ||
| 57 | if (usize != vsize && !u->sign && !v->sign) | ||
| 58 | return usize - vsize; | ||
| 59 | if (usize != vsize && u->sign && v->sign) | ||
| 60 | return vsize + usize; | ||
| 61 | if (!usize) | ||
| 62 | return 0; | ||
| 63 | cmp = mpihelp_cmp(u->d, v->d, usize); | ||
| 64 | if (!cmp) | ||
| 65 | return 0; | ||
| 66 | if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) | ||
| 67 | return 1; | ||
| 68 | return -1; | ||
| 69 | } | ||
| 70 | EXPORT_SYMBOL_GPL(mpi_cmp); | ||
diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c index 67f3e79af914..5464c8744ea9 100644 --- a/lib/mpi/mpi-pow.c +++ b/lib/mpi/mpi-pow.c | |||
| @@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) | |||
| 77 | mp = mp_marker = mpi_alloc_limb_space(msize); | 77 | mp = mp_marker = mpi_alloc_limb_space(msize); |
| 78 | if (!mp) | 78 | if (!mp) |
| 79 | goto enomem; | 79 | goto enomem; |
| 80 | count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); | 80 | mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); |
| 81 | if (mod_shift_cnt) | 81 | if (mod_shift_cnt) |
| 82 | mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); | 82 | mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); |
| 83 | else | 83 | else |
| @@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) | |||
| 169 | 169 | ||
| 170 | i = esize - 1; | 170 | i = esize - 1; |
| 171 | e = ep[i]; | 171 | e = ep[i]; |
| 172 | count_leading_zeros(c, e); | 172 | c = count_leading_zeros(e); |
| 173 | e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ | 173 | e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ |
| 174 | c = BITS_PER_MPI_LIMB - 1 - c; | 174 | c = BITS_PER_MPI_LIMB - 1 - c; |
| 175 | 175 | ||
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index f0fa65995800..3962b7f7fe3f 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c | |||
| @@ -18,10 +18,65 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/bitops.h> | ||
| 22 | #include <asm-generic/bitops/count_zeros.h> | ||
| 21 | #include "mpi-internal.h" | 23 | #include "mpi-internal.h" |
| 22 | 24 | ||
| 23 | #define MAX_EXTERN_MPI_BITS 16384 | 25 | #define MAX_EXTERN_MPI_BITS 16384 |
| 24 | 26 | ||
| 27 | /** | ||
| 28 | * mpi_read_raw_data - Read a raw byte stream as a positive integer | ||
| 29 | * @xbuffer: The data to read | ||
| 30 | * @nbytes: The amount of data to read | ||
| 31 | */ | ||
| 32 | MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes) | ||
| 33 | { | ||
| 34 | const uint8_t *buffer = xbuffer; | ||
| 35 | int i, j; | ||
| 36 | unsigned nbits, nlimbs; | ||
| 37 | mpi_limb_t a; | ||
| 38 | MPI val = NULL; | ||
| 39 | |||
| 40 | while (nbytes >= 0 && buffer[0] == 0) { | ||
| 41 | buffer++; | ||
| 42 | nbytes--; | ||
| 43 | } | ||
| 44 | |||
| 45 | nbits = nbytes * 8; | ||
| 46 | if (nbits > MAX_EXTERN_MPI_BITS) { | ||
| 47 | pr_info("MPI: mpi too large (%u bits)\n", nbits); | ||
| 48 | return NULL; | ||
| 49 | } | ||
| 50 | if (nbytes > 0) | ||
| 51 | nbits -= count_leading_zeros(buffer[0]); | ||
| 52 | else | ||
| 53 | nbits = 0; | ||
| 54 | |||
| 55 | nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; | ||
| 56 | val = mpi_alloc(nlimbs); | ||
| 57 | if (!val) | ||
| 58 | return NULL; | ||
| 59 | val->nbits = nbits; | ||
| 60 | val->sign = 0; | ||
| 61 | val->nlimbs = nlimbs; | ||
| 62 | |||
| 63 | if (nbytes > 0) { | ||
| 64 | i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | ||
| 65 | i %= BYTES_PER_MPI_LIMB; | ||
| 66 | for (j = nlimbs; j > 0; j--) { | ||
| 67 | a = 0; | ||
| 68 | for (; i < BYTES_PER_MPI_LIMB; i++) { | ||
| 69 | a <<= 8; | ||
| 70 | a |= *buffer++; | ||
| 71 | } | ||
| 72 | i = 0; | ||
| 73 | val->d[j - 1] = a; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | return val; | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL_GPL(mpi_read_raw_data); | ||
| 79 | |||
| 25 | MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) | 80 | MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) |
| 26 | { | 81 | { |
| 27 | const uint8_t *buffer = xbuffer; | 82 | const uint8_t *buffer = xbuffer; |
diff --git a/lib/oid_registry.c b/lib/oid_registry.c new file mode 100644 index 000000000000..d8de11f45908 --- /dev/null +++ b/lib/oid_registry.c | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | /* ASN.1 Object identifier (OID) registry | ||
| 2 | * | ||
| 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/export.h> | ||
| 13 | #include <linux/oid_registry.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/bug.h> | ||
| 17 | #include "oid_registry_data.c" | ||
| 18 | |||
| 19 | /** | ||
| 20 | * look_up_OID - Find an OID registration for the specified data | ||
| 21 | * @data: Binary representation of the OID | ||
| 22 | * @datasize: Size of the binary representation | ||
| 23 | */ | ||
| 24 | enum OID look_up_OID(const void *data, size_t datasize) | ||
| 25 | { | ||
| 26 | const unsigned char *octets = data; | ||
| 27 | enum OID oid; | ||
| 28 | unsigned char xhash; | ||
| 29 | unsigned i, j, k, hash; | ||
| 30 | size_t len; | ||
| 31 | |||
| 32 | /* Hash the OID data */ | ||
| 33 | hash = datasize - 1; | ||
| 34 | |||
| 35 | for (i = 0; i < datasize; i++) | ||
| 36 | hash += octets[i] * 33; | ||
| 37 | hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; | ||
| 38 | hash &= 0xff; | ||
| 39 | |||
| 40 | /* Binary search the OID registry. OIDs are stored in ascending order | ||
| 41 | * of hash value then ascending order of size and then in ascending | ||
| 42 | * order of reverse value. | ||
| 43 | */ | ||
| 44 | i = 0; | ||
| 45 | k = OID__NR; | ||
| 46 | while (i < k) { | ||
| 47 | j = (i + k) / 2; | ||
| 48 | |||
| 49 | xhash = oid_search_table[j].hash; | ||
| 50 | if (xhash > hash) { | ||
| 51 | k = j; | ||
| 52 | continue; | ||
| 53 | } | ||
| 54 | if (xhash < hash) { | ||
| 55 | i = j + 1; | ||
| 56 | continue; | ||
| 57 | } | ||
| 58 | |||
| 59 | oid = oid_search_table[j].oid; | ||
| 60 | len = oid_index[oid + 1] - oid_index[oid]; | ||
| 61 | if (len > datasize) { | ||
| 62 | k = j; | ||
| 63 | continue; | ||
| 64 | } | ||
| 65 | if (len < datasize) { | ||
| 66 | i = j + 1; | ||
| 67 | continue; | ||
| 68 | } | ||
| 69 | |||
| 70 | /* Variation is most likely to be at the tail end of the | ||
| 71 | * OID, so do the comparison in reverse. | ||
| 72 | */ | ||
| 73 | while (len > 0) { | ||
| 74 | unsigned char a = oid_data[oid_index[oid] + --len]; | ||
| 75 | unsigned char b = octets[len]; | ||
| 76 | if (a > b) { | ||
| 77 | k = j; | ||
| 78 | goto next; | ||
| 79 | } | ||
| 80 | if (a < b) { | ||
| 81 | i = j + 1; | ||
| 82 | goto next; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | return oid; | ||
| 86 | next: | ||
| 87 | ; | ||
| 88 | } | ||
| 89 | |||
| 90 | return OID__NR; | ||
| 91 | } | ||
| 92 | EXPORT_SYMBOL_GPL(look_up_OID); | ||
| 93 | |||
| 94 | /* | ||
| 95 | * sprint_OID - Print an Object Identifier into a buffer | ||
| 96 | * @data: The encoded OID to print | ||
| 97 | * @datasize: The size of the encoded OID | ||
| 98 | * @buffer: The buffer to render into | ||
| 99 | * @bufsize: The size of the buffer | ||
| 100 | * | ||
| 101 | * The OID is rendered into the buffer in "a.b.c.d" format and the number of | ||
| 102 | * bytes is returned. -EBADMSG is returned if the data could not be intepreted | ||
| 103 | * and -ENOBUFS if the buffer was too small. | ||
| 104 | */ | ||
| 105 | int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) | ||
| 106 | { | ||
| 107 | const unsigned char *v = data, *end = v + datasize; | ||
| 108 | unsigned long num; | ||
| 109 | unsigned char n; | ||
| 110 | size_t ret; | ||
| 111 | int count; | ||
| 112 | |||
| 113 | if (v >= end) | ||
| 114 | return -EBADMSG; | ||
| 115 | |||
| 116 | n = *v++; | ||
| 117 | ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); | ||
| 118 | buffer += count; | ||
| 119 | bufsize -= count; | ||
| 120 | if (bufsize == 0) | ||
| 121 | return -ENOBUFS; | ||
| 122 | |||
| 123 | while (v < end) { | ||
| 124 | num = 0; | ||
| 125 | n = *v++; | ||
| 126 | if (!(n & 0x80)) { | ||
| 127 | num = n; | ||
| 128 | } else { | ||
| 129 | num = n & 0x7f; | ||
| 130 | do { | ||
| 131 | if (v >= end) | ||
| 132 | return -EBADMSG; | ||
| 133 | n = *v++; | ||
| 134 | num <<= 7; | ||
| 135 | num |= n & 0x7f; | ||
| 136 | } while (n & 0x80); | ||
| 137 | } | ||
| 138 | ret += count = snprintf(buffer, bufsize, ".%lu", num); | ||
| 139 | buffer += count; | ||
| 140 | bufsize -= count; | ||
| 141 | if (bufsize == 0) | ||
| 142 | return -ENOBUFS; | ||
| 143 | } | ||
| 144 | |||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | EXPORT_SYMBOL_GPL(sprint_oid); | ||
| 148 | |||
| 149 | /** | ||
| 150 | * sprint_OID - Print an Object Identifier into a buffer | ||
| 151 | * @oid: The OID to print | ||
| 152 | * @buffer: The buffer to render into | ||
| 153 | * @bufsize: The size of the buffer | ||
| 154 | * | ||
| 155 | * The OID is rendered into the buffer in "a.b.c.d" format and the number of | ||
| 156 | * bytes is returned. | ||
| 157 | */ | ||
| 158 | int sprint_OID(enum OID oid, char *buffer, size_t bufsize) | ||
| 159 | { | ||
| 160 | int ret; | ||
| 161 | |||
| 162 | BUG_ON(oid >= OID__NR); | ||
| 163 | |||
| 164 | ret = sprint_oid(oid_data + oid_index[oid], | ||
| 165 | oid_index[oid + 1] - oid_index[oid], | ||
| 166 | buffer, bufsize); | ||
| 167 | BUG_ON(ret == -EBADMSG); | ||
| 168 | return ret; | ||
| 169 | } | ||
| 170 | EXPORT_SYMBOL_GPL(sprint_OID); | ||
