1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 
4 #include "tomcrypt_private.h"
5 
6 #ifdef LTC_PKCS_12
7 
pkcs12_utf8_to_utf16(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)8 int pkcs12_utf8_to_utf16(const unsigned char *in,  unsigned long  inlen,
9                                unsigned char *out, unsigned long *outlen) {
10    unsigned long len = 0;
11    const unsigned char* in_end = in + inlen;
12    const ulong32 offset[6] = {
13       0x00000000UL, 0x00003080UL, 0x000E2080UL,
14       0x03C82080UL, 0xFA082080UL, 0x82082080UL
15    };
16    int err = CRYPT_ERROR;
17 
18    LTC_ARGCHK(in     != NULL);
19    LTC_ARGCHK(out    != NULL);
20    LTC_ARGCHK(outlen != NULL);
21 
22    while (in < in_end) {
23       ulong32 ch = 0;
24       unsigned short extra = 0; /* 0 */
25       if (*in >= 192) extra++;  /* 1 */
26       if (*in >= 224) extra++;  /* 2 */
27       if (*in >= 240) extra++;  /* 3 */
28       if (*in >= 248) extra++;  /* 4 */
29       if (*in >= 252) extra++;  /* 5 */
30       if (in + extra >= in_end) goto ERROR;
31       switch (extra) {
32          case 5: ch += *in++; ch <<= 6;
33          /* FALLTHROUGH */
34          case 4: ch += *in++; ch <<= 6;
35          /* FALLTHROUGH */
36          case 3: ch += *in++; ch <<= 6;
37          /* FALLTHROUGH */
38          case 2: ch += *in++; ch <<= 6;
39          /* FALLTHROUGH */
40          case 1: ch += *in++; ch <<= 6;
41          /* FALLTHROUGH */
42          case 0: ch += *in++;
43          default: break;
44       }
45       ch -= offset[extra];
46       if (ch > 0xFFFF) goto ERROR;
47       if (*outlen >= len + 2) {
48          out[len] = (unsigned short)((ch >> 8) & 0xFF);
49          out[len + 1] = (unsigned char)(ch & 0xFF);
50       }
51       len += 2;
52    }
53 
54    err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK;
55    *outlen = len;
56 ERROR:
57    return err;
58 }
59 
60 #endif
61