1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_decode_asn1_length.c
7   ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel
8 */
9 
10 #ifdef LTC_DER
11 /**
12   Decode the ASN.1 Length field
13   @param in       Where to read the length field from
14   @param inlen    [in/out] The size of in available/read
15   @param outlen   [out] The decoded ASN.1 length
16   @return CRYPT_OK if successful
17 */
der_decode_asn1_length(const unsigned char * in,unsigned long * inlen,unsigned long * outlen)18 int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen)
19 {
20    unsigned long real_len, decoded_len, offset, i;
21 
22    LTC_ARGCHK(in    != NULL);
23    LTC_ARGCHK(inlen != NULL);
24 
25    if (*inlen < 1) {
26       return CRYPT_BUFFER_OVERFLOW;
27    }
28 
29    real_len = in[0];
30 
31    if (real_len < 128) {
32       decoded_len = real_len;
33       offset = 1;
34    } else {
35       real_len &= 0x7F;
36       if (real_len == 0) {
37          return CRYPT_PK_ASN1_ERROR;
38       }
39       if (real_len > sizeof(decoded_len)) {
40          return CRYPT_OVERFLOW;
41       }
42       if (real_len > (*inlen - 1)) {
43          return CRYPT_BUFFER_OVERFLOW;
44       }
45       decoded_len = 0;
46       offset = 1 + real_len;
47       for (i = 0; i < real_len; i++) {
48          decoded_len = (decoded_len << 8) | in[1 + i];
49       }
50    }
51 
52    if (outlen != NULL) *outlen = decoded_len;
53    if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW;
54    *inlen = offset;
55 
56    return CRYPT_OK;
57 }
58 
59 #endif
60