1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2  *
3  * LibTomCrypt is a library that provides various cryptographic
4  * algorithms in a highly modular and flexible manner.
5  *
6  * The library is free for all purposes without any express
7  * guarantee it works.
8  */
9 #include "tomcrypt.h"
10 
11 /**
12   @file der_length_object_identifier.c
13   ASN.1 DER, get length of Object Identifier, Tom St Denis
14 */
15 
16 #ifdef LTC_DER
17 
der_object_identifier_bits(unsigned long x)18 unsigned long der_object_identifier_bits(unsigned long x)
19 {
20    unsigned long c;
21    x &= 0xFFFFFFFF;
22    c  = 0;
23    while (x) {
24      ++c;
25      x >>= 1;
26    }
27    return c;
28 }
29 
30 
31 /**
32   Gets length of DER encoding of Object Identifier
33   @param nwords   The number of OID words
34   @param words    The actual OID words to get the size of
35   @param outlen   [out] The length of the DER encoding for the given string
36   @return CRYPT_OK if successful
37 */
der_length_object_identifier(unsigned long * words,unsigned long nwords,unsigned long * outlen)38 int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen)
39 {
40    unsigned long y, z, t, wordbuf;
41 
42    LTC_ARGCHK(words  != NULL);
43    LTC_ARGCHK(outlen != NULL);
44 
45 
46    /* must be >= 2 words */
47    if (nwords < 2) {
48       return CRYPT_INVALID_ARG;
49    }
50 
51    /* word1 = 0,1,2,3 and word2 0..39 */
52    if (words[0] > 3 || (words[0] < 2 && words[1] > 39)) {
53       return CRYPT_INVALID_ARG;
54    }
55 
56    /* leading word is the first two */
57    z = 0;
58    wordbuf = words[0] * 40 + words[1];
59    for (y = 1; y < nwords; y++) {
60        t = der_object_identifier_bits(wordbuf);
61        z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
62        if (y < nwords - 1) {
63           /* grab next word */
64           wordbuf = words[y+1];
65        }
66    }
67 
68    /* now depending on the length our length encoding changes */
69    if (z < 128) {
70       z += 2;
71    } else if (z < 256) {
72       z += 3;
73    } else if (z < 65536UL) {
74       z += 4;
75    } else {
76       return CRYPT_INVALID_ARG;
77    }
78 
79    *outlen = z;
80    return CRYPT_OK;
81 }
82 
83 #endif
84 
85 /* ref:         $Format:%D$ */
86 /* git commit:  $Format:%H$ */
87 /* commit time: $Format:%ai$ */
88