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_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 an UTF8 STRING
22 @param in The array of UTF8 to store (one per wchar_t)
23 @param inlen The number of UTF8 to store
24 @param out [out] The destination for the DER encoded UTF8 STRING
25 @param outlen [in/out] The max size and resulting size of the DER UTF8 STRING
26 @return CRYPT_OK if successful
27 */
der_encode_utf8_string(const wchar_t * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)28 int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
29 unsigned char *out, unsigned long *outlen)
30 {
31 unsigned long x, y, len;
32 int err;
33
34 LTC_ARGCHK(in != NULL);
35 LTC_ARGCHK(out != NULL);
36 LTC_ARGCHK(outlen != NULL);
37
38 /* get the size */
39 for (x = len = 0; x < inlen; x++) {
40 if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG;
41 len += der_utf8_charsize(in[x]);
42 }
43 if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
44 return err;
45 }
46 x += len + 1;
47
48 /* too big? */
49 if (x > *outlen) {
50 *outlen = x;
51 return CRYPT_BUFFER_OVERFLOW;
52 }
53
54 /* encode the header+len */
55 x = 0;
56 out[x++] = 0x0C;
57
58 y = *outlen - x;
59 if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) {
60 return err;
61 }
62 x += y;
63
64 /* store UTF8 */
65 for (y = 0; y < inlen; y++) {
66 switch (der_utf8_charsize(in[y])) {
67 case 1: out[x++] = (unsigned char)in[y]; break;
68 case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break;
69 case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break;
70 #if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF
71 case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break;
72 #endif
73 default: break;
74 }
75 }
76
77 /* return length */
78 *outlen = x;
79
80 return CRYPT_OK;
81 }
82
83 #endif
84
85 /* ref: $Format:%D$ */
86 /* git commit: $Format:%H$ */
87 /* commit time: $Format:%ai$ */
88