1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_length_utf8_string.c
7   ASN.1 DER, get length of UTF8 STRING, Tom St Denis
8 */
9 
10 #ifdef LTC_DER
11 
12 /** Return the size in bytes of a UTF-8 character
13   @param c   The UTF-8 character to measure
14   @return    The size in bytes
15 */
der_utf8_charsize(const wchar_t c)16 unsigned long der_utf8_charsize(const wchar_t c)
17 {
18    if (c <= 0x7F) {
19       return 1;
20    }
21    if (c <= 0x7FF) {
22       return 2;
23    }
24 #if LTC_WCHAR_MAX == 0xFFFF
25    return 3;
26 #else
27    if (c <= 0xFFFF) {
28       return 3;
29    }
30    return 4;
31 #endif
32 }
33 
34 /**
35   Test whether the given code point is valid character
36   @param c   The UTF-8 character to test
37   @return    1 - valid, 0 - invalid
38 */
der_utf8_valid_char(const wchar_t c)39 int der_utf8_valid_char(const wchar_t c)
40 {
41    LTC_UNUSED_PARAM(c);
42 #if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF
43    if (c > 0x10FFFF) return 0;
44 #endif
45 #if LTC_WCHAR_MAX != 0xFFFF && LTC_WCHAR_MAX != 0xFFFFFFFF
46    if (c < 0) return 0;
47 #endif
48    return 1;
49 }
50 
51 /**
52   Gets length of DER encoding of UTF8 STRING
53   @param in       The characters to measure the length of
54   @param noctets  The number of octets in the string to encode
55   @param outlen   [out] The length of the DER encoding for the given string
56   @return CRYPT_OK if successful
57 */
der_length_utf8_string(const wchar_t * in,unsigned long noctets,unsigned long * outlen)58 int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen)
59 {
60    unsigned long x, len;
61    int err;
62 
63    LTC_ARGCHK(in     != NULL);
64    LTC_ARGCHK(outlen != NULL);
65 
66    len = 0;
67    for (x = 0; x < noctets; x++) {
68       if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG;
69       len += der_utf8_charsize(in[x]);
70    }
71 
72    if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
73       return err;
74    }
75    *outlen = 1 + x + len;
76 
77    return CRYPT_OK;
78 }
79 
80 #endif
81 
82