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