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