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_decode_utf8_string.c
14 ASN.1 DER, encode a UTF8 STRING, Tom St Denis
15 */
16
17
18 #ifdef LTC_DER
19
20 /**
21 Store a UTF8 STRING
22 @param in The DER encoded UTF8 STRING
23 @param inlen The size of the DER UTF8 STRING
24 @param out [out] The array of utf8s stored (one per char)
25 @param outlen [in/out] The number of utf8s stored
26 @return CRYPT_OK if successful
27 */
der_decode_utf8_string(const unsigned char * in,unsigned long inlen,wchar_t * out,unsigned long * outlen)28 int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
29 wchar_t *out, unsigned long *outlen)
30 {
31 wchar_t tmp;
32 unsigned long x, y, z, len;
33 int err;
34
35 LTC_ARGCHK(in != NULL);
36 LTC_ARGCHK(out != NULL);
37 LTC_ARGCHK(outlen != NULL);
38
39 /* must have header at least */
40 if (inlen < 2) {
41 return CRYPT_INVALID_PACKET;
42 }
43
44 /* check for 0x0C */
45 if ((in[0] & 0x1F) != 0x0C) {
46 return CRYPT_INVALID_PACKET;
47 }
48 x = 1;
49
50 /* get the length of the data */
51 y = inlen - x;
52 if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
53 return err;
54 }
55 x += y;
56
57 if (len > (inlen - x)) {
58 return CRYPT_INVALID_PACKET;
59 }
60
61 /* proceed to decode */
62 for (y = 0; x < inlen; ) {
63 /* get first byte */
64 tmp = in[x++];
65
66 /* count number of bytes */
67 for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF);
68
69 if (z == 1 || z > 4 || (x + (z - 1) > inlen)) {
70 return CRYPT_INVALID_PACKET;
71 }
72
73 /* decode, grab upper bits */
74 tmp >>= z;
75
76 /* grab remaining bytes */
77 if (z > 1) { --z; }
78 while (z-- != 0) {
79 if ((in[x] & 0xC0) != 0x80) {
80 return CRYPT_INVALID_PACKET;
81 }
82 tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);
83 }
84
85 if (y < *outlen) {
86 out[y] = tmp;
87 }
88 y++;
89 }
90 if (y > *outlen) {
91 err = CRYPT_BUFFER_OVERFLOW;
92 } else {
93 err = CRYPT_OK;
94 }
95 *outlen = y;
96
97 return err;
98 }
99
100 #endif
101
102 /* ref: $Format:%D$ */
103 /* git commit: $Format:%H$ */
104 /* commit time: $Format:%ai$ */
105