aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-14 16:39:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-14 16:39:34 -0400
commitd25282d1c9b9bc4cda7f9d3c0205108e99aa7a9d (patch)
treef414482d768b015a609924293b779b4ad0b8f764 /lib
parentb6eea87fc6850d3531a64a27d2323a4498cd4e43 (diff)
parentdbadc17683e6c673a69b236c0f041b931cc55c42 (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/.gitignore2
-rw-r--r--lib/Kconfig5
-rw-r--r--lib/Makefile18
-rw-r--r--lib/asn1_decoder.c487
-rwxr-xr-xlib/build_OID_registry209
-rw-r--r--lib/mpi/Makefile1
-rw-r--r--lib/mpi/longlong.h138
-rw-r--r--lib/mpi/mpi-bit.c2
-rw-r--r--lib/mpi/mpi-cmp.c70
-rw-r--r--lib/mpi/mpi-pow.c4
-rw-r--r--lib/mpi/mpicoder.c55
-rw-r--r--lib/oid_registry.c170
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#
4gen_crc32table 4gen_crc32table
5crc32table.h 5crc32table.h
6 6oid_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
396config LIBFDT 396config LIBFDT
397 bool 397 bool
398 398
399config OID_REGISTRY
400 tristate
401 help
402 Enable fast lookup object identifier registry.
403
399endmenu 404endmenu
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
146interval_tree_test-objs := interval_tree_test_main.o interval_tree.o 146interval_tree_test-objs := interval_tree_test_main.o interval_tree.o
147 147
148obj-$(CONFIG_ASN1) += asn1_decoder.o
149
148hostprogs-y := gen_crc32table 150hostprogs-y := gen_crc32table
149clean-files := crc32table.h 151clean-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#
164obj-$(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
172quiet_cmd_build_OID_registry = GEN $@
173 cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@
174
175clean-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
18static 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 */
55static 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
63next_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
119length_too_long:
120 *_errmsg = "Unsupported length";
121 goto error;
122indefinite_len_primitive:
123 *_errmsg = "Indefinite len primitive not permitted";
124 goto error;
125invalid_eoc:
126 *_errmsg = "Invalid length EOC";
127 goto error;
128data_overrun_error:
129 *_errmsg = "Data overrun error";
130 goto error;
131missing_eoc:
132 *_errmsg = "Missing EOC in indefinite len cons";
133error:
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 */
163int 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
195next_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
444data_overrun_error:
445 errmsg = "Data overrun error";
446 goto error;
447machine_overrun_error:
448 errmsg = "Machine overrun error";
449 goto error;
450jump_stack_underflow:
451 errmsg = "Jump stack underflow";
452 goto error;
453jump_stack_overflow:
454 errmsg = "Jump stack overflow";
455 goto error;
456cons_stack_underflow:
457 errmsg = "Cons stack underflow";
458 goto error;
459cons_stack_overflow:
460 errmsg = "Cons stack overflow";
461 goto error;
462cons_length_error:
463 errmsg = "Cons length error";
464 goto error;
465missing_eoc:
466 errmsg = "Missing EOC in indefinite len cons";
467 goto error;
468invalid_eoc:
469 errmsg = "Invalid length EOC";
470 goto error;
471length_too_long:
472 errmsg = "Unsupported length";
473 goto error;
474indefinite_len_primitive:
475 errmsg = "Indefinite len primitive not permitted";
476 goto error;
477tag_mismatch:
478 errmsg = "Unexpected tag";
479 goto error;
480long_tag_not_supported:
481 errmsg = "Long tag not supported";
482error:
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}
487EXPORT_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
14use strict;
15
16my @names = ();
17my @oids = ();
18
19if ($#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#
27open IN_FILE, "<$ARGV[0]" || die;
28while (<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}
35close IN_FILE || die;
36
37#
38# Open the files to write into
39#
40open C_FILE, ">$ARGV[1]" or die;
41print C_FILE "/*\n";
42print C_FILE " * Automatically generated by ", $0, ". Do not edit\n";
43print 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#
49my @indices = ();
50my @lengths = ();
51my $total_length = 0;
52
53print "Compiling ", $#names + 1, " OIDs\n";
54
55for (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#
79print C_FILE "\n";
80if ($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}
85for (my $i = 0; $i <= $#names; $i++) {
86 print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n"
87}
88print C_FILE "\t[OID__NR] = ", $total_length, "\n";
89print C_FILE "};\n";
90
91#
92# Encode the OIDs
93#
94my @encoded_oids = ();
95
96for (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#
122my @hash_values = ();
123for (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#
139print C_FILE "\n";
140print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n";
141for (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}
148print C_FILE "};\n";
149
150#
151# Build the search index table (ordered by length then hash then content)
152#
153my @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#
174print C_FILE "\n";
175print C_FILE "static const struct {\n";
176print C_FILE "\tunsigned char hash;\n";
177if ($#names <= 255) {
178 print C_FILE "\tenum OID oid : 8;\n";
179} else {
180 print C_FILE "\tenum OID oid : 16;\n";
181}
182print C_FILE "} oid_search_table[OID__NR] = {\n";
183for (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}
192print 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#
209close 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)
355extern USItype __udiv_qrnnd(); 346extern USItype __udiv_qrnnd();
356#endif /* LONGLONG_STANDALONE */ 347#endif /* LONGLONG_STANDALONE */
357#define count_leading_zeros(count, x) \
358do { \
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) \
461do { \
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) \
540do { \
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) \
550do { \ 502do { \
@@ -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) \
613do { USItype __umul_tmp1, __umul_tmp2; \ 560do { 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) \
668do { \
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) \
678do { \ 616do { \
@@ -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) \
783do { \
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) \
865do { \ 792do { \
@@ -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) \
1005do { \
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) \
1465do { \
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) \
1490do { \
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
23int 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}
42EXPORT_SYMBOL_GPL(mpi_cmp_ui);
43
44int 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}
70EXPORT_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 */
32MPI 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}
78EXPORT_SYMBOL_GPL(mpi_read_raw_data);
79
25MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) 80MPI 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 */
24enum 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}
92EXPORT_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 */
105int 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}
147EXPORT_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 */
158int 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}
170EXPORT_SYMBOL_GPL(sprint_OID);