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_encode_object_identifier.c
14 ASN.1 DER, Encode Object Identifier, Tom St Denis
15 */
16
17 #ifdef LTC_DER
18 /**
19 Encode an OID
20 @param words The words to encode (upto 32-bits each)
21 @param nwords The number of words in the OID
22 @param out [out] Destination of OID data
23 @param outlen [in/out] The max and resulting size of the OID
24 @return CRYPT_OK if successful
25 */
der_encode_object_identifier(const unsigned long * words,unsigned long nwords,unsigned char * out,unsigned long * outlen)26 int der_encode_object_identifier(const unsigned long *words, unsigned long nwords,
27 unsigned char *out, unsigned long *outlen)
28 {
29 unsigned long i, x, y, z, t, mask, wordbuf;
30 int err;
31
32 LTC_ARGCHK(words != NULL);
33 LTC_ARGCHK(out != NULL);
34 LTC_ARGCHK(outlen != NULL);
35
36 /* check length */
37 if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) {
38 return err;
39 }
40 if (x > *outlen) {
41 *outlen = x;
42 return CRYPT_BUFFER_OVERFLOW;
43 }
44
45 /* compute length to store OID data */
46 z = 0;
47 wordbuf = words[0] * 40 + words[1];
48 for (y = 1; y < nwords; y++) {
49 t = der_object_identifier_bits(wordbuf);
50 z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
51 if (y < nwords - 1) {
52 wordbuf = words[y + 1];
53 }
54 }
55
56 /* store header + length */
57 x = 0;
58 out[x++] = 0x06;
59 y = *outlen - x;
60 if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) {
61 return err;
62 }
63 x += y;
64
65 /* store first byte */
66 wordbuf = words[0] * 40 + words[1];
67 for (i = 1; i < nwords; i++) {
68 /* store 7 bit words in little endian */
69 t = wordbuf & 0xFFFFFFFF;
70 if (t) {
71 y = x;
72 mask = 0;
73 while (t) {
74 out[x++] = (unsigned char)((t & 0x7F) | mask);
75 t >>= 7;
76 mask |= 0x80; /* upper bit is set on all but the last byte */
77 }
78 /* now swap bytes y...x-1 */
79 z = x - 1;
80 while (y < z) {
81 t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t;
82 ++y;
83 --z;
84 }
85 } else {
86 /* zero word */
87 out[x++] = 0x00;
88 }
89
90 if (i < nwords - 1) {
91 wordbuf = words[i + 1];
92 }
93 }
94
95 *outlen = x;
96 return CRYPT_OK;
97 }
98
99 #endif
100
101 /* ref: $Format:%D$ */
102 /* git commit: $Format:%H$ */
103 /* commit time: $Format:%ai$ */
104